blob: b77fe7d459ed410c798f5b23911b0ba9bdeb6e26 [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
Alex Sakhartchoukdf272022011-01-09 11:34:03 -080026 * Mesh class is a container for geometric data displayed in
27 * renderscript.
28 *
29 * Internally, mesh is a collection of allocations that
30 * represent vertex data (positions, normals, texture
31 * coordinates) and index data such as triangles and lines.
32 *
33 * Vertex data could either be interlieved within one
34 * allocation, provided separately as multiple allocation
35 * objects or done as a combination of the above. When a
36 * vertex channel name matches an input in the vertex program,
37 * renderscript will automatically connect the two together.
38 *
39 * Parts of the mesh could be rendered with either explicit
40 * index sets or primitive types.
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -070041 *
42 **/
43public class Mesh extends BaseObj {
44
Alex Sakhartchoukdf272022011-01-09 11:34:03 -080045 /**
46 * Describes the way mesh vertex data is interpreted when rendering
47 *
48 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -080049 public enum Primitive {
50 POINT (0),
51 LINE (1),
52 LINE_STRIP (2),
53 TRIANGLE (3),
54 TRIANGLE_STRIP (4),
55 TRIANGLE_FAN (5);
56
57 int mID;
58 Primitive(int id) {
59 mID = id;
60 }
61 }
62
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -070063 Allocation[] mVertexBuffers;
64 Allocation[] mIndexBuffers;
65 Primitive[] mPrimitives;
66
67 Mesh(int id, RenderScript rs) {
Alex Sakhartchouk0de94442010-08-11 14:41:28 -070068 super(id, rs);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -070069 }
70
Alex Sakhartchoukdf272022011-01-09 11:34:03 -080071 /**
72 * @return number of allocations containing vertex data
73 *
74 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -070075 public int getVertexAllocationCount() {
76 if(mVertexBuffers == null) {
77 return 0;
78 }
79 return mVertexBuffers.length;
80 }
Alex Sakhartchoukdf272022011-01-09 11:34:03 -080081 /**
82 * @param slot index in the list of allocations to return
83 * @return vertex data allocation at the given index
84 *
85 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -070086 public Allocation getVertexAllocation(int slot) {
87 return mVertexBuffers[slot];
88 }
89
Alex Sakhartchoukdf272022011-01-09 11:34:03 -080090 /**
91 * @return number of primitives or index sets in the mesh
92 *
93 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -070094 public int getPrimitiveCount() {
95 if(mIndexBuffers == null) {
96 return 0;
97 }
98 return mIndexBuffers.length;
99 }
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800100
101 /**
102 * @param slot locaton within the list of index set allocation
103 * @return allocation containing primtive index data or null if
104 * the index data is not specified explicitly
105 *
106 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800107 public Allocation getIndexSetAllocation(int slot) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700108 return mIndexBuffers[slot];
109 }
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800110 /**
111 * @param slot locaiton within the list of index set primitives
112 * @return index set primitive type
113 *
114 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700115 public Primitive getPrimitive(int slot) {
116 return mPrimitives[slot];
117 }
118
Alex Sakhartchouk80a4c2c2010-07-12 15:50:32 -0700119 @Override
120 void updateFromNative() {
Jason Sams06d69de2010-11-09 17:11:40 -0800121 super.updateFromNative();
122 int vtxCount = mRS.nMeshGetVertexBufferCount(getID());
123 int idxCount = mRS.nMeshGetIndexCount(getID());
Alex Sakhartchouk80a4c2c2010-07-12 15:50:32 -0700124
125 int[] vtxIDs = new int[vtxCount];
126 int[] idxIDs = new int[idxCount];
127 int[] primitives = new int[idxCount];
128
Jason Sams06d69de2010-11-09 17:11:40 -0800129 mRS.nMeshGetVertices(getID(), vtxIDs, vtxCount);
130 mRS.nMeshGetIndices(getID(), idxIDs, primitives, idxCount);
Alex Sakhartchouk80a4c2c2010-07-12 15:50:32 -0700131
132 mVertexBuffers = new Allocation[vtxCount];
133 mIndexBuffers = new Allocation[idxCount];
134 mPrimitives = new Primitive[idxCount];
135
136 for(int i = 0; i < vtxCount; i ++) {
137 if(vtxIDs[i] != 0) {
Jason Samsd4b23b52010-12-13 15:32:35 -0800138 mVertexBuffers[i] = new Allocation(vtxIDs[i], mRS, null, Allocation.USAGE_SCRIPT);
Alex Sakhartchouk80a4c2c2010-07-12 15:50:32 -0700139 mVertexBuffers[i].updateFromNative();
140 }
141 }
142
143 for(int i = 0; i < idxCount; i ++) {
144 if(idxIDs[i] != 0) {
Jason Samsd4b23b52010-12-13 15:32:35 -0800145 mIndexBuffers[i] = new Allocation(idxIDs[i], mRS, null, Allocation.USAGE_SCRIPT);
Alex Sakhartchouk80a4c2c2010-07-12 15:50:32 -0700146 mIndexBuffers[i].updateFromNative();
147 }
148 mPrimitives[i] = Primitive.values()[primitives[i]];
149 }
150 }
151
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800152 /**
153 * Mesh builder object. It starts empty and requires the user to
154 * add the types necessary to create vertex and index
155 * allocations
156 *
157 */
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700158 public static class Builder {
159 RenderScript mRS;
Jason Samsd1952402010-12-20 12:55:28 -0800160 int mUsage;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700161
162 class Entry {
163 Type t;
164 Element e;
165 int size;
166 Primitive prim;
Jason Samsd1952402010-12-20 12:55:28 -0800167 int usage;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700168 }
169
170 int mVertexTypeCount;
171 Entry[] mVertexTypes;
172 Vector mIndexTypes;
173
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800174 /**
175 * Creates builder object
176 * @param rs
177 * @param usage specifies how the mesh allocations are to be
178 * handled, whether they need to be uploaded to a
179 * buffer on the gpu, maintain a cpu copy, etc
180 */
Jason Samsd1952402010-12-20 12:55:28 -0800181 public Builder(RenderScript rs, int usage) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700182 mRS = rs;
Jason Samsd1952402010-12-20 12:55:28 -0800183 mUsage = usage;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700184 mVertexTypeCount = 0;
185 mVertexTypes = new Entry[16];
186 mIndexTypes = new Vector();
187 }
188
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800189 /**
190 * @return internal index of the last vertex buffer type added to
191 * builder
192 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800193 public int getCurrentVertexTypeIndex() {
194 return mVertexTypeCount - 1;
195 }
196
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800197 /**
198 * @return internal index of the last index set added to the
199 * builder
200 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800201 public int getCurrentIndexSetIndex() {
202 return mIndexTypes.size() - 1;
203 }
204
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800205 /**
206 * Adds a vertex data type to the builder object
207 *
208 * @param r type of the vertex data allocation to be created
209 *
210 * @return this
211 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800212 public Builder addVertexType(Type t) throws IllegalStateException {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700213 if (mVertexTypeCount >= mVertexTypes.length) {
214 throw new IllegalStateException("Max vertex types exceeded.");
215 }
216
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700217 mVertexTypes[mVertexTypeCount] = new Entry();
218 mVertexTypes[mVertexTypeCount].t = t;
219 mVertexTypes[mVertexTypeCount].e = null;
220 mVertexTypeCount++;
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800221 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700222 }
223
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800224 /**
225 * Adds a vertex data type to the builder object
226 *
227 * @param e element describing the vertex data layout
228 * @param size number of elements in the buffer
229 *
230 * @return this
231 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800232 public Builder addVertexType(Element e, int size) throws IllegalStateException {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700233 if (mVertexTypeCount >= mVertexTypes.length) {
234 throw new IllegalStateException("Max vertex types exceeded.");
235 }
236
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700237 mVertexTypes[mVertexTypeCount] = new Entry();
238 mVertexTypes[mVertexTypeCount].t = null;
239 mVertexTypes[mVertexTypeCount].e = e;
240 mVertexTypes[mVertexTypeCount].size = size;
241 mVertexTypeCount++;
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800242 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700243 }
244
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800245 /**
246 * Adds an index set data type to the builder object
247 *
248 * @param t type of the index set data, could be null
249 * @param p primitive type
250 *
251 * @return this
252 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800253 public Builder addIndexSetType(Type t, Primitive p) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700254 Entry indexType = new Entry();
255 indexType.t = t;
256 indexType.e = null;
257 indexType.size = 0;
258 indexType.prim = p;
259 mIndexTypes.addElement(indexType);
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800260 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700261 }
262
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800263 /**
264 * Adds an index set primitive type to the builder object
265 *
266 * @param p primitive type
267 *
268 * @return this
269 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800270 public Builder addIndexSetType(Primitive p) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700271 Entry indexType = new Entry();
272 indexType.t = null;
273 indexType.e = null;
274 indexType.size = 0;
275 indexType.prim = p;
276 mIndexTypes.addElement(indexType);
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800277 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700278 }
279
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800280 /**
281 * Adds an index set data type to the builder object
282 *
283 * @param e element describing the index set data layout
284 * @param size number of elements in the buffer
285 * @param p primitive type
286 *
287 * @return this
288 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800289 public Builder addIndexSetType(Element e, int size, Primitive p) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700290 Entry indexType = new Entry();
291 indexType.t = null;
292 indexType.e = e;
293 indexType.size = size;
294 indexType.prim = p;
295 mIndexTypes.addElement(indexType);
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800296 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700297 }
298
299 Type newType(Element e, int size) {
300 Type.Builder tb = new Type.Builder(mRS, e);
Jason Samsbf6ef8d2010-12-06 15:59:59 -0800301 tb.setX(size);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700302 return tb.create();
303 }
304
305 static synchronized Mesh internalCreate(RenderScript rs, Builder b) {
306
307 int id = rs.nMeshCreate(b.mVertexTypeCount, b.mIndexTypes.size());
308 Mesh newMesh = new Mesh(id, rs);
309 newMesh.mIndexBuffers = new Allocation[b.mIndexTypes.size()];
310 newMesh.mPrimitives = new Primitive[b.mIndexTypes.size()];
311 newMesh.mVertexBuffers = new Allocation[b.mVertexTypeCount];
312
313 for(int ct = 0; ct < b.mIndexTypes.size(); ct ++) {
314 Allocation alloc = null;
315 Entry entry = (Entry)b.mIndexTypes.elementAt(ct);
316 if (entry.t != null) {
Jason Samsd1952402010-12-20 12:55:28 -0800317 alloc = Allocation.createTyped(rs, entry.t, b.mUsage);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700318 }
319 else if(entry.e != null) {
Jason Samsd1952402010-12-20 12:55:28 -0800320 alloc = Allocation.createSized(rs, entry.e, entry.size, b.mUsage);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700321 }
322 int allocID = (alloc == null) ? 0 : alloc.getID();
323 rs.nMeshBindIndex(id, allocID, entry.prim.mID, ct);
324 newMesh.mIndexBuffers[ct] = alloc;
325 newMesh.mPrimitives[ct] = entry.prim;
326 }
327
328 for(int ct = 0; ct < b.mVertexTypeCount; ct ++) {
329 Allocation alloc = null;
330 Entry entry = b.mVertexTypes[ct];
331 if (entry.t != null) {
Jason Samsd1952402010-12-20 12:55:28 -0800332 alloc = Allocation.createTyped(rs, entry.t, b.mUsage);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700333 } else if(entry.e != null) {
Jason Samsd1952402010-12-20 12:55:28 -0800334 alloc = Allocation.createSized(rs, entry.e, entry.size, b.mUsage);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700335 }
336 rs.nMeshBindVertex(id, alloc.getID(), ct);
337 newMesh.mVertexBuffers[ct] = alloc;
338 }
Alex Sakhartchouk9d71e212010-11-08 15:10:52 -0800339 rs.nMeshInitVertexAttribs(id);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700340
341 return newMesh;
342 }
343
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800344 /**
345 * Create a Mesh object from the current state of the builder
346 *
347 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700348 public Mesh create() {
349 mRS.validate();
350 Mesh sm = internalCreate(mRS, this);
351 return sm;
352 }
353 }
354
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800355 /**
356 * Mesh builder object. It starts empty and requires the user to
357 * add all the vertex and index allocations that comprise the
358 * mesh
359 *
360 */
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700361 public static class AllocationBuilder {
362 RenderScript mRS;
363
364 class Entry {
365 Allocation a;
366 Primitive prim;
367 }
368
369 int mVertexTypeCount;
370 Entry[] mVertexTypes;
371
372 Vector mIndexTypes;
373
374 public AllocationBuilder(RenderScript rs) {
375 mRS = rs;
376 mVertexTypeCount = 0;
377 mVertexTypes = new Entry[16];
378 mIndexTypes = new Vector();
379 }
380
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800381 /**
382 * @return internal index of the last vertex buffer type added to
383 * builder
384 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800385 public int getCurrentVertexTypeIndex() {
386 return mVertexTypeCount - 1;
387 }
388
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800389 /**
390 * @return internal index of the last index set added to the
391 * builder
392 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800393 public int getCurrentIndexSetIndex() {
394 return mIndexTypes.size() - 1;
395 }
396
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800397 /**
398 * Adds an allocation containing vertex buffer data to the
399 * builder
400 *
401 * @param a vertex data allocation
402 *
403 * @return this
404 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800405 public AllocationBuilder addVertexAllocation(Allocation a) throws IllegalStateException {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700406 if (mVertexTypeCount >= mVertexTypes.length) {
407 throw new IllegalStateException("Max vertex types exceeded.");
408 }
409
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700410 mVertexTypes[mVertexTypeCount] = new Entry();
411 mVertexTypes[mVertexTypeCount].a = a;
412 mVertexTypeCount++;
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800413 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700414 }
415
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800416 /**
417 * Adds an allocation containing index buffer data and index type
418 * to the builder
419 *
420 * @param a index set data allocation, could be null
421 * @param p index set primitive type
422 *
423 * @return this
424 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800425 public AllocationBuilder addIndexSetAllocation(Allocation a, Primitive p) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700426 Entry indexType = new Entry();
427 indexType.a = a;
428 indexType.prim = p;
429 mIndexTypes.addElement(indexType);
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800430 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700431 }
432
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800433 /**
434 * Adds an index set type to the builder
435 *
436 * @param p index set primitive type
437 *
438 * @return this
439 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800440 public AllocationBuilder addIndexSetType(Primitive p) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700441 Entry indexType = new Entry();
442 indexType.a = null;
443 indexType.prim = p;
444 mIndexTypes.addElement(indexType);
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800445 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700446 }
447
448 static synchronized Mesh internalCreate(RenderScript rs, AllocationBuilder b) {
449
450 int id = rs.nMeshCreate(b.mVertexTypeCount, b.mIndexTypes.size());
451 Mesh newMesh = new Mesh(id, rs);
452 newMesh.mIndexBuffers = new Allocation[b.mIndexTypes.size()];
453 newMesh.mPrimitives = new Primitive[b.mIndexTypes.size()];
454 newMesh.mVertexBuffers = new Allocation[b.mVertexTypeCount];
455
456 for(int ct = 0; ct < b.mIndexTypes.size(); ct ++) {
457 Entry entry = (Entry)b.mIndexTypes.elementAt(ct);
458 int allocID = (entry.a == null) ? 0 : entry.a.getID();
459 rs.nMeshBindIndex(id, allocID, entry.prim.mID, ct);
460 newMesh.mIndexBuffers[ct] = entry.a;
461 newMesh.mPrimitives[ct] = entry.prim;
462 }
463
464 for(int ct = 0; ct < b.mVertexTypeCount; ct ++) {
465 Entry entry = b.mVertexTypes[ct];
Jason Sams06d69de2010-11-09 17:11:40 -0800466 rs.nMeshBindVertex(id, entry.a.getID(), ct);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700467 newMesh.mVertexBuffers[ct] = entry.a;
468 }
Alex Sakhartchouk9d71e212010-11-08 15:10:52 -0800469 rs.nMeshInitVertexAttribs(id);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700470
471 return newMesh;
472 }
473
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800474 /**
475 * Create a Mesh object from the current state of the builder
476 *
477 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700478 public Mesh create() {
479 mRS.validate();
480 Mesh sm = internalCreate(mRS, this);
481 return sm;
482 }
483 }
484
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800485 /**
486 * Builder that allows creation of a mesh object point by point
487 * and triangle by triangle
488 *
489 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700490 public static class TriangleMeshBuilder {
491 float mVtxData[];
492 int mVtxCount;
493 short mIndexData[];
494 int mIndexCount;
495 RenderScript mRS;
496 Element mElement;
497
498 float mNX = 0;
499 float mNY = 0;
500 float mNZ = -1;
501 float mS0 = 0;
502 float mT0 = 0;
503 float mR = 1;
504 float mG = 1;
505 float mB = 1;
506 float mA = 1;
507
508 int mVtxSize;
509 int mFlags;
510
511 public static final int COLOR = 0x0001;
512 public static final int NORMAL = 0x0002;
513 public static final int TEXTURE_0 = 0x0100;
514
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800515 /**
516 * @param rs
517 * @param vtxSize specifies whether the vertex is a float2 or
518 * float3
519 * @param flags bitfield that is a combination of COLOR, NORMAL,
520 * and TEXTURE_0 that specifies what vertex data
521 * channels are present in the mesh
522 *
523 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700524 public TriangleMeshBuilder(RenderScript rs, int vtxSize, int flags) {
525 mRS = rs;
526 mVtxCount = 0;
527 mIndexCount = 0;
528 mVtxData = new float[128];
529 mIndexData = new short[128];
530 mVtxSize = vtxSize;
531 mFlags = flags;
532
533 if (vtxSize < 2 || vtxSize > 3) {
534 throw new IllegalArgumentException("Vertex size out of range.");
535 }
536 }
537
538 private void makeSpace(int count) {
539 if ((mVtxCount + count) >= mVtxData.length) {
540 float t[] = new float[mVtxData.length * 2];
541 System.arraycopy(mVtxData, 0, t, 0, mVtxData.length);
542 mVtxData = t;
543 }
544 }
545
546 private void latch() {
547 if ((mFlags & COLOR) != 0) {
548 makeSpace(4);
549 mVtxData[mVtxCount++] = mR;
550 mVtxData[mVtxCount++] = mG;
551 mVtxData[mVtxCount++] = mB;
552 mVtxData[mVtxCount++] = mA;
553 }
554 if ((mFlags & TEXTURE_0) != 0) {
555 makeSpace(2);
556 mVtxData[mVtxCount++] = mS0;
557 mVtxData[mVtxCount++] = mT0;
558 }
559 if ((mFlags & NORMAL) != 0) {
560 makeSpace(3);
561 mVtxData[mVtxCount++] = mNX;
562 mVtxData[mVtxCount++] = mNY;
563 mVtxData[mVtxCount++] = mNZ;
564 }
565 }
566
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800567 /**
568 * Adds a float2 vertex to the mesh
569 *
570 * @param x position x
571 * @param y position y
572 *
573 * @return this
574 *
575 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800576 public TriangleMeshBuilder addVertex(float x, float y) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700577 if (mVtxSize != 2) {
578 throw new IllegalStateException("add mistmatch with declared components.");
579 }
580 makeSpace(2);
581 mVtxData[mVtxCount++] = x;
582 mVtxData[mVtxCount++] = y;
583 latch();
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800584 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700585 }
586
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800587 /**
588 * Adds a float3 vertex to the mesh
589 *
590 * @param x position x
591 * @param y position y
592 * @param z position z
593 *
594 * @return this
595 *
596 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800597 public TriangleMeshBuilder addVertex(float x, float y, float z) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700598 if (mVtxSize != 3) {
599 throw new IllegalStateException("add mistmatch with declared components.");
600 }
601 makeSpace(3);
602 mVtxData[mVtxCount++] = x;
603 mVtxData[mVtxCount++] = y;
604 mVtxData[mVtxCount++] = z;
605 latch();
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800606 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700607 }
608
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800609 /**
610 * Sets the texture coordinate for the last added vertex
611 *
612 * @param s texture coordinate s
613 * @param t texture coordinate t
614 *
615 * @return this
616 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800617 public TriangleMeshBuilder setTexture(float s, float t) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700618 if ((mFlags & TEXTURE_0) == 0) {
619 throw new IllegalStateException("add mistmatch with declared components.");
620 }
621 mS0 = s;
622 mT0 = t;
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800623 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700624 }
625
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800626 /**
627 * Sets the normal vector for the last added vertex
628 *
629 * @param x normal vector x
630 * @param y normal vector y
631 * @param z normal vector z
632 *
633 * @return this
634 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800635 public TriangleMeshBuilder setNormal(float x, float y, float z) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700636 if ((mFlags & NORMAL) == 0) {
637 throw new IllegalStateException("add mistmatch with declared components.");
638 }
639 mNX = x;
640 mNY = y;
641 mNZ = z;
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800642 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700643 }
644
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800645 /**
646 * Sets the color for the last added vertex
647 *
648 * @param r red component
649 * @param g green component
650 * @param b blue component
651 * @param a alpha component
652 *
653 * @return this
654 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800655 public TriangleMeshBuilder setColor(float r, float g, float b, float a) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700656 if ((mFlags & COLOR) == 0) {
657 throw new IllegalStateException("add mistmatch with declared components.");
658 }
659 mR = r;
660 mG = g;
661 mB = b;
662 mA = a;
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800663 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700664 }
665
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800666 /**
667 * Adds a new triangle to the mesh builder
668 *
669 * @param idx1 index of the first vertex in the triangle
670 * @param idx2 index of the second vertex in the triangle
671 * @param idx3 index of the third vertex in the triangle
672 *
673 * @return this
674 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800675 public TriangleMeshBuilder addTriangle(int idx1, int idx2, int idx3) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700676 if((idx1 >= mVtxCount) || (idx1 < 0) ||
677 (idx2 >= mVtxCount) || (idx2 < 0) ||
678 (idx3 >= mVtxCount) || (idx3 < 0)) {
679 throw new IllegalStateException("Index provided greater than vertex count.");
680 }
681 if ((mIndexCount + 3) >= mIndexData.length) {
682 short t[] = new short[mIndexData.length * 2];
683 System.arraycopy(mIndexData, 0, t, 0, mIndexData.length);
684 mIndexData = t;
685 }
686 mIndexData[mIndexCount++] = (short)idx1;
687 mIndexData[mIndexCount++] = (short)idx2;
688 mIndexData[mIndexCount++] = (short)idx3;
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800689 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700690 }
691
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800692 /**
693 * Creates the mesh object from the current state of the builder
694 *
695 * @param uploadToBufferObject specifies whether the vertex data
696 * is to be uploaded into the buffer
697 * object indicating that it's likely
698 * not going to be modified and
699 * rendered many times.
700 * Alternatively, it indicates the
701 * mesh data will be updated
702 * frequently and remain in script
703 * accessible memory
704 *
705 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700706 public Mesh create(boolean uploadToBufferObject) {
707 Element.Builder b = new Element.Builder(mRS);
708 int floatCount = mVtxSize;
709 b.add(Element.createVector(mRS,
710 Element.DataType.FLOAT_32,
711 mVtxSize), "position");
712 if ((mFlags & COLOR) != 0) {
713 floatCount += 4;
714 b.add(Element.F32_4(mRS), "color");
715 }
716 if ((mFlags & TEXTURE_0) != 0) {
717 floatCount += 2;
718 b.add(Element.F32_2(mRS), "texture0");
719 }
720 if ((mFlags & NORMAL) != 0) {
721 floatCount += 3;
722 b.add(Element.F32_3(mRS), "normal");
723 }
724 mElement = b.create();
725
Jason Samsd1952402010-12-20 12:55:28 -0800726 int usage = Allocation.USAGE_SCRIPT;
727 if (uploadToBufferObject) {
728 usage |= Allocation.USAGE_GRAPHICS_VERTEX;
729 }
730
731 Builder smb = new Builder(mRS, usage);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700732 smb.addVertexType(mElement, mVtxCount / floatCount);
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800733 smb.addIndexSetType(Element.U16(mRS), mIndexCount, Primitive.TRIANGLE);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700734
735 Mesh sm = smb.create();
736
Jason Samsbf6ef8d2010-12-06 15:59:59 -0800737 sm.getVertexAllocation(0).copyFrom(mVtxData);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700738 if(uploadToBufferObject) {
Jason Samsd1952402010-12-20 12:55:28 -0800739 if (uploadToBufferObject) {
740 sm.getVertexAllocation(0).syncAll(Allocation.USAGE_SCRIPT);
741 }
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700742 }
743
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800744 sm.getIndexSetAllocation(0).copyFrom(mIndexData);
Jason Samsd1952402010-12-20 12:55:28 -0800745 if (uploadToBufferObject) {
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800746 sm.getIndexSetAllocation(0).syncAll(Allocation.USAGE_SCRIPT);
Jason Samsd1952402010-12-20 12:55:28 -0800747 }
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700748
749 return sm;
750 }
751 }
752}
753