Mesh.java revision d19524047fa2d12ecd45ebcf69543836e1b45579
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        int mUsage;
97
98        class Entry {
99            Type t;
100            Element e;
101            int size;
102            Primitive prim;
103            int usage;
104        }
105
106        int mVertexTypeCount;
107        Entry[] mVertexTypes;
108        Vector mIndexTypes;
109
110        public Builder(RenderScript rs, int usage) {
111            mRS = rs;
112            mUsage = usage;
113            mVertexTypeCount = 0;
114            mVertexTypes = new Entry[16];
115            mIndexTypes = new Vector();
116        }
117
118        public int addVertexType(Type t) throws IllegalStateException {
119            if (mVertexTypeCount >= mVertexTypes.length) {
120                throw new IllegalStateException("Max vertex types exceeded.");
121            }
122
123            int addedIndex = mVertexTypeCount;
124            mVertexTypes[mVertexTypeCount] = new Entry();
125            mVertexTypes[mVertexTypeCount].t = t;
126            mVertexTypes[mVertexTypeCount].e = null;
127            mVertexTypeCount++;
128            return addedIndex;
129        }
130
131        public int addVertexType(Element e, int size) throws IllegalStateException {
132            if (mVertexTypeCount >= mVertexTypes.length) {
133                throw new IllegalStateException("Max vertex types exceeded.");
134            }
135
136            int addedIndex = mVertexTypeCount;
137            mVertexTypes[mVertexTypeCount] = new Entry();
138            mVertexTypes[mVertexTypeCount].t = null;
139            mVertexTypes[mVertexTypeCount].e = e;
140            mVertexTypes[mVertexTypeCount].size = size;
141            mVertexTypeCount++;
142            return addedIndex;
143        }
144
145        public int addIndexType(Type t, Primitive p) {
146            int addedIndex  = mIndexTypes.size();
147            Entry indexType = new Entry();
148            indexType.t = t;
149            indexType.e = null;
150            indexType.size = 0;
151            indexType.prim = p;
152            mIndexTypes.addElement(indexType);
153            return addedIndex;
154        }
155
156        public int addIndexType(Primitive p) {
157            int addedIndex  = mIndexTypes.size();
158            Entry indexType = new Entry();
159            indexType.t = null;
160            indexType.e = null;
161            indexType.size = 0;
162            indexType.prim = p;
163            mIndexTypes.addElement(indexType);
164            return addedIndex;
165        }
166
167        public int addIndexType(Element e, int size, Primitive p) {
168            int addedIndex  = mIndexTypes.size();
169            Entry indexType = new Entry();
170            indexType.t = null;
171            indexType.e = e;
172            indexType.size = size;
173            indexType.prim = p;
174            mIndexTypes.addElement(indexType);
175            return addedIndex;
176        }
177
178        Type newType(Element e, int size) {
179            Type.Builder tb = new Type.Builder(mRS, e);
180            tb.setX(size);
181            return tb.create();
182        }
183
184        static synchronized Mesh internalCreate(RenderScript rs, Builder b) {
185
186            int id = rs.nMeshCreate(b.mVertexTypeCount, b.mIndexTypes.size());
187            Mesh newMesh = new Mesh(id, rs);
188            newMesh.mIndexBuffers = new Allocation[b.mIndexTypes.size()];
189            newMesh.mPrimitives = new Primitive[b.mIndexTypes.size()];
190            newMesh.mVertexBuffers = new Allocation[b.mVertexTypeCount];
191
192            for(int ct = 0; ct < b.mIndexTypes.size(); ct ++) {
193                Allocation alloc = null;
194                Entry entry = (Entry)b.mIndexTypes.elementAt(ct);
195                if (entry.t != null) {
196                    alloc = Allocation.createTyped(rs, entry.t, b.mUsage);
197                }
198                else if(entry.e != null) {
199                    alloc = Allocation.createSized(rs, entry.e, entry.size, b.mUsage);
200                }
201                int allocID = (alloc == null) ? 0 : alloc.getID();
202                rs.nMeshBindIndex(id, allocID, entry.prim.mID, ct);
203                newMesh.mIndexBuffers[ct] = alloc;
204                newMesh.mPrimitives[ct] = entry.prim;
205            }
206
207            for(int ct = 0; ct < b.mVertexTypeCount; ct ++) {
208                Allocation alloc = null;
209                Entry entry = b.mVertexTypes[ct];
210                if (entry.t != null) {
211                    alloc = Allocation.createTyped(rs, entry.t, b.mUsage);
212                } else if(entry.e != null) {
213                    alloc = Allocation.createSized(rs, entry.e, entry.size, b.mUsage);
214                }
215                rs.nMeshBindVertex(id, alloc.getID(), ct);
216                newMesh.mVertexBuffers[ct] = alloc;
217            }
218            rs.nMeshInitVertexAttribs(id);
219
220            return newMesh;
221        }
222
223        public Mesh create() {
224            mRS.validate();
225            Mesh sm = internalCreate(mRS, this);
226            return sm;
227        }
228    }
229
230    public static class AllocationBuilder {
231        RenderScript mRS;
232
233        class Entry {
234            Allocation a;
235            Primitive prim;
236        }
237
238        int mVertexTypeCount;
239        Entry[] mVertexTypes;
240
241        Vector mIndexTypes;
242
243        public AllocationBuilder(RenderScript rs) {
244            mRS = rs;
245            mVertexTypeCount = 0;
246            mVertexTypes = new Entry[16];
247            mIndexTypes = new Vector();
248        }
249
250        public int addVertexAllocation(Allocation a) throws IllegalStateException {
251            if (mVertexTypeCount >= mVertexTypes.length) {
252                throw new IllegalStateException("Max vertex types exceeded.");
253            }
254
255            int addedIndex = mVertexTypeCount;
256            mVertexTypes[mVertexTypeCount] = new Entry();
257            mVertexTypes[mVertexTypeCount].a = a;
258            mVertexTypeCount++;
259            return addedIndex;
260        }
261
262        public int addIndexAllocation(Allocation a, Primitive p) {
263            int addedIndex  = mIndexTypes.size();
264            Entry indexType = new Entry();
265            indexType.a = a;
266            indexType.prim = p;
267            mIndexTypes.addElement(indexType);
268            return addedIndex;
269        }
270
271        public int addIndexType(Primitive p) {
272            int addedIndex  = mIndexTypes.size();
273            Entry indexType = new Entry();
274            indexType.a = null;
275            indexType.prim = p;
276            mIndexTypes.addElement(indexType);
277            return addedIndex;
278        }
279
280        static synchronized Mesh internalCreate(RenderScript rs, AllocationBuilder b) {
281
282            int id = rs.nMeshCreate(b.mVertexTypeCount, b.mIndexTypes.size());
283            Mesh newMesh = new Mesh(id, rs);
284            newMesh.mIndexBuffers = new Allocation[b.mIndexTypes.size()];
285            newMesh.mPrimitives = new Primitive[b.mIndexTypes.size()];
286            newMesh.mVertexBuffers = new Allocation[b.mVertexTypeCount];
287
288            for(int ct = 0; ct < b.mIndexTypes.size(); ct ++) {
289                Entry entry = (Entry)b.mIndexTypes.elementAt(ct);
290                int allocID = (entry.a == null) ? 0 : entry.a.getID();
291                rs.nMeshBindIndex(id, allocID, entry.prim.mID, ct);
292                newMesh.mIndexBuffers[ct] = entry.a;
293                newMesh.mPrimitives[ct] = entry.prim;
294            }
295
296            for(int ct = 0; ct < b.mVertexTypeCount; ct ++) {
297                Entry entry = b.mVertexTypes[ct];
298                rs.nMeshBindVertex(id, entry.a.getID(), ct);
299                newMesh.mVertexBuffers[ct] = entry.a;
300            }
301            rs.nMeshInitVertexAttribs(id);
302
303            return newMesh;
304        }
305
306        public Mesh create() {
307            mRS.validate();
308            Mesh sm = internalCreate(mRS, this);
309            return sm;
310        }
311    }
312
313
314    public static class TriangleMeshBuilder {
315        float mVtxData[];
316        int mVtxCount;
317        short mIndexData[];
318        int mIndexCount;
319        RenderScript mRS;
320        Element mElement;
321
322        float mNX = 0;
323        float mNY = 0;
324        float mNZ = -1;
325        float mS0 = 0;
326        float mT0 = 0;
327        float mR = 1;
328        float mG = 1;
329        float mB = 1;
330        float mA = 1;
331
332        int mVtxSize;
333        int mFlags;
334
335        public static final int COLOR = 0x0001;
336        public static final int NORMAL = 0x0002;
337        public static final int TEXTURE_0 = 0x0100;
338
339        public TriangleMeshBuilder(RenderScript rs, int vtxSize, int flags) {
340            mRS = rs;
341            mVtxCount = 0;
342            mIndexCount = 0;
343            mVtxData = new float[128];
344            mIndexData = new short[128];
345            mVtxSize = vtxSize;
346            mFlags = flags;
347
348            if (vtxSize < 2 || vtxSize > 3) {
349                throw new IllegalArgumentException("Vertex size out of range.");
350            }
351        }
352
353        private void makeSpace(int count) {
354            if ((mVtxCount + count) >= mVtxData.length) {
355                float t[] = new float[mVtxData.length * 2];
356                System.arraycopy(mVtxData, 0, t, 0, mVtxData.length);
357                mVtxData = t;
358            }
359        }
360
361        private void latch() {
362            if ((mFlags & COLOR) != 0) {
363                makeSpace(4);
364                mVtxData[mVtxCount++] = mR;
365                mVtxData[mVtxCount++] = mG;
366                mVtxData[mVtxCount++] = mB;
367                mVtxData[mVtxCount++] = mA;
368            }
369            if ((mFlags & TEXTURE_0) != 0) {
370                makeSpace(2);
371                mVtxData[mVtxCount++] = mS0;
372                mVtxData[mVtxCount++] = mT0;
373            }
374            if ((mFlags & NORMAL) != 0) {
375                makeSpace(3);
376                mVtxData[mVtxCount++] = mNX;
377                mVtxData[mVtxCount++] = mNY;
378                mVtxData[mVtxCount++] = mNZ;
379            }
380        }
381
382        public void addVertex(float x, float y) {
383            if (mVtxSize != 2) {
384                throw new IllegalStateException("add mistmatch with declared components.");
385            }
386            makeSpace(2);
387            mVtxData[mVtxCount++] = x;
388            mVtxData[mVtxCount++] = y;
389            latch();
390        }
391
392        public void addVertex(float x, float y, float z) {
393            if (mVtxSize != 3) {
394                throw new IllegalStateException("add mistmatch with declared components.");
395            }
396            makeSpace(3);
397            mVtxData[mVtxCount++] = x;
398            mVtxData[mVtxCount++] = y;
399            mVtxData[mVtxCount++] = z;
400            latch();
401        }
402
403        public void setTexture(float s, float t) {
404            if ((mFlags & TEXTURE_0) == 0) {
405                throw new IllegalStateException("add mistmatch with declared components.");
406            }
407            mS0 = s;
408            mT0 = t;
409        }
410
411        public void setNormal(float x, float y, float z) {
412            if ((mFlags & NORMAL) == 0) {
413                throw new IllegalStateException("add mistmatch with declared components.");
414            }
415            mNX = x;
416            mNY = y;
417            mNZ = z;
418        }
419
420        public void setColor(float r, float g, float b, float a) {
421            if ((mFlags & COLOR) == 0) {
422                throw new IllegalStateException("add mistmatch with declared components.");
423            }
424            mR = r;
425            mG = g;
426            mB = b;
427            mA = a;
428        }
429
430        public void addTriangle(int idx1, int idx2, int idx3) {
431            if((idx1 >= mVtxCount) || (idx1 < 0) ||
432               (idx2 >= mVtxCount) || (idx2 < 0) ||
433               (idx3 >= mVtxCount) || (idx3 < 0)) {
434               throw new IllegalStateException("Index provided greater than vertex count.");
435            }
436            if ((mIndexCount + 3) >= mIndexData.length) {
437                short t[] = new short[mIndexData.length * 2];
438                System.arraycopy(mIndexData, 0, t, 0, mIndexData.length);
439                mIndexData = t;
440            }
441            mIndexData[mIndexCount++] = (short)idx1;
442            mIndexData[mIndexCount++] = (short)idx2;
443            mIndexData[mIndexCount++] = (short)idx3;
444        }
445
446        public Mesh create(boolean uploadToBufferObject) {
447            Element.Builder b = new Element.Builder(mRS);
448            int floatCount = mVtxSize;
449            b.add(Element.createVector(mRS,
450                                       Element.DataType.FLOAT_32,
451                                       mVtxSize), "position");
452            if ((mFlags & COLOR) != 0) {
453                floatCount += 4;
454                b.add(Element.F32_4(mRS), "color");
455            }
456            if ((mFlags & TEXTURE_0) != 0) {
457                floatCount += 2;
458                b.add(Element.F32_2(mRS), "texture0");
459            }
460            if ((mFlags & NORMAL) != 0) {
461                floatCount += 3;
462                b.add(Element.F32_3(mRS), "normal");
463            }
464            mElement = b.create();
465
466            int usage = Allocation.USAGE_SCRIPT;
467            if (uploadToBufferObject) {
468                usage |= Allocation.USAGE_GRAPHICS_VERTEX;
469            }
470
471            Builder smb = new Builder(mRS, usage);
472            smb.addVertexType(mElement, mVtxCount / floatCount);
473            smb.addIndexType(Element.U16(mRS), mIndexCount, Primitive.TRIANGLE);
474
475            Mesh sm = smb.create();
476
477            sm.getVertexAllocation(0).copyFrom(mVtxData);
478            if(uploadToBufferObject) {
479                if (uploadToBufferObject) {
480                    sm.getVertexAllocation(0).syncAll(Allocation.USAGE_SCRIPT);
481                }
482            }
483
484            sm.getIndexAllocation(0).copyFrom(mIndexData);
485            if (uploadToBufferObject) {
486                sm.getIndexAllocation(0).syncAll(Allocation.USAGE_SCRIPT);
487            }
488
489            return sm;
490        }
491    }
492}
493
494