Mesh.java revision d4b23b54445b13dacaafad97d100999abb36ea6f
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.renderscript;
18
19import java.util.Vector;
20
21import android.util.Config;
22import android.util.Log;
23
24/**
25 * @hide
26 *
27 **/
28public class Mesh extends BaseObj {
29
30    Allocation[] mVertexBuffers;
31    Allocation[] mIndexBuffers;
32    Primitive[] mPrimitives;
33
34    Mesh(int id, RenderScript rs) {
35        super(id, rs);
36    }
37
38    public int getVertexAllocationCount() {
39        if(mVertexBuffers == null) {
40            return 0;
41        }
42        return mVertexBuffers.length;
43    }
44    public Allocation getVertexAllocation(int slot) {
45        return mVertexBuffers[slot];
46    }
47
48    public int getPrimitiveCount() {
49        if(mIndexBuffers == null) {
50            return 0;
51        }
52        return mIndexBuffers.length;
53    }
54    public Allocation getIndexAllocation(int slot) {
55        return mIndexBuffers[slot];
56    }
57    public Primitive getPrimitive(int slot) {
58        return mPrimitives[slot];
59    }
60
61    @Override
62    void updateFromNative() {
63        super.updateFromNative();
64        int vtxCount = mRS.nMeshGetVertexBufferCount(getID());
65        int idxCount = mRS.nMeshGetIndexCount(getID());
66
67        int[] vtxIDs = new int[vtxCount];
68        int[] idxIDs = new int[idxCount];
69        int[] primitives = new int[idxCount];
70
71        mRS.nMeshGetVertices(getID(), vtxIDs, vtxCount);
72        mRS.nMeshGetIndices(getID(), idxIDs, primitives, idxCount);
73
74        mVertexBuffers = new Allocation[vtxCount];
75        mIndexBuffers = new Allocation[idxCount];
76        mPrimitives = new Primitive[idxCount];
77
78        for(int i = 0; i < vtxCount; i ++) {
79            if(vtxIDs[i] != 0) {
80                mVertexBuffers[i] = new Allocation(vtxIDs[i], mRS, null, Allocation.USAGE_SCRIPT);
81                mVertexBuffers[i].updateFromNative();
82            }
83        }
84
85        for(int i = 0; i < idxCount; i ++) {
86            if(idxIDs[i] != 0) {
87                mIndexBuffers[i] = new Allocation(idxIDs[i], mRS, null, Allocation.USAGE_SCRIPT);
88                mIndexBuffers[i].updateFromNative();
89            }
90            mPrimitives[i] = Primitive.values()[primitives[i]];
91        }
92    }
93
94    public static class Builder {
95        RenderScript mRS;
96
97        class Entry {
98            Type t;
99            Element e;
100            int size;
101            Primitive prim;
102        }
103
104        int mVertexTypeCount;
105        Entry[] mVertexTypes;
106        Vector mIndexTypes;
107
108        public Builder(RenderScript rs) {
109            mRS = rs;
110            mVertexTypeCount = 0;
111            mVertexTypes = new Entry[16];
112            mIndexTypes = new Vector();
113        }
114
115        public int addVertexType(Type t) throws IllegalStateException {
116            if (mVertexTypeCount >= mVertexTypes.length) {
117                throw new IllegalStateException("Max vertex types exceeded.");
118            }
119
120            int addedIndex = mVertexTypeCount;
121            mVertexTypes[mVertexTypeCount] = new Entry();
122            mVertexTypes[mVertexTypeCount].t = t;
123            mVertexTypes[mVertexTypeCount].e = null;
124            mVertexTypeCount++;
125            return addedIndex;
126        }
127
128        public int addVertexType(Element e, int size) throws IllegalStateException {
129            if (mVertexTypeCount >= mVertexTypes.length) {
130                throw new IllegalStateException("Max vertex types exceeded.");
131            }
132
133            int addedIndex = mVertexTypeCount;
134            mVertexTypes[mVertexTypeCount] = new Entry();
135            mVertexTypes[mVertexTypeCount].t = null;
136            mVertexTypes[mVertexTypeCount].e = e;
137            mVertexTypes[mVertexTypeCount].size = size;
138            mVertexTypeCount++;
139            return addedIndex;
140        }
141
142        public int addIndexType(Type t, Primitive p) {
143            int addedIndex  = mIndexTypes.size();
144            Entry indexType = new Entry();
145            indexType.t = t;
146            indexType.e = null;
147            indexType.size = 0;
148            indexType.prim = p;
149            mIndexTypes.addElement(indexType);
150            return addedIndex;
151        }
152
153        public int addIndexType(Primitive p) {
154            int addedIndex  = mIndexTypes.size();
155            Entry indexType = new Entry();
156            indexType.t = null;
157            indexType.e = null;
158            indexType.size = 0;
159            indexType.prim = p;
160            mIndexTypes.addElement(indexType);
161            return addedIndex;
162        }
163
164        public int addIndexType(Element e, int size, Primitive p) {
165            int addedIndex  = mIndexTypes.size();
166            Entry indexType = new Entry();
167            indexType.t = null;
168            indexType.e = e;
169            indexType.size = size;
170            indexType.prim = p;
171            mIndexTypes.addElement(indexType);
172            return addedIndex;
173        }
174
175        Type newType(Element e, int size) {
176            Type.Builder tb = new Type.Builder(mRS, e);
177            tb.setX(size);
178            return tb.create();
179        }
180
181        static synchronized Mesh internalCreate(RenderScript rs, Builder b) {
182
183            int id = rs.nMeshCreate(b.mVertexTypeCount, b.mIndexTypes.size());
184            Mesh newMesh = new Mesh(id, rs);
185            newMesh.mIndexBuffers = new Allocation[b.mIndexTypes.size()];
186            newMesh.mPrimitives = new Primitive[b.mIndexTypes.size()];
187            newMesh.mVertexBuffers = new Allocation[b.mVertexTypeCount];
188
189            for(int ct = 0; ct < b.mIndexTypes.size(); ct ++) {
190                Allocation alloc = null;
191                Entry entry = (Entry)b.mIndexTypes.elementAt(ct);
192                if (entry.t != null) {
193                    alloc = Allocation.createTyped(rs, entry.t);
194                }
195                else if(entry.e != null) {
196                    alloc = Allocation.createSized(rs, entry.e, entry.size);
197                }
198                int allocID = (alloc == null) ? 0 : alloc.getID();
199                rs.nMeshBindIndex(id, allocID, entry.prim.mID, ct);
200                newMesh.mIndexBuffers[ct] = alloc;
201                newMesh.mPrimitives[ct] = entry.prim;
202            }
203
204            for(int ct = 0; ct < b.mVertexTypeCount; ct ++) {
205                Allocation alloc = null;
206                Entry entry = b.mVertexTypes[ct];
207                if (entry.t != null) {
208                    alloc = Allocation.createTyped(rs, entry.t);
209                } else if(entry.e != null) {
210                    alloc = Allocation.createSized(rs, entry.e, entry.size);
211                }
212                rs.nMeshBindVertex(id, alloc.getID(), ct);
213                newMesh.mVertexBuffers[ct] = alloc;
214            }
215            rs.nMeshInitVertexAttribs(id);
216
217            return newMesh;
218        }
219
220        public Mesh create() {
221            mRS.validate();
222            Mesh sm = internalCreate(mRS, this);
223            return sm;
224        }
225    }
226
227    public static class AllocationBuilder {
228        RenderScript mRS;
229
230        class Entry {
231            Allocation a;
232            Primitive prim;
233        }
234
235        int mVertexTypeCount;
236        Entry[] mVertexTypes;
237
238        Vector mIndexTypes;
239
240        public AllocationBuilder(RenderScript rs) {
241            mRS = rs;
242            mVertexTypeCount = 0;
243            mVertexTypes = new Entry[16];
244            mIndexTypes = new Vector();
245        }
246
247        public int addVertexAllocation(Allocation a) throws IllegalStateException {
248            if (mVertexTypeCount >= mVertexTypes.length) {
249                throw new IllegalStateException("Max vertex types exceeded.");
250            }
251
252            int addedIndex = mVertexTypeCount;
253            mVertexTypes[mVertexTypeCount] = new Entry();
254            mVertexTypes[mVertexTypeCount].a = a;
255            mVertexTypeCount++;
256            return addedIndex;
257        }
258
259        public int addIndexAllocation(Allocation a, Primitive p) {
260            int addedIndex  = mIndexTypes.size();
261            Entry indexType = new Entry();
262            indexType.a = a;
263            indexType.prim = p;
264            mIndexTypes.addElement(indexType);
265            return addedIndex;
266        }
267
268        public int addIndexType(Primitive p) {
269            int addedIndex  = mIndexTypes.size();
270            Entry indexType = new Entry();
271            indexType.a = null;
272            indexType.prim = p;
273            mIndexTypes.addElement(indexType);
274            return addedIndex;
275        }
276
277        static synchronized Mesh internalCreate(RenderScript rs, AllocationBuilder b) {
278
279            int id = rs.nMeshCreate(b.mVertexTypeCount, b.mIndexTypes.size());
280            Mesh newMesh = new Mesh(id, rs);
281            newMesh.mIndexBuffers = new Allocation[b.mIndexTypes.size()];
282            newMesh.mPrimitives = new Primitive[b.mIndexTypes.size()];
283            newMesh.mVertexBuffers = new Allocation[b.mVertexTypeCount];
284
285            for(int ct = 0; ct < b.mIndexTypes.size(); ct ++) {
286                Entry entry = (Entry)b.mIndexTypes.elementAt(ct);
287                int allocID = (entry.a == null) ? 0 : entry.a.getID();
288                rs.nMeshBindIndex(id, allocID, entry.prim.mID, ct);
289                newMesh.mIndexBuffers[ct] = entry.a;
290                newMesh.mPrimitives[ct] = entry.prim;
291            }
292
293            for(int ct = 0; ct < b.mVertexTypeCount; ct ++) {
294                Entry entry = b.mVertexTypes[ct];
295                rs.nMeshBindVertex(id, entry.a.getID(), ct);
296                newMesh.mVertexBuffers[ct] = entry.a;
297            }
298            rs.nMeshInitVertexAttribs(id);
299
300            return newMesh;
301        }
302
303        public Mesh create() {
304            mRS.validate();
305            Mesh sm = internalCreate(mRS, this);
306            return sm;
307        }
308    }
309
310
311    public static class TriangleMeshBuilder {
312        float mVtxData[];
313        int mVtxCount;
314        short mIndexData[];
315        int mIndexCount;
316        RenderScript mRS;
317        Element mElement;
318
319        float mNX = 0;
320        float mNY = 0;
321        float mNZ = -1;
322        float mS0 = 0;
323        float mT0 = 0;
324        float mR = 1;
325        float mG = 1;
326        float mB = 1;
327        float mA = 1;
328
329        int mVtxSize;
330        int mFlags;
331
332        public static final int COLOR = 0x0001;
333        public static final int NORMAL = 0x0002;
334        public static final int TEXTURE_0 = 0x0100;
335
336        public TriangleMeshBuilder(RenderScript rs, int vtxSize, int flags) {
337            mRS = rs;
338            mVtxCount = 0;
339            mIndexCount = 0;
340            mVtxData = new float[128];
341            mIndexData = new short[128];
342            mVtxSize = vtxSize;
343            mFlags = flags;
344
345            if (vtxSize < 2 || vtxSize > 3) {
346                throw new IllegalArgumentException("Vertex size out of range.");
347            }
348        }
349
350        private void makeSpace(int count) {
351            if ((mVtxCount + count) >= mVtxData.length) {
352                float t[] = new float[mVtxData.length * 2];
353                System.arraycopy(mVtxData, 0, t, 0, mVtxData.length);
354                mVtxData = t;
355            }
356        }
357
358        private void latch() {
359            if ((mFlags & COLOR) != 0) {
360                makeSpace(4);
361                mVtxData[mVtxCount++] = mR;
362                mVtxData[mVtxCount++] = mG;
363                mVtxData[mVtxCount++] = mB;
364                mVtxData[mVtxCount++] = mA;
365            }
366            if ((mFlags & TEXTURE_0) != 0) {
367                makeSpace(2);
368                mVtxData[mVtxCount++] = mS0;
369                mVtxData[mVtxCount++] = mT0;
370            }
371            if ((mFlags & NORMAL) != 0) {
372                makeSpace(3);
373                mVtxData[mVtxCount++] = mNX;
374                mVtxData[mVtxCount++] = mNY;
375                mVtxData[mVtxCount++] = mNZ;
376            }
377        }
378
379        public void addVertex(float x, float y) {
380            if (mVtxSize != 2) {
381                throw new IllegalStateException("add mistmatch with declared components.");
382            }
383            makeSpace(2);
384            mVtxData[mVtxCount++] = x;
385            mVtxData[mVtxCount++] = y;
386            latch();
387        }
388
389        public void addVertex(float x, float y, float z) {
390            if (mVtxSize != 3) {
391                throw new IllegalStateException("add mistmatch with declared components.");
392            }
393            makeSpace(3);
394            mVtxData[mVtxCount++] = x;
395            mVtxData[mVtxCount++] = y;
396            mVtxData[mVtxCount++] = z;
397            latch();
398        }
399
400        public void setTexture(float s, float t) {
401            if ((mFlags & TEXTURE_0) == 0) {
402                throw new IllegalStateException("add mistmatch with declared components.");
403            }
404            mS0 = s;
405            mT0 = t;
406        }
407
408        public void setNormal(float x, float y, float z) {
409            if ((mFlags & NORMAL) == 0) {
410                throw new IllegalStateException("add mistmatch with declared components.");
411            }
412            mNX = x;
413            mNY = y;
414            mNZ = z;
415        }
416
417        public void setColor(float r, float g, float b, float a) {
418            if ((mFlags & COLOR) == 0) {
419                throw new IllegalStateException("add mistmatch with declared components.");
420            }
421            mR = r;
422            mG = g;
423            mB = b;
424            mA = a;
425        }
426
427        public void addTriangle(int idx1, int idx2, int idx3) {
428            if((idx1 >= mVtxCount) || (idx1 < 0) ||
429               (idx2 >= mVtxCount) || (idx2 < 0) ||
430               (idx3 >= mVtxCount) || (idx3 < 0)) {
431               throw new IllegalStateException("Index provided greater than vertex count.");
432            }
433            if ((mIndexCount + 3) >= mIndexData.length) {
434                short t[] = new short[mIndexData.length * 2];
435                System.arraycopy(mIndexData, 0, t, 0, mIndexData.length);
436                mIndexData = t;
437            }
438            mIndexData[mIndexCount++] = (short)idx1;
439            mIndexData[mIndexCount++] = (short)idx2;
440            mIndexData[mIndexCount++] = (short)idx3;
441        }
442
443        public Mesh create(boolean uploadToBufferObject) {
444            Element.Builder b = new Element.Builder(mRS);
445            int floatCount = mVtxSize;
446            b.add(Element.createVector(mRS,
447                                       Element.DataType.FLOAT_32,
448                                       mVtxSize), "position");
449            if ((mFlags & COLOR) != 0) {
450                floatCount += 4;
451                b.add(Element.F32_4(mRS), "color");
452            }
453            if ((mFlags & TEXTURE_0) != 0) {
454                floatCount += 2;
455                b.add(Element.F32_2(mRS), "texture0");
456            }
457            if ((mFlags & NORMAL) != 0) {
458                floatCount += 3;
459                b.add(Element.F32_3(mRS), "normal");
460            }
461            mElement = b.create();
462
463            Builder smb = new Builder(mRS);
464            smb.addVertexType(mElement, mVtxCount / floatCount);
465            smb.addIndexType(Element.U16(mRS), mIndexCount, Primitive.TRIANGLE);
466
467            Mesh sm = smb.create();
468
469            sm.getVertexAllocation(0).copyFrom(mVtxData);
470            if(uploadToBufferObject) {
471                sm.getVertexAllocation(0).uploadToBufferObject();
472            }
473
474            sm.getIndexAllocation(0).copyFrom(mIndexData);
475            sm.getIndexAllocation(0).uploadToBufferObject();
476
477            return sm;
478        }
479    }
480}
481
482