blob: bf02319e5fa8c08106ecc2fc97a470ec374554af [file] [log] [blame]
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -07001/*
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(rs);
36 mID = id;
37 }
38
39 public int getVertexAllocationCount() {
40 if(mVertexBuffers == null) {
41 return 0;
42 }
43 return mVertexBuffers.length;
44 }
45 public Allocation getVertexAllocation(int slot) {
46 return mVertexBuffers[slot];
47 }
48
49 public int getPrimitiveCount() {
50 if(mIndexBuffers == null) {
51 return 0;
52 }
53 return mIndexBuffers.length;
54 }
55 public Allocation getIndexAllocation(int slot) {
56 return mIndexBuffers[slot];
57 }
58 public Primitive getPrimitive(int slot) {
59 return mPrimitives[slot];
60 }
61
Alex Sakhartchouk80a4c2c2010-07-12 15:50:32 -070062 @Override
63 void updateFromNative() {
Alex Sakhartchoukfb10c162010-08-04 14:45:48 -070064 mName = mRS.nGetName(mID);
Alex Sakhartchouk80a4c2c2010-07-12 15:50:32 -070065 int vtxCount = mRS.nMeshGetVertexBufferCount(mID);
66 int idxCount = mRS.nMeshGetIndexCount(mID);
67
68 int[] vtxIDs = new int[vtxCount];
69 int[] idxIDs = new int[idxCount];
70 int[] primitives = new int[idxCount];
71
72 mRS.nMeshGetVertices(mID, vtxIDs, vtxCount);
73 mRS.nMeshGetIndices(mID, idxIDs, primitives, vtxCount);
74
75 mVertexBuffers = new Allocation[vtxCount];
76 mIndexBuffers = new Allocation[idxCount];
77 mPrimitives = new Primitive[idxCount];
78
79 for(int i = 0; i < vtxCount; i ++) {
80 if(vtxIDs[i] != 0) {
81 mVertexBuffers[i] = new Allocation(vtxIDs[i], mRS);
82 mVertexBuffers[i].updateFromNative();
83 }
84 }
85
86 for(int i = 0; i < idxCount; i ++) {
87 if(idxIDs[i] != 0) {
88 mIndexBuffers[i] = new Allocation(idxIDs[i], mRS);
89 mIndexBuffers[i].updateFromNative();
90 }
91 mPrimitives[i] = Primitive.values()[primitives[i]];
92 }
93 }
94
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -070095 public static class Builder {
96 RenderScript mRS;
97
98 class Entry {
99 Type t;
100 Element e;
101 int size;
102 Primitive prim;
103 }
104
105 int mVertexTypeCount;
106 Entry[] mVertexTypes;
107 Vector mIndexTypes;
108
109 public Builder(RenderScript rs) {
110 mRS = rs;
111 mVertexTypeCount = 0;
112 mVertexTypes = new Entry[16];
113 mIndexTypes = new Vector();
114 }
115
116 public int addVertexType(Type t) throws IllegalStateException {
117 if (mVertexTypeCount >= mVertexTypes.length) {
118 throw new IllegalStateException("Max vertex types exceeded.");
119 }
120
121 int addedIndex = mVertexTypeCount;
122 mVertexTypes[mVertexTypeCount] = new Entry();
123 mVertexTypes[mVertexTypeCount].t = t;
124 mVertexTypes[mVertexTypeCount].e = null;
125 mVertexTypeCount++;
126 return addedIndex;
127 }
128
129 public int addVertexType(Element e, int size) throws IllegalStateException {
130 if (mVertexTypeCount >= mVertexTypes.length) {
131 throw new IllegalStateException("Max vertex types exceeded.");
132 }
133
134 int addedIndex = mVertexTypeCount;
135 mVertexTypes[mVertexTypeCount] = new Entry();
136 mVertexTypes[mVertexTypeCount].t = null;
137 mVertexTypes[mVertexTypeCount].e = e;
138 mVertexTypes[mVertexTypeCount].size = size;
139 mVertexTypeCount++;
140 return addedIndex;
141 }
142
143 public int addIndexType(Type t, Primitive p) {
144 int addedIndex = mIndexTypes.size();
145 Entry indexType = new Entry();
146 indexType.t = t;
147 indexType.e = null;
148 indexType.size = 0;
149 indexType.prim = p;
150 mIndexTypes.addElement(indexType);
151 return addedIndex;
152 }
153
154 public int addIndexType(Primitive p) {
155 int addedIndex = mIndexTypes.size();
156 Entry indexType = new Entry();
157 indexType.t = null;
158 indexType.e = null;
159 indexType.size = 0;
160 indexType.prim = p;
161 mIndexTypes.addElement(indexType);
162 return addedIndex;
163 }
164
165 public int addIndexType(Element e, int size, Primitive p) {
166 int addedIndex = mIndexTypes.size();
167 Entry indexType = new Entry();
168 indexType.t = null;
169 indexType.e = e;
170 indexType.size = size;
171 indexType.prim = p;
172 mIndexTypes.addElement(indexType);
173 return addedIndex;
174 }
175
176 Type newType(Element e, int size) {
177 Type.Builder tb = new Type.Builder(mRS, e);
178 tb.add(Dimension.X, size);
179 return tb.create();
180 }
181
182 static synchronized Mesh internalCreate(RenderScript rs, Builder b) {
183
184 int id = rs.nMeshCreate(b.mVertexTypeCount, b.mIndexTypes.size());
185 Mesh newMesh = new Mesh(id, rs);
186 newMesh.mIndexBuffers = new Allocation[b.mIndexTypes.size()];
187 newMesh.mPrimitives = new Primitive[b.mIndexTypes.size()];
188 newMesh.mVertexBuffers = new Allocation[b.mVertexTypeCount];
189
190 for(int ct = 0; ct < b.mIndexTypes.size(); ct ++) {
191 Allocation alloc = null;
192 Entry entry = (Entry)b.mIndexTypes.elementAt(ct);
193 if (entry.t != null) {
194 alloc = Allocation.createTyped(rs, entry.t);
195 }
196 else if(entry.e != null) {
197 alloc = Allocation.createSized(rs, entry.e, entry.size);
198 }
199 int allocID = (alloc == null) ? 0 : alloc.getID();
200 rs.nMeshBindIndex(id, allocID, entry.prim.mID, ct);
201 newMesh.mIndexBuffers[ct] = alloc;
202 newMesh.mPrimitives[ct] = entry.prim;
203 }
204
205 for(int ct = 0; ct < b.mVertexTypeCount; ct ++) {
206 Allocation alloc = null;
207 Entry entry = b.mVertexTypes[ct];
208 if (entry.t != null) {
209 alloc = Allocation.createTyped(rs, entry.t);
210 } else if(entry.e != null) {
211 alloc = Allocation.createSized(rs, entry.e, entry.size);
212 }
213 rs.nMeshBindVertex(id, alloc.getID(), ct);
214 newMesh.mVertexBuffers[ct] = alloc;
215 }
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.mID, ct);
296 newMesh.mVertexBuffers[ct] = entry.a;
297 }
298
299 return newMesh;
300 }
301
302 public Mesh create() {
303 mRS.validate();
304 Mesh sm = internalCreate(mRS, this);
305 return sm;
306 }
307 }
308
309
310 public static class TriangleMeshBuilder {
311 float mVtxData[];
312 int mVtxCount;
313 short mIndexData[];
314 int mIndexCount;
315 RenderScript mRS;
316 Element mElement;
317
318 float mNX = 0;
319 float mNY = 0;
320 float mNZ = -1;
321 float mS0 = 0;
322 float mT0 = 0;
323 float mR = 1;
324 float mG = 1;
325 float mB = 1;
326 float mA = 1;
327
328 int mVtxSize;
329 int mFlags;
330
331 public static final int COLOR = 0x0001;
332 public static final int NORMAL = 0x0002;
333 public static final int TEXTURE_0 = 0x0100;
334
335 public TriangleMeshBuilder(RenderScript rs, int vtxSize, int flags) {
336 mRS = rs;
337 mVtxCount = 0;
338 mIndexCount = 0;
339 mVtxData = new float[128];
340 mIndexData = new short[128];
341 mVtxSize = vtxSize;
342 mFlags = flags;
343
344 if (vtxSize < 2 || vtxSize > 3) {
345 throw new IllegalArgumentException("Vertex size out of range.");
346 }
347 }
348
349 private void makeSpace(int count) {
350 if ((mVtxCount + count) >= mVtxData.length) {
351 float t[] = new float[mVtxData.length * 2];
352 System.arraycopy(mVtxData, 0, t, 0, mVtxData.length);
353 mVtxData = t;
354 }
355 }
356
357 private void latch() {
358 if ((mFlags & COLOR) != 0) {
359 makeSpace(4);
360 mVtxData[mVtxCount++] = mR;
361 mVtxData[mVtxCount++] = mG;
362 mVtxData[mVtxCount++] = mB;
363 mVtxData[mVtxCount++] = mA;
364 }
365 if ((mFlags & TEXTURE_0) != 0) {
366 makeSpace(2);
367 mVtxData[mVtxCount++] = mS0;
368 mVtxData[mVtxCount++] = mT0;
369 }
370 if ((mFlags & NORMAL) != 0) {
371 makeSpace(3);
372 mVtxData[mVtxCount++] = mNX;
373 mVtxData[mVtxCount++] = mNY;
374 mVtxData[mVtxCount++] = mNZ;
375 }
376 }
377
378 public void addVertex(float x, float y) {
379 if (mVtxSize != 2) {
380 throw new IllegalStateException("add mistmatch with declared components.");
381 }
382 makeSpace(2);
383 mVtxData[mVtxCount++] = x;
384 mVtxData[mVtxCount++] = y;
385 latch();
386 }
387
388 public void addVertex(float x, float y, float z) {
389 if (mVtxSize != 3) {
390 throw new IllegalStateException("add mistmatch with declared components.");
391 }
392 makeSpace(3);
393 mVtxData[mVtxCount++] = x;
394 mVtxData[mVtxCount++] = y;
395 mVtxData[mVtxCount++] = z;
396 latch();
397 }
398
399 public void setTexture(float s, float t) {
400 if ((mFlags & TEXTURE_0) == 0) {
401 throw new IllegalStateException("add mistmatch with declared components.");
402 }
403 mS0 = s;
404 mT0 = t;
405 }
406
407 public void setNormal(float x, float y, float z) {
408 if ((mFlags & NORMAL) == 0) {
409 throw new IllegalStateException("add mistmatch with declared components.");
410 }
411 mNX = x;
412 mNY = y;
413 mNZ = z;
414 }
415
416 public void setColor(float r, float g, float b, float a) {
417 if ((mFlags & COLOR) == 0) {
418 throw new IllegalStateException("add mistmatch with declared components.");
419 }
420 mR = r;
421 mG = g;
422 mB = b;
423 mA = a;
424 }
425
426 public void addTriangle(int idx1, int idx2, int idx3) {
427 if((idx1 >= mVtxCount) || (idx1 < 0) ||
428 (idx2 >= mVtxCount) || (idx2 < 0) ||
429 (idx3 >= mVtxCount) || (idx3 < 0)) {
430 throw new IllegalStateException("Index provided greater than vertex count.");
431 }
432 if ((mIndexCount + 3) >= mIndexData.length) {
433 short t[] = new short[mIndexData.length * 2];
434 System.arraycopy(mIndexData, 0, t, 0, mIndexData.length);
435 mIndexData = t;
436 }
437 mIndexData[mIndexCount++] = (short)idx1;
438 mIndexData[mIndexCount++] = (short)idx2;
439 mIndexData[mIndexCount++] = (short)idx3;
440 }
441
442 public Mesh create(boolean uploadToBufferObject) {
443 Element.Builder b = new Element.Builder(mRS);
444 int floatCount = mVtxSize;
445 b.add(Element.createVector(mRS,
446 Element.DataType.FLOAT_32,
447 mVtxSize), "position");
448 if ((mFlags & COLOR) != 0) {
449 floatCount += 4;
450 b.add(Element.F32_4(mRS), "color");
451 }
452 if ((mFlags & TEXTURE_0) != 0) {
453 floatCount += 2;
454 b.add(Element.F32_2(mRS), "texture0");
455 }
456 if ((mFlags & NORMAL) != 0) {
457 floatCount += 3;
458 b.add(Element.F32_3(mRS), "normal");
459 }
460 mElement = b.create();
461
462 Builder smb = new Builder(mRS);
463 smb.addVertexType(mElement, mVtxCount / floatCount);
464 smb.addIndexType(Element.U16(mRS), mIndexCount, Primitive.TRIANGLE);
465
466 Mesh sm = smb.create();
467
468 sm.getVertexAllocation(0).data(mVtxData);
469 if(uploadToBufferObject) {
470 sm.getVertexAllocation(0).uploadToBufferObject();
471 }
472
473 sm.getIndexAllocation(0).data(mIndexData);
474 sm.getIndexAllocation(0).uploadToBufferObject();
475
476 return sm;
477 }
478 }
479}
480