blob: 950a91a52efbe38c83c455a6118b38481465a2bd [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) {
Alex Sakhartchouk0de94442010-08-11 14:41:28 -070035 super(id, rs);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -070036 }
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
Alex Sakhartchouk80a4c2c2010-07-12 15:50:32 -070061 @Override
62 void updateFromNative() {
Jason Sams06d69de2010-11-09 17:11:40 -080063 super.updateFromNative();
64 int vtxCount = mRS.nMeshGetVertexBufferCount(getID());
65 int idxCount = mRS.nMeshGetIndexCount(getID());
Alex Sakhartchouk80a4c2c2010-07-12 15:50:32 -070066
67 int[] vtxIDs = new int[vtxCount];
68 int[] idxIDs = new int[idxCount];
69 int[] primitives = new int[idxCount];
70
Jason Sams06d69de2010-11-09 17:11:40 -080071 mRS.nMeshGetVertices(getID(), vtxIDs, vtxCount);
72 mRS.nMeshGetIndices(getID(), idxIDs, primitives, idxCount);
Alex Sakhartchouk80a4c2c2010-07-12 15:50:32 -070073
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) {
Jason Samsd4b23b52010-12-13 15:32:35 -080080 mVertexBuffers[i] = new Allocation(vtxIDs[i], mRS, null, Allocation.USAGE_SCRIPT);
Alex Sakhartchouk80a4c2c2010-07-12 15:50:32 -070081 mVertexBuffers[i].updateFromNative();
82 }
83 }
84
85 for(int i = 0; i < idxCount; i ++) {
86 if(idxIDs[i] != 0) {
Jason Samsd4b23b52010-12-13 15:32:35 -080087 mIndexBuffers[i] = new Allocation(idxIDs[i], mRS, null, Allocation.USAGE_SCRIPT);
Alex Sakhartchouk80a4c2c2010-07-12 15:50:32 -070088 mIndexBuffers[i].updateFromNative();
89 }
90 mPrimitives[i] = Primitive.values()[primitives[i]];
91 }
92 }
93
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -070094 public static class Builder {
95 RenderScript mRS;
Jason Samsd1952402010-12-20 12:55:28 -080096 int mUsage;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -070097
98 class Entry {
99 Type t;
100 Element e;
101 int size;
102 Primitive prim;
Jason Samsd1952402010-12-20 12:55:28 -0800103 int usage;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700104 }
105
106 int mVertexTypeCount;
107 Entry[] mVertexTypes;
108 Vector mIndexTypes;
109
Jason Samsd1952402010-12-20 12:55:28 -0800110 public Builder(RenderScript rs, int usage) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700111 mRS = rs;
Jason Samsd1952402010-12-20 12:55:28 -0800112 mUsage = usage;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700113 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);
Jason Samsbf6ef8d2010-12-06 15:59:59 -0800180 tb.setX(size);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700181 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) {
Jason Samsd1952402010-12-20 12:55:28 -0800196 alloc = Allocation.createTyped(rs, entry.t, b.mUsage);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700197 }
198 else if(entry.e != null) {
Jason Samsd1952402010-12-20 12:55:28 -0800199 alloc = Allocation.createSized(rs, entry.e, entry.size, b.mUsage);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700200 }
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) {
Jason Samsd1952402010-12-20 12:55:28 -0800211 alloc = Allocation.createTyped(rs, entry.t, b.mUsage);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700212 } else if(entry.e != null) {
Jason Samsd1952402010-12-20 12:55:28 -0800213 alloc = Allocation.createSized(rs, entry.e, entry.size, b.mUsage);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700214 }
215 rs.nMeshBindVertex(id, alloc.getID(), ct);
216 newMesh.mVertexBuffers[ct] = alloc;
217 }
Alex Sakhartchouk9d71e212010-11-08 15:10:52 -0800218 rs.nMeshInitVertexAttribs(id);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700219
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];
Jason Sams06d69de2010-11-09 17:11:40 -0800298 rs.nMeshBindVertex(id, entry.a.getID(), ct);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700299 newMesh.mVertexBuffers[ct] = entry.a;
300 }
Alex Sakhartchouk9d71e212010-11-08 15:10:52 -0800301 rs.nMeshInitVertexAttribs(id);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700302
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
Jason Samsd1952402010-12-20 12:55:28 -0800466 int usage = Allocation.USAGE_SCRIPT;
467 if (uploadToBufferObject) {
468 usage |= Allocation.USAGE_GRAPHICS_VERTEX;
469 }
470
471 Builder smb = new Builder(mRS, usage);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700472 smb.addVertexType(mElement, mVtxCount / floatCount);
473 smb.addIndexType(Element.U16(mRS), mIndexCount, Primitive.TRIANGLE);
474
475 Mesh sm = smb.create();
476
Jason Samsbf6ef8d2010-12-06 15:59:59 -0800477 sm.getVertexAllocation(0).copyFrom(mVtxData);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700478 if(uploadToBufferObject) {
Jason Samsd1952402010-12-20 12:55:28 -0800479 if (uploadToBufferObject) {
480 sm.getVertexAllocation(0).syncAll(Allocation.USAGE_SCRIPT);
481 }
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700482 }
483
Jason Samsbf6ef8d2010-12-06 15:59:59 -0800484 sm.getIndexAllocation(0).copyFrom(mIndexData);
Jason Samsd1952402010-12-20 12:55:28 -0800485 if (uploadToBufferObject) {
486 sm.getIndexAllocation(0).syncAll(Allocation.USAGE_SCRIPT);
487 }
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700488
489 return sm;
490 }
491 }
492}
493