blob: 43e04962ec41733fa77b69d464221df1f9246113 [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/**
Alex Sakhartchoukdf272022011-01-09 11:34:03 -080025 * Mesh class is a container for geometric data displayed in
26 * renderscript.
27 *
28 * Internally, mesh is a collection of allocations that
29 * represent vertex data (positions, normals, texture
30 * coordinates) and index data such as triangles and lines.
31 *
32 * Vertex data could either be interlieved within one
33 * allocation, provided separately as multiple allocation
34 * objects or done as a combination of the above. When a
35 * vertex channel name matches an input in the vertex program,
36 * renderscript will automatically connect the two together.
37 *
38 * Parts of the mesh could be rendered with either explicit
39 * index sets or primitive types.
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -070040 *
41 **/
42public class Mesh extends BaseObj {
43
Alex Sakhartchoukdf272022011-01-09 11:34:03 -080044 /**
45 * Describes the way mesh vertex data is interpreted when rendering
46 *
47 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -080048 public enum Primitive {
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -080049 /**
50 * Vertex data will be rendered as a series of points
51 */
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -080052 POINT (0),
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -080053 /**
54 * Vertex pairs will be rendered as lines
55 */
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -080056 LINE (1),
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -080057 /**
58 * Vertex data will be rendered as a connected line strip
59 */
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -080060 LINE_STRIP (2),
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -080061 /**
62 * Vertices will be rendered as individual triangles
63 */
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -080064 TRIANGLE (3),
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -080065 /**
66 * Vertices will be rendered as a connected triangle strip
67 * defined by the first three vertices with each additional
68 * triangle defined by a new vertex
69 */
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -080070 TRIANGLE_STRIP (4),
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -080071 /**
72 * Vertices will be rendered as a sequence of triangles that all
73 * share first vertex as the origin
74 */
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -080075 TRIANGLE_FAN (5);
76
77 int mID;
78 Primitive(int id) {
79 mID = id;
80 }
81 }
82
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -070083 Allocation[] mVertexBuffers;
84 Allocation[] mIndexBuffers;
85 Primitive[] mPrimitives;
86
87 Mesh(int id, RenderScript rs) {
Alex Sakhartchouk0de94442010-08-11 14:41:28 -070088 super(id, rs);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -070089 }
90
Alex Sakhartchoukdf272022011-01-09 11:34:03 -080091 /**
92 * @return number of allocations containing vertex data
93 *
94 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -070095 public int getVertexAllocationCount() {
96 if(mVertexBuffers == null) {
97 return 0;
98 }
99 return mVertexBuffers.length;
100 }
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800101 /**
102 * @param slot index in the list of allocations to return
103 * @return vertex data allocation at the given index
104 *
105 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700106 public Allocation getVertexAllocation(int slot) {
107 return mVertexBuffers[slot];
108 }
109
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800110 /**
111 * @return number of primitives or index sets in the mesh
112 *
113 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700114 public int getPrimitiveCount() {
115 if(mIndexBuffers == null) {
116 return 0;
117 }
118 return mIndexBuffers.length;
119 }
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800120
121 /**
122 * @param slot locaton within the list of index set allocation
123 * @return allocation containing primtive index data or null if
124 * the index data is not specified explicitly
125 *
126 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800127 public Allocation getIndexSetAllocation(int slot) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700128 return mIndexBuffers[slot];
129 }
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800130 /**
131 * @param slot locaiton within the list of index set primitives
132 * @return index set primitive type
133 *
134 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700135 public Primitive getPrimitive(int slot) {
136 return mPrimitives[slot];
137 }
138
Alex Sakhartchouk80a4c2c2010-07-12 15:50:32 -0700139 @Override
140 void updateFromNative() {
Jason Sams06d69de2010-11-09 17:11:40 -0800141 super.updateFromNative();
142 int vtxCount = mRS.nMeshGetVertexBufferCount(getID());
143 int idxCount = mRS.nMeshGetIndexCount(getID());
Alex Sakhartchouk80a4c2c2010-07-12 15:50:32 -0700144
145 int[] vtxIDs = new int[vtxCount];
146 int[] idxIDs = new int[idxCount];
147 int[] primitives = new int[idxCount];
148
Jason Sams06d69de2010-11-09 17:11:40 -0800149 mRS.nMeshGetVertices(getID(), vtxIDs, vtxCount);
150 mRS.nMeshGetIndices(getID(), idxIDs, primitives, idxCount);
Alex Sakhartchouk80a4c2c2010-07-12 15:50:32 -0700151
152 mVertexBuffers = new Allocation[vtxCount];
153 mIndexBuffers = new Allocation[idxCount];
154 mPrimitives = new Primitive[idxCount];
155
156 for(int i = 0; i < vtxCount; i ++) {
157 if(vtxIDs[i] != 0) {
Jason Samsd4b23b52010-12-13 15:32:35 -0800158 mVertexBuffers[i] = new Allocation(vtxIDs[i], mRS, null, Allocation.USAGE_SCRIPT);
Alex Sakhartchouk80a4c2c2010-07-12 15:50:32 -0700159 mVertexBuffers[i].updateFromNative();
160 }
161 }
162
163 for(int i = 0; i < idxCount; i ++) {
164 if(idxIDs[i] != 0) {
Jason Samsd4b23b52010-12-13 15:32:35 -0800165 mIndexBuffers[i] = new Allocation(idxIDs[i], mRS, null, Allocation.USAGE_SCRIPT);
Alex Sakhartchouk80a4c2c2010-07-12 15:50:32 -0700166 mIndexBuffers[i].updateFromNative();
167 }
168 mPrimitives[i] = Primitive.values()[primitives[i]];
169 }
170 }
171
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800172 /**
173 * Mesh builder object. It starts empty and requires the user to
174 * add the types necessary to create vertex and index
175 * allocations
176 *
177 */
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700178 public static class Builder {
179 RenderScript mRS;
Jason Samsd1952402010-12-20 12:55:28 -0800180 int mUsage;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700181
182 class Entry {
183 Type t;
184 Element e;
185 int size;
186 Primitive prim;
Jason Samsd1952402010-12-20 12:55:28 -0800187 int usage;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700188 }
189
190 int mVertexTypeCount;
191 Entry[] mVertexTypes;
192 Vector mIndexTypes;
193
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800194 /**
195 * Creates builder object
Alex Sakhartchoukf5c876e2011-01-13 14:53:43 -0800196 * @param rs Context to which the mesh will belong.
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800197 * @param usage specifies how the mesh allocations are to be
198 * handled, whether they need to be uploaded to a
199 * buffer on the gpu, maintain a cpu copy, etc
200 */
Jason Samsd1952402010-12-20 12:55:28 -0800201 public Builder(RenderScript rs, int usage) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700202 mRS = rs;
Jason Samsd1952402010-12-20 12:55:28 -0800203 mUsage = usage;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700204 mVertexTypeCount = 0;
205 mVertexTypes = new Entry[16];
206 mIndexTypes = new Vector();
207 }
208
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800209 /**
210 * @return internal index of the last vertex buffer type added to
211 * builder
212 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800213 public int getCurrentVertexTypeIndex() {
214 return mVertexTypeCount - 1;
215 }
216
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800217 /**
218 * @return internal index of the last index set added to the
219 * builder
220 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800221 public int getCurrentIndexSetIndex() {
222 return mIndexTypes.size() - 1;
223 }
224
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800225 /**
226 * Adds a vertex data type to the builder object
227 *
Stephen Hinesb11e3d22011-01-11 19:30:58 -0800228 * @param t type of the vertex data allocation to be created
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800229 *
230 * @return this
231 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800232 public Builder addVertexType(Type t) 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 = t;
239 mVertexTypes[mVertexTypeCount].e = null;
240 mVertexTypeCount++;
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800241 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700242 }
243
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800244 /**
245 * Adds a vertex data type to the builder object
246 *
247 * @param e element describing the vertex data layout
248 * @param size number of elements in the buffer
249 *
250 * @return this
251 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800252 public Builder addVertexType(Element e, int size) throws IllegalStateException {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700253 if (mVertexTypeCount >= mVertexTypes.length) {
254 throw new IllegalStateException("Max vertex types exceeded.");
255 }
256
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700257 mVertexTypes[mVertexTypeCount] = new Entry();
258 mVertexTypes[mVertexTypeCount].t = null;
259 mVertexTypes[mVertexTypeCount].e = e;
260 mVertexTypes[mVertexTypeCount].size = size;
261 mVertexTypeCount++;
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800262 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700263 }
264
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800265 /**
266 * Adds an index set data type to the builder object
267 *
268 * @param t type of the index set data, could be null
269 * @param p primitive type
270 *
271 * @return this
272 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800273 public Builder addIndexSetType(Type t, Primitive p) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700274 Entry indexType = new Entry();
275 indexType.t = t;
276 indexType.e = null;
277 indexType.size = 0;
278 indexType.prim = p;
279 mIndexTypes.addElement(indexType);
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800280 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700281 }
282
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800283 /**
284 * Adds an index set primitive type to the builder object
285 *
286 * @param p primitive type
287 *
288 * @return this
289 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800290 public Builder addIndexSetType(Primitive p) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700291 Entry indexType = new Entry();
292 indexType.t = null;
293 indexType.e = null;
294 indexType.size = 0;
295 indexType.prim = p;
296 mIndexTypes.addElement(indexType);
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800297 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700298 }
299
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800300 /**
301 * Adds an index set data type to the builder object
302 *
303 * @param e element describing the index set data layout
304 * @param size number of elements in the buffer
305 * @param p primitive type
306 *
307 * @return this
308 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800309 public Builder addIndexSetType(Element e, int size, Primitive p) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700310 Entry indexType = new Entry();
311 indexType.t = null;
312 indexType.e = e;
313 indexType.size = size;
314 indexType.prim = p;
315 mIndexTypes.addElement(indexType);
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800316 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700317 }
318
319 Type newType(Element e, int size) {
320 Type.Builder tb = new Type.Builder(mRS, e);
Jason Samsbf6ef8d2010-12-06 15:59:59 -0800321 tb.setX(size);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700322 return tb.create();
323 }
324
325 static synchronized Mesh internalCreate(RenderScript rs, Builder b) {
326
327 int id = rs.nMeshCreate(b.mVertexTypeCount, b.mIndexTypes.size());
328 Mesh newMesh = new Mesh(id, rs);
329 newMesh.mIndexBuffers = new Allocation[b.mIndexTypes.size()];
330 newMesh.mPrimitives = new Primitive[b.mIndexTypes.size()];
331 newMesh.mVertexBuffers = new Allocation[b.mVertexTypeCount];
332
333 for(int ct = 0; ct < b.mIndexTypes.size(); ct ++) {
334 Allocation alloc = null;
335 Entry entry = (Entry)b.mIndexTypes.elementAt(ct);
336 if (entry.t != null) {
Jason Samsd1952402010-12-20 12:55:28 -0800337 alloc = Allocation.createTyped(rs, entry.t, b.mUsage);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700338 }
339 else if(entry.e != null) {
Jason Samsd1952402010-12-20 12:55:28 -0800340 alloc = Allocation.createSized(rs, entry.e, entry.size, b.mUsage);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700341 }
342 int allocID = (alloc == null) ? 0 : alloc.getID();
343 rs.nMeshBindIndex(id, allocID, entry.prim.mID, ct);
344 newMesh.mIndexBuffers[ct] = alloc;
345 newMesh.mPrimitives[ct] = entry.prim;
346 }
347
348 for(int ct = 0; ct < b.mVertexTypeCount; ct ++) {
349 Allocation alloc = null;
350 Entry entry = b.mVertexTypes[ct];
351 if (entry.t != null) {
Jason Samsd1952402010-12-20 12:55:28 -0800352 alloc = Allocation.createTyped(rs, entry.t, b.mUsage);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700353 } else if(entry.e != null) {
Jason Samsd1952402010-12-20 12:55:28 -0800354 alloc = Allocation.createSized(rs, entry.e, entry.size, b.mUsage);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700355 }
356 rs.nMeshBindVertex(id, alloc.getID(), ct);
357 newMesh.mVertexBuffers[ct] = alloc;
358 }
Alex Sakhartchouk9d71e212010-11-08 15:10:52 -0800359 rs.nMeshInitVertexAttribs(id);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700360
361 return newMesh;
362 }
363
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800364 /**
365 * Create a Mesh object from the current state of the builder
366 *
367 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700368 public Mesh create() {
369 mRS.validate();
370 Mesh sm = internalCreate(mRS, this);
371 return sm;
372 }
373 }
374
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800375 /**
376 * Mesh builder object. It starts empty and requires the user to
377 * add all the vertex and index allocations that comprise the
378 * mesh
379 *
380 */
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700381 public static class AllocationBuilder {
382 RenderScript mRS;
383
384 class Entry {
385 Allocation a;
386 Primitive prim;
387 }
388
389 int mVertexTypeCount;
390 Entry[] mVertexTypes;
391
392 Vector mIndexTypes;
393
394 public AllocationBuilder(RenderScript rs) {
395 mRS = rs;
396 mVertexTypeCount = 0;
397 mVertexTypes = new Entry[16];
398 mIndexTypes = new Vector();
399 }
400
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800401 /**
402 * @return internal index of the last vertex buffer type added to
403 * builder
404 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800405 public int getCurrentVertexTypeIndex() {
406 return mVertexTypeCount - 1;
407 }
408
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800409 /**
410 * @return internal index of the last index set added to the
411 * builder
412 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800413 public int getCurrentIndexSetIndex() {
414 return mIndexTypes.size() - 1;
415 }
416
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800417 /**
418 * Adds an allocation containing vertex buffer data to the
419 * builder
420 *
421 * @param a vertex data allocation
422 *
423 * @return this
424 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800425 public AllocationBuilder addVertexAllocation(Allocation a) throws IllegalStateException {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700426 if (mVertexTypeCount >= mVertexTypes.length) {
427 throw new IllegalStateException("Max vertex types exceeded.");
428 }
429
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700430 mVertexTypes[mVertexTypeCount] = new Entry();
431 mVertexTypes[mVertexTypeCount].a = a;
432 mVertexTypeCount++;
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800433 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700434 }
435
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800436 /**
437 * Adds an allocation containing index buffer data and index type
438 * to the builder
439 *
440 * @param a index set data allocation, could be null
441 * @param p index set primitive type
442 *
443 * @return this
444 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800445 public AllocationBuilder addIndexSetAllocation(Allocation a, Primitive p) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700446 Entry indexType = new Entry();
447 indexType.a = a;
448 indexType.prim = p;
449 mIndexTypes.addElement(indexType);
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800450 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700451 }
452
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800453 /**
454 * Adds an index set type to the builder
455 *
456 * @param p index set primitive type
457 *
458 * @return this
459 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800460 public AllocationBuilder addIndexSetType(Primitive p) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700461 Entry indexType = new Entry();
462 indexType.a = null;
463 indexType.prim = p;
464 mIndexTypes.addElement(indexType);
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800465 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700466 }
467
468 static synchronized Mesh internalCreate(RenderScript rs, AllocationBuilder b) {
469
470 int id = rs.nMeshCreate(b.mVertexTypeCount, b.mIndexTypes.size());
471 Mesh newMesh = new Mesh(id, rs);
472 newMesh.mIndexBuffers = new Allocation[b.mIndexTypes.size()];
473 newMesh.mPrimitives = new Primitive[b.mIndexTypes.size()];
474 newMesh.mVertexBuffers = new Allocation[b.mVertexTypeCount];
475
476 for(int ct = 0; ct < b.mIndexTypes.size(); ct ++) {
477 Entry entry = (Entry)b.mIndexTypes.elementAt(ct);
478 int allocID = (entry.a == null) ? 0 : entry.a.getID();
479 rs.nMeshBindIndex(id, allocID, entry.prim.mID, ct);
480 newMesh.mIndexBuffers[ct] = entry.a;
481 newMesh.mPrimitives[ct] = entry.prim;
482 }
483
484 for(int ct = 0; ct < b.mVertexTypeCount; ct ++) {
485 Entry entry = b.mVertexTypes[ct];
Jason Sams06d69de2010-11-09 17:11:40 -0800486 rs.nMeshBindVertex(id, entry.a.getID(), ct);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700487 newMesh.mVertexBuffers[ct] = entry.a;
488 }
Alex Sakhartchouk9d71e212010-11-08 15:10:52 -0800489 rs.nMeshInitVertexAttribs(id);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700490
491 return newMesh;
492 }
493
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800494 /**
495 * Create a Mesh object from the current state of the builder
496 *
497 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700498 public Mesh create() {
499 mRS.validate();
500 Mesh sm = internalCreate(mRS, this);
501 return sm;
502 }
503 }
504
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800505 /**
506 * Builder that allows creation of a mesh object point by point
507 * and triangle by triangle
508 *
509 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700510 public static class TriangleMeshBuilder {
511 float mVtxData[];
512 int mVtxCount;
513 short mIndexData[];
514 int mIndexCount;
515 RenderScript mRS;
516 Element mElement;
517
518 float mNX = 0;
519 float mNY = 0;
520 float mNZ = -1;
521 float mS0 = 0;
522 float mT0 = 0;
523 float mR = 1;
524 float mG = 1;
525 float mB = 1;
526 float mA = 1;
527
528 int mVtxSize;
529 int mFlags;
530
531 public static final int COLOR = 0x0001;
532 public static final int NORMAL = 0x0002;
533 public static final int TEXTURE_0 = 0x0100;
534
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800535 /**
Alex Sakhartchoukf5c876e2011-01-13 14:53:43 -0800536 * @param rs Context to which the mesh will belong.
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800537 * @param vtxSize specifies whether the vertex is a float2 or
538 * float3
539 * @param flags bitfield that is a combination of COLOR, NORMAL,
540 * and TEXTURE_0 that specifies what vertex data
541 * channels are present in the mesh
542 *
543 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700544 public TriangleMeshBuilder(RenderScript rs, int vtxSize, int flags) {
545 mRS = rs;
546 mVtxCount = 0;
547 mIndexCount = 0;
548 mVtxData = new float[128];
549 mIndexData = new short[128];
550 mVtxSize = vtxSize;
551 mFlags = flags;
552
553 if (vtxSize < 2 || vtxSize > 3) {
554 throw new IllegalArgumentException("Vertex size out of range.");
555 }
556 }
557
558 private void makeSpace(int count) {
559 if ((mVtxCount + count) >= mVtxData.length) {
560 float t[] = new float[mVtxData.length * 2];
561 System.arraycopy(mVtxData, 0, t, 0, mVtxData.length);
562 mVtxData = t;
563 }
564 }
565
566 private void latch() {
567 if ((mFlags & COLOR) != 0) {
568 makeSpace(4);
569 mVtxData[mVtxCount++] = mR;
570 mVtxData[mVtxCount++] = mG;
571 mVtxData[mVtxCount++] = mB;
572 mVtxData[mVtxCount++] = mA;
573 }
574 if ((mFlags & TEXTURE_0) != 0) {
575 makeSpace(2);
576 mVtxData[mVtxCount++] = mS0;
577 mVtxData[mVtxCount++] = mT0;
578 }
579 if ((mFlags & NORMAL) != 0) {
580 makeSpace(3);
581 mVtxData[mVtxCount++] = mNX;
582 mVtxData[mVtxCount++] = mNY;
583 mVtxData[mVtxCount++] = mNZ;
584 }
585 }
586
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800587 /**
588 * Adds a float2 vertex to the mesh
589 *
590 * @param x position x
591 * @param y position y
592 *
593 * @return this
594 *
595 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800596 public TriangleMeshBuilder addVertex(float x, float y) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700597 if (mVtxSize != 2) {
598 throw new IllegalStateException("add mistmatch with declared components.");
599 }
600 makeSpace(2);
601 mVtxData[mVtxCount++] = x;
602 mVtxData[mVtxCount++] = y;
603 latch();
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800604 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700605 }
606
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800607 /**
608 * Adds a float3 vertex to the mesh
609 *
610 * @param x position x
611 * @param y position y
612 * @param z position z
613 *
614 * @return this
615 *
616 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800617 public TriangleMeshBuilder addVertex(float x, float y, float z) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700618 if (mVtxSize != 3) {
619 throw new IllegalStateException("add mistmatch with declared components.");
620 }
621 makeSpace(3);
622 mVtxData[mVtxCount++] = x;
623 mVtxData[mVtxCount++] = y;
624 mVtxData[mVtxCount++] = z;
625 latch();
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800626 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700627 }
628
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800629 /**
630 * Sets the texture coordinate for the last added vertex
631 *
632 * @param s texture coordinate s
633 * @param t texture coordinate t
634 *
635 * @return this
636 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800637 public TriangleMeshBuilder setTexture(float s, float t) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700638 if ((mFlags & TEXTURE_0) == 0) {
639 throw new IllegalStateException("add mistmatch with declared components.");
640 }
641 mS0 = s;
642 mT0 = t;
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800643 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700644 }
645
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800646 /**
647 * Sets the normal vector for the last added vertex
648 *
649 * @param x normal vector x
650 * @param y normal vector y
651 * @param z normal vector z
652 *
653 * @return this
654 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800655 public TriangleMeshBuilder setNormal(float x, float y, float z) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700656 if ((mFlags & NORMAL) == 0) {
657 throw new IllegalStateException("add mistmatch with declared components.");
658 }
659 mNX = x;
660 mNY = y;
661 mNZ = z;
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800662 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700663 }
664
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800665 /**
666 * Sets the color for the last added vertex
667 *
668 * @param r red component
669 * @param g green component
670 * @param b blue component
671 * @param a alpha component
672 *
673 * @return this
674 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800675 public TriangleMeshBuilder setColor(float r, float g, float b, float a) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700676 if ((mFlags & COLOR) == 0) {
677 throw new IllegalStateException("add mistmatch with declared components.");
678 }
679 mR = r;
680 mG = g;
681 mB = b;
682 mA = a;
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800683 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700684 }
685
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800686 /**
687 * Adds a new triangle to the mesh builder
688 *
689 * @param idx1 index of the first vertex in the triangle
690 * @param idx2 index of the second vertex in the triangle
691 * @param idx3 index of the third vertex in the triangle
692 *
693 * @return this
694 **/
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800695 public TriangleMeshBuilder addTriangle(int idx1, int idx2, int idx3) {
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700696 if((idx1 >= mVtxCount) || (idx1 < 0) ||
697 (idx2 >= mVtxCount) || (idx2 < 0) ||
698 (idx3 >= mVtxCount) || (idx3 < 0)) {
699 throw new IllegalStateException("Index provided greater than vertex count.");
700 }
701 if ((mIndexCount + 3) >= mIndexData.length) {
702 short t[] = new short[mIndexData.length * 2];
703 System.arraycopy(mIndexData, 0, t, 0, mIndexData.length);
704 mIndexData = t;
705 }
706 mIndexData[mIndexCount++] = (short)idx1;
707 mIndexData[mIndexCount++] = (short)idx2;
708 mIndexData[mIndexCount++] = (short)idx3;
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800709 return this;
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700710 }
711
Alex Sakhartchoukdf272022011-01-09 11:34:03 -0800712 /**
713 * Creates the mesh object from the current state of the builder
714 *
715 * @param uploadToBufferObject specifies whether the vertex data
716 * is to be uploaded into the buffer
717 * object indicating that it's likely
718 * not going to be modified and
719 * rendered many times.
720 * Alternatively, it indicates the
721 * mesh data will be updated
722 * frequently and remain in script
723 * accessible memory
724 *
725 **/
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700726 public Mesh create(boolean uploadToBufferObject) {
727 Element.Builder b = new Element.Builder(mRS);
728 int floatCount = mVtxSize;
729 b.add(Element.createVector(mRS,
730 Element.DataType.FLOAT_32,
731 mVtxSize), "position");
732 if ((mFlags & COLOR) != 0) {
733 floatCount += 4;
734 b.add(Element.F32_4(mRS), "color");
735 }
736 if ((mFlags & TEXTURE_0) != 0) {
737 floatCount += 2;
738 b.add(Element.F32_2(mRS), "texture0");
739 }
740 if ((mFlags & NORMAL) != 0) {
741 floatCount += 3;
742 b.add(Element.F32_3(mRS), "normal");
743 }
744 mElement = b.create();
745
Jason Samsd1952402010-12-20 12:55:28 -0800746 int usage = Allocation.USAGE_SCRIPT;
747 if (uploadToBufferObject) {
748 usage |= Allocation.USAGE_GRAPHICS_VERTEX;
749 }
750
751 Builder smb = new Builder(mRS, usage);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700752 smb.addVertexType(mElement, mVtxCount / floatCount);
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800753 smb.addIndexSetType(Element.U16(mRS), mIndexCount, Primitive.TRIANGLE);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700754
755 Mesh sm = smb.create();
756
Jason Samsbf6ef8d2010-12-06 15:59:59 -0800757 sm.getVertexAllocation(0).copyFrom(mVtxData);
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700758 if(uploadToBufferObject) {
Jason Samsd1952402010-12-20 12:55:28 -0800759 if (uploadToBufferObject) {
760 sm.getVertexAllocation(0).syncAll(Allocation.USAGE_SCRIPT);
761 }
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700762 }
763
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800764 sm.getIndexSetAllocation(0).copyFrom(mIndexData);
Jason Samsd1952402010-12-20 12:55:28 -0800765 if (uploadToBufferObject) {
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800766 sm.getIndexSetAllocation(0).syncAll(Allocation.USAGE_SCRIPT);
Jason Samsd1952402010-12-20 12:55:28 -0800767 }
Alex Sakhartchouk164aaed2010-07-01 16:14:06 -0700768
769 return sm;
770 }
771 }
772}
773