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 android.util.Config;
20import android.util.Log;
21
22/**
23 * @hide
24 *
25 **/
26public class SimpleMesh extends BaseObj {
27    Type[] mVertexTypes;
28    Type mIndexType;
29    //Type mBatcheType;
30    Primitive mPrimitive;
31
32    SimpleMesh(int id, RenderScript rs) {
33        super(rs);
34        mID = id;
35    }
36
37    public void bindVertexAllocation(Allocation a, int slot) {
38        mRS.validate();
39        mRS.nSimpleMeshBindVertex(mID, a.mID, slot);
40    }
41
42    public void bindIndexAllocation(Allocation a) {
43        mRS.validate();
44        mRS.nSimpleMeshBindIndex(mID, a.mID);
45    }
46
47    public Allocation createVertexAllocation(int slot) {
48        mRS.validate();
49        return Allocation.createTyped(mRS, mVertexTypes[slot]);
50    }
51
52    public Allocation createIndexAllocation() {
53        mRS.validate();
54        return Allocation.createTyped(mRS, mIndexType);
55    }
56
57    public Type getVertexType(int slot) {
58        return mVertexTypes[slot];
59    }
60
61    public Type getIndexType() {
62        return mIndexType;
63    }
64
65    public static class Builder {
66        RenderScript mRS;
67
68        class Entry {
69            Type t;
70            Element e;
71            int size;
72        }
73
74        int mVertexTypeCount;
75        Entry[] mVertexTypes;
76        Entry mIndexType;
77        //Entry mBatchType;
78        Primitive mPrimitive;
79
80
81        public Builder(RenderScript rs) {
82            mRS = rs;
83            mVertexTypeCount = 0;
84            mVertexTypes = new Entry[16];
85            mIndexType = new Entry();
86        }
87
88        public int addVertexType(Type t) throws IllegalStateException {
89            if (mVertexTypeCount >= mVertexTypes.length) {
90                throw new IllegalStateException("Max vertex types exceeded.");
91            }
92
93            int addedIndex = mVertexTypeCount;
94            mVertexTypes[mVertexTypeCount] = new Entry();
95            mVertexTypes[mVertexTypeCount].t = t;
96            mVertexTypeCount++;
97            return addedIndex;
98        }
99
100        public int addVertexType(Element e, int size) throws IllegalStateException {
101            if (mVertexTypeCount >= mVertexTypes.length) {
102                throw new IllegalStateException("Max vertex types exceeded.");
103            }
104
105            int addedIndex = mVertexTypeCount;
106            mVertexTypes[mVertexTypeCount] = new Entry();
107            mVertexTypes[mVertexTypeCount].e = e;
108            mVertexTypes[mVertexTypeCount].size = size;
109            mVertexTypeCount++;
110            return addedIndex;
111        }
112
113        public void setIndexType(Type t) {
114            mIndexType.t = t;
115            mIndexType.e = null;
116            mIndexType.size = 0;
117        }
118
119        public void setIndexType(Element e, int size) {
120            mIndexType.t = null;
121            mIndexType.e = e;
122            mIndexType.size = size;
123        }
124
125        public void setPrimitive(Primitive p) {
126            mPrimitive = p;
127        }
128
129
130        Type newType(Element e, int size) {
131            Type.Builder tb = new Type.Builder(mRS, e);
132            tb.add(Dimension.X, size);
133            return tb.create();
134        }
135
136        static synchronized SimpleMesh internalCreate(RenderScript rs, Builder b) {
137            Type[] toDestroy = new Type[18];
138            int toDestroyCount = 0;
139
140            int indexID = 0;
141            if (b.mIndexType.t != null) {
142                indexID = b.mIndexType.t.mID;
143            } else if (b.mIndexType.size != 0) {
144                b.mIndexType.t = b.newType(b.mIndexType.e, b.mIndexType.size);
145                indexID = b.mIndexType.t.mID;
146                toDestroy[toDestroyCount++] = b.mIndexType.t;
147            }
148
149            int[] IDs = new int[b.mVertexTypeCount];
150            for(int ct=0; ct < b.mVertexTypeCount; ct++) {
151                if (b.mVertexTypes[ct].t != null) {
152                    IDs[ct] = b.mVertexTypes[ct].t.mID;
153                } else {
154                    b.mVertexTypes[ct].t = b.newType(b.mVertexTypes[ct].e, b.mVertexTypes[ct].size);
155                    IDs[ct] = b.mVertexTypes[ct].t.mID;
156                    toDestroy[toDestroyCount++] = b.mVertexTypes[ct].t;
157                }
158            }
159
160            int id = rs.nSimpleMeshCreate(0, indexID, IDs, b.mPrimitive.mID);
161            for(int ct=0; ct < toDestroyCount; ct++) {
162                toDestroy[ct].destroy();
163            }
164
165            return new SimpleMesh(id, rs);
166        }
167
168        public SimpleMesh create() {
169            mRS.validate();
170            SimpleMesh sm = internalCreate(mRS, this);
171            sm.mVertexTypes = new Type[mVertexTypeCount];
172            for(int ct=0; ct < mVertexTypeCount; ct++) {
173                sm.mVertexTypes[ct] = mVertexTypes[ct].t;
174            }
175            sm.mIndexType = mIndexType.t;
176            sm.mPrimitive = mPrimitive;
177            return sm;
178        }
179    }
180
181    public static class TriangleMeshBuilder {
182        float mVtxData[];
183        int mVtxCount;
184        short mIndexData[];
185        int mIndexCount;
186        RenderScript mRS;
187        Element mElement;
188
189        float mNX = 0;
190        float mNY = 0;
191        float mNZ = -1;
192        float mS0 = 0;
193        float mT0 = 0;
194        float mR = 1;
195        float mG = 1;
196        float mB = 1;
197        float mA = 1;
198
199        int mVtxSize;
200        int mFlags;
201
202        public static final int COLOR = 0x0001;
203        public static final int NORMAL = 0x0002;
204        public static final int TEXTURE_0 = 0x0100;
205
206        public TriangleMeshBuilder(RenderScript rs, int vtxSize, int flags) {
207            mRS = rs;
208            mVtxCount = 0;
209            mIndexCount = 0;
210            mVtxData = new float[128];
211            mIndexData = new short[128];
212            mVtxSize = vtxSize;
213            mFlags = flags;
214
215            if (vtxSize < 2 || vtxSize > 3) {
216                throw new IllegalArgumentException("Vertex size out of range.");
217            }
218        }
219
220        private void makeSpace(int count) {
221            if ((mVtxCount + count) >= mVtxData.length) {
222                float t[] = new float[mVtxData.length * 2];
223                System.arraycopy(mVtxData, 0, t, 0, mVtxData.length);
224                mVtxData = t;
225            }
226        }
227
228        private void latch() {
229            if ((mFlags & COLOR) != 0) {
230                makeSpace(4);
231                mVtxData[mVtxCount++] = mR;
232                mVtxData[mVtxCount++] = mG;
233                mVtxData[mVtxCount++] = mB;
234                mVtxData[mVtxCount++] = mA;
235            }
236            if ((mFlags & TEXTURE_0) != 0) {
237                makeSpace(2);
238                mVtxData[mVtxCount++] = mS0;
239                mVtxData[mVtxCount++] = mT0;
240            }
241            if ((mFlags & NORMAL) != 0) {
242                makeSpace(3);
243                mVtxData[mVtxCount++] = mNX;
244                mVtxData[mVtxCount++] = mNY;
245                mVtxData[mVtxCount++] = mNZ;
246            }
247        }
248
249        public void addVertex(float x, float y) {
250            if (mVtxSize != 2) {
251                throw new IllegalStateException("add mistmatch with declared components.");
252            }
253            makeSpace(2);
254            mVtxData[mVtxCount++] = x;
255            mVtxData[mVtxCount++] = y;
256            latch();
257        }
258
259        public void addVertex(float x, float y, float z) {
260            if (mVtxSize != 3) {
261                throw new IllegalStateException("add mistmatch with declared components.");
262            }
263            makeSpace(3);
264            mVtxData[mVtxCount++] = x;
265            mVtxData[mVtxCount++] = y;
266            mVtxData[mVtxCount++] = z;
267            latch();
268        }
269
270        public void setTexture(float s, float t) {
271            if ((mFlags & TEXTURE_0) == 0) {
272                throw new IllegalStateException("add mistmatch with declared components.");
273            }
274            mS0 = s;
275            mT0 = t;
276        }
277
278        public void setNormal(float x, float y, float z) {
279            if ((mFlags & NORMAL) == 0) {
280                throw new IllegalStateException("add mistmatch with declared components.");
281            }
282            mNX = x;
283            mNY = y;
284            mNZ = z;
285        }
286
287        public void setColor(float r, float g, float b, float a) {
288            if ((mFlags & COLOR) == 0) {
289                throw new IllegalStateException("add mistmatch with declared components.");
290            }
291            mR = r;
292            mG = g;
293            mB = b;
294            mA = a;
295        }
296
297        public void addTriangle(int idx1, int idx2, int idx3) {
298            if((idx1 >= mVtxCount) || (idx1 < 0) ||
299               (idx2 >= mVtxCount) || (idx2 < 0) ||
300               (idx3 >= mVtxCount) || (idx3 < 0)) {
301               throw new IllegalStateException("Index provided greater than vertex count.");
302            }
303            if ((mIndexCount + 3) >= mIndexData.length) {
304                short t[] = new short[mIndexData.length * 2];
305                System.arraycopy(mIndexData, 0, t, 0, mIndexData.length);
306                mIndexData = t;
307            }
308            mIndexData[mIndexCount++] = (short)idx1;
309            mIndexData[mIndexCount++] = (short)idx2;
310            mIndexData[mIndexCount++] = (short)idx3;
311        }
312
313        public SimpleMesh create() {
314            Element.Builder b = new Element.Builder(mRS);
315            int floatCount = mVtxSize;
316            b.add(Element.createAttrib(mRS,
317                                       Element.DataType.FLOAT_32,
318                                       Element.DataKind.POSITION,
319                                       mVtxSize), "position");
320            if ((mFlags & COLOR) != 0) {
321                floatCount += 4;
322                b.add(Element.createAttrib(mRS,
323                                           Element.DataType.FLOAT_32,
324                                           Element.DataKind.COLOR,
325                                           4), "color");
326            }
327            if ((mFlags & TEXTURE_0) != 0) {
328                floatCount += 2;
329                b.add(Element.createAttrib(mRS,
330                                           Element.DataType.FLOAT_32,
331                                           Element.DataKind.TEXTURE,
332                                           2), "texture");
333            }
334            if ((mFlags & NORMAL) != 0) {
335                floatCount += 3;
336                b.add(Element.createAttrib(mRS,
337                                           Element.DataType.FLOAT_32,
338                                           Element.DataKind.NORMAL,
339                                           3), "normal");
340            }
341            mElement = b.create();
342
343            Builder smb = new Builder(mRS);
344            smb.addVertexType(mElement, mVtxCount / floatCount);
345            smb.setIndexType(Element.createIndex(mRS), mIndexCount);
346            smb.setPrimitive(Primitive.TRIANGLE);
347            SimpleMesh sm = smb.create();
348
349            Allocation vertexAlloc = sm.createVertexAllocation(0);
350            Allocation indexAlloc = sm.createIndexAllocation();
351            sm.bindVertexAllocation(vertexAlloc, 0);
352            sm.bindIndexAllocation(indexAlloc);
353
354            vertexAlloc.data(mVtxData);
355            vertexAlloc.uploadToBufferObject();
356
357            indexAlloc.data(mIndexData);
358            indexAlloc.uploadToBufferObject();
359
360            return sm;
361        }
362    }
363}
364
365