Mesh.java revision d19524047fa2d12ecd45ebcf69543836e1b45579
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 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(id, rs); 36 } 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 61 @Override 62 void updateFromNative() { 63 super.updateFromNative(); 64 int vtxCount = mRS.nMeshGetVertexBufferCount(getID()); 65 int idxCount = mRS.nMeshGetIndexCount(getID()); 66 67 int[] vtxIDs = new int[vtxCount]; 68 int[] idxIDs = new int[idxCount]; 69 int[] primitives = new int[idxCount]; 70 71 mRS.nMeshGetVertices(getID(), vtxIDs, vtxCount); 72 mRS.nMeshGetIndices(getID(), idxIDs, primitives, idxCount); 73 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) { 80 mVertexBuffers[i] = new Allocation(vtxIDs[i], mRS, null, Allocation.USAGE_SCRIPT); 81 mVertexBuffers[i].updateFromNative(); 82 } 83 } 84 85 for(int i = 0; i < idxCount; i ++) { 86 if(idxIDs[i] != 0) { 87 mIndexBuffers[i] = new Allocation(idxIDs[i], mRS, null, Allocation.USAGE_SCRIPT); 88 mIndexBuffers[i].updateFromNative(); 89 } 90 mPrimitives[i] = Primitive.values()[primitives[i]]; 91 } 92 } 93 94 public static class Builder { 95 RenderScript mRS; 96 int mUsage; 97 98 class Entry { 99 Type t; 100 Element e; 101 int size; 102 Primitive prim; 103 int usage; 104 } 105 106 int mVertexTypeCount; 107 Entry[] mVertexTypes; 108 Vector mIndexTypes; 109 110 public Builder(RenderScript rs, int usage) { 111 mRS = rs; 112 mUsage = usage; 113 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); 180 tb.setX(size); 181 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) { 196 alloc = Allocation.createTyped(rs, entry.t, b.mUsage); 197 } 198 else if(entry.e != null) { 199 alloc = Allocation.createSized(rs, entry.e, entry.size, b.mUsage); 200 } 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) { 211 alloc = Allocation.createTyped(rs, entry.t, b.mUsage); 212 } else if(entry.e != null) { 213 alloc = Allocation.createSized(rs, entry.e, entry.size, b.mUsage); 214 } 215 rs.nMeshBindVertex(id, alloc.getID(), ct); 216 newMesh.mVertexBuffers[ct] = alloc; 217 } 218 rs.nMeshInitVertexAttribs(id); 219 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]; 298 rs.nMeshBindVertex(id, entry.a.getID(), ct); 299 newMesh.mVertexBuffers[ct] = entry.a; 300 } 301 rs.nMeshInitVertexAttribs(id); 302 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 466 int usage = Allocation.USAGE_SCRIPT; 467 if (uploadToBufferObject) { 468 usage |= Allocation.USAGE_GRAPHICS_VERTEX; 469 } 470 471 Builder smb = new Builder(mRS, usage); 472 smb.addVertexType(mElement, mVtxCount / floatCount); 473 smb.addIndexType(Element.U16(mRS), mIndexCount, Primitive.TRIANGLE); 474 475 Mesh sm = smb.create(); 476 477 sm.getVertexAllocation(0).copyFrom(mVtxData); 478 if(uploadToBufferObject) { 479 if (uploadToBufferObject) { 480 sm.getVertexAllocation(0).syncAll(Allocation.USAGE_SCRIPT); 481 } 482 } 483 484 sm.getIndexAllocation(0).copyFrom(mIndexData); 485 if (uploadToBufferObject) { 486 sm.getIndexAllocation(0).syncAll(Allocation.USAGE_SCRIPT); 487 } 488 489 return sm; 490 } 491 } 492} 493 494