Mesh.java revision 80a4c2cd34aedb4f1a2e5e7d1ac26a9aeebe41ae
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(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 62 @Override 63 void updateFromNative() { 64 int vtxCount = mRS.nMeshGetVertexBufferCount(mID); 65 int idxCount = mRS.nMeshGetIndexCount(mID); 66 67 int[] vtxIDs = new int[vtxCount]; 68 int[] idxIDs = new int[idxCount]; 69 int[] primitives = new int[idxCount]; 70 71 mRS.nMeshGetVertices(mID, vtxIDs, vtxCount); 72 mRS.nMeshGetIndices(mID, idxIDs, primitives, vtxCount); 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); 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); 88 mIndexBuffers[i].updateFromNative(); 89 } 90 mPrimitives[i] = Primitive.values()[primitives[i]]; 91 } 92 } 93 94 public static class Builder { 95 RenderScript mRS; 96 97 class Entry { 98 Type t; 99 Element e; 100 int size; 101 Primitive prim; 102 } 103 104 int mVertexTypeCount; 105 Entry[] mVertexTypes; 106 Vector mIndexTypes; 107 108 public Builder(RenderScript rs) { 109 mRS = rs; 110 mVertexTypeCount = 0; 111 mVertexTypes = new Entry[16]; 112 mIndexTypes = new Vector(); 113 } 114 115 public int addVertexType(Type t) throws IllegalStateException { 116 if (mVertexTypeCount >= mVertexTypes.length) { 117 throw new IllegalStateException("Max vertex types exceeded."); 118 } 119 120 int addedIndex = mVertexTypeCount; 121 mVertexTypes[mVertexTypeCount] = new Entry(); 122 mVertexTypes[mVertexTypeCount].t = t; 123 mVertexTypes[mVertexTypeCount].e = null; 124 mVertexTypeCount++; 125 return addedIndex; 126 } 127 128 public int addVertexType(Element e, int size) throws IllegalStateException { 129 if (mVertexTypeCount >= mVertexTypes.length) { 130 throw new IllegalStateException("Max vertex types exceeded."); 131 } 132 133 int addedIndex = mVertexTypeCount; 134 mVertexTypes[mVertexTypeCount] = new Entry(); 135 mVertexTypes[mVertexTypeCount].t = null; 136 mVertexTypes[mVertexTypeCount].e = e; 137 mVertexTypes[mVertexTypeCount].size = size; 138 mVertexTypeCount++; 139 return addedIndex; 140 } 141 142 public int addIndexType(Type t, Primitive p) { 143 int addedIndex = mIndexTypes.size(); 144 Entry indexType = new Entry(); 145 indexType.t = t; 146 indexType.e = null; 147 indexType.size = 0; 148 indexType.prim = p; 149 mIndexTypes.addElement(indexType); 150 return addedIndex; 151 } 152 153 public int addIndexType(Primitive p) { 154 int addedIndex = mIndexTypes.size(); 155 Entry indexType = new Entry(); 156 indexType.t = null; 157 indexType.e = null; 158 indexType.size = 0; 159 indexType.prim = p; 160 mIndexTypes.addElement(indexType); 161 return addedIndex; 162 } 163 164 public int addIndexType(Element e, int size, Primitive p) { 165 int addedIndex = mIndexTypes.size(); 166 Entry indexType = new Entry(); 167 indexType.t = null; 168 indexType.e = e; 169 indexType.size = size; 170 indexType.prim = p; 171 mIndexTypes.addElement(indexType); 172 return addedIndex; 173 } 174 175 Type newType(Element e, int size) { 176 Type.Builder tb = new Type.Builder(mRS, e); 177 tb.add(Dimension.X, size); 178 return tb.create(); 179 } 180 181 static synchronized Mesh internalCreate(RenderScript rs, Builder b) { 182 183 int id = rs.nMeshCreate(b.mVertexTypeCount, b.mIndexTypes.size()); 184 Mesh newMesh = new Mesh(id, rs); 185 newMesh.mIndexBuffers = new Allocation[b.mIndexTypes.size()]; 186 newMesh.mPrimitives = new Primitive[b.mIndexTypes.size()]; 187 newMesh.mVertexBuffers = new Allocation[b.mVertexTypeCount]; 188 189 for(int ct = 0; ct < b.mIndexTypes.size(); ct ++) { 190 Allocation alloc = null; 191 Entry entry = (Entry)b.mIndexTypes.elementAt(ct); 192 if (entry.t != null) { 193 alloc = Allocation.createTyped(rs, entry.t); 194 } 195 else if(entry.e != null) { 196 alloc = Allocation.createSized(rs, entry.e, entry.size); 197 } 198 int allocID = (alloc == null) ? 0 : alloc.getID(); 199 rs.nMeshBindIndex(id, allocID, entry.prim.mID, ct); 200 newMesh.mIndexBuffers[ct] = alloc; 201 newMesh.mPrimitives[ct] = entry.prim; 202 } 203 204 for(int ct = 0; ct < b.mVertexTypeCount; ct ++) { 205 Allocation alloc = null; 206 Entry entry = b.mVertexTypes[ct]; 207 if (entry.t != null) { 208 alloc = Allocation.createTyped(rs, entry.t); 209 } else if(entry.e != null) { 210 alloc = Allocation.createSized(rs, entry.e, entry.size); 211 } 212 rs.nMeshBindVertex(id, alloc.getID(), ct); 213 newMesh.mVertexBuffers[ct] = alloc; 214 } 215 216 return newMesh; 217 } 218 219 public Mesh create() { 220 mRS.validate(); 221 Mesh sm = internalCreate(mRS, this); 222 return sm; 223 } 224 } 225 226 public static class AllocationBuilder { 227 RenderScript mRS; 228 229 class Entry { 230 Allocation a; 231 Primitive prim; 232 } 233 234 int mVertexTypeCount; 235 Entry[] mVertexTypes; 236 237 Vector mIndexTypes; 238 239 public AllocationBuilder(RenderScript rs) { 240 mRS = rs; 241 mVertexTypeCount = 0; 242 mVertexTypes = new Entry[16]; 243 mIndexTypes = new Vector(); 244 } 245 246 public int addVertexAllocation(Allocation a) throws IllegalStateException { 247 if (mVertexTypeCount >= mVertexTypes.length) { 248 throw new IllegalStateException("Max vertex types exceeded."); 249 } 250 251 int addedIndex = mVertexTypeCount; 252 mVertexTypes[mVertexTypeCount] = new Entry(); 253 mVertexTypes[mVertexTypeCount].a = a; 254 mVertexTypeCount++; 255 return addedIndex; 256 } 257 258 public int addIndexAllocation(Allocation a, Primitive p) { 259 int addedIndex = mIndexTypes.size(); 260 Entry indexType = new Entry(); 261 indexType.a = a; 262 indexType.prim = p; 263 mIndexTypes.addElement(indexType); 264 return addedIndex; 265 } 266 267 public int addIndexType(Primitive p) { 268 int addedIndex = mIndexTypes.size(); 269 Entry indexType = new Entry(); 270 indexType.a = null; 271 indexType.prim = p; 272 mIndexTypes.addElement(indexType); 273 return addedIndex; 274 } 275 276 static synchronized Mesh internalCreate(RenderScript rs, AllocationBuilder b) { 277 278 int id = rs.nMeshCreate(b.mVertexTypeCount, b.mIndexTypes.size()); 279 Mesh newMesh = new Mesh(id, rs); 280 newMesh.mIndexBuffers = new Allocation[b.mIndexTypes.size()]; 281 newMesh.mPrimitives = new Primitive[b.mIndexTypes.size()]; 282 newMesh.mVertexBuffers = new Allocation[b.mVertexTypeCount]; 283 284 for(int ct = 0; ct < b.mIndexTypes.size(); ct ++) { 285 Entry entry = (Entry)b.mIndexTypes.elementAt(ct); 286 int allocID = (entry.a == null) ? 0 : entry.a.getID(); 287 rs.nMeshBindIndex(id, allocID, entry.prim.mID, ct); 288 newMesh.mIndexBuffers[ct] = entry.a; 289 newMesh.mPrimitives[ct] = entry.prim; 290 } 291 292 for(int ct = 0; ct < b.mVertexTypeCount; ct ++) { 293 Entry entry = b.mVertexTypes[ct]; 294 rs.nMeshBindVertex(id, entry.a.mID, ct); 295 newMesh.mVertexBuffers[ct] = entry.a; 296 } 297 298 return newMesh; 299 } 300 301 public Mesh create() { 302 mRS.validate(); 303 Mesh sm = internalCreate(mRS, this); 304 return sm; 305 } 306 } 307 308 309 public static class TriangleMeshBuilder { 310 float mVtxData[]; 311 int mVtxCount; 312 short mIndexData[]; 313 int mIndexCount; 314 RenderScript mRS; 315 Element mElement; 316 317 float mNX = 0; 318 float mNY = 0; 319 float mNZ = -1; 320 float mS0 = 0; 321 float mT0 = 0; 322 float mR = 1; 323 float mG = 1; 324 float mB = 1; 325 float mA = 1; 326 327 int mVtxSize; 328 int mFlags; 329 330 public static final int COLOR = 0x0001; 331 public static final int NORMAL = 0x0002; 332 public static final int TEXTURE_0 = 0x0100; 333 334 public TriangleMeshBuilder(RenderScript rs, int vtxSize, int flags) { 335 mRS = rs; 336 mVtxCount = 0; 337 mIndexCount = 0; 338 mVtxData = new float[128]; 339 mIndexData = new short[128]; 340 mVtxSize = vtxSize; 341 mFlags = flags; 342 343 if (vtxSize < 2 || vtxSize > 3) { 344 throw new IllegalArgumentException("Vertex size out of range."); 345 } 346 } 347 348 private void makeSpace(int count) { 349 if ((mVtxCount + count) >= mVtxData.length) { 350 float t[] = new float[mVtxData.length * 2]; 351 System.arraycopy(mVtxData, 0, t, 0, mVtxData.length); 352 mVtxData = t; 353 } 354 } 355 356 private void latch() { 357 if ((mFlags & COLOR) != 0) { 358 makeSpace(4); 359 mVtxData[mVtxCount++] = mR; 360 mVtxData[mVtxCount++] = mG; 361 mVtxData[mVtxCount++] = mB; 362 mVtxData[mVtxCount++] = mA; 363 } 364 if ((mFlags & TEXTURE_0) != 0) { 365 makeSpace(2); 366 mVtxData[mVtxCount++] = mS0; 367 mVtxData[mVtxCount++] = mT0; 368 } 369 if ((mFlags & NORMAL) != 0) { 370 makeSpace(3); 371 mVtxData[mVtxCount++] = mNX; 372 mVtxData[mVtxCount++] = mNY; 373 mVtxData[mVtxCount++] = mNZ; 374 } 375 } 376 377 public void addVertex(float x, float y) { 378 if (mVtxSize != 2) { 379 throw new IllegalStateException("add mistmatch with declared components."); 380 } 381 makeSpace(2); 382 mVtxData[mVtxCount++] = x; 383 mVtxData[mVtxCount++] = y; 384 latch(); 385 } 386 387 public void addVertex(float x, float y, float z) { 388 if (mVtxSize != 3) { 389 throw new IllegalStateException("add mistmatch with declared components."); 390 } 391 makeSpace(3); 392 mVtxData[mVtxCount++] = x; 393 mVtxData[mVtxCount++] = y; 394 mVtxData[mVtxCount++] = z; 395 latch(); 396 } 397 398 public void setTexture(float s, float t) { 399 if ((mFlags & TEXTURE_0) == 0) { 400 throw new IllegalStateException("add mistmatch with declared components."); 401 } 402 mS0 = s; 403 mT0 = t; 404 } 405 406 public void setNormal(float x, float y, float z) { 407 if ((mFlags & NORMAL) == 0) { 408 throw new IllegalStateException("add mistmatch with declared components."); 409 } 410 mNX = x; 411 mNY = y; 412 mNZ = z; 413 } 414 415 public void setColor(float r, float g, float b, float a) { 416 if ((mFlags & COLOR) == 0) { 417 throw new IllegalStateException("add mistmatch with declared components."); 418 } 419 mR = r; 420 mG = g; 421 mB = b; 422 mA = a; 423 } 424 425 public void addTriangle(int idx1, int idx2, int idx3) { 426 if((idx1 >= mVtxCount) || (idx1 < 0) || 427 (idx2 >= mVtxCount) || (idx2 < 0) || 428 (idx3 >= mVtxCount) || (idx3 < 0)) { 429 throw new IllegalStateException("Index provided greater than vertex count."); 430 } 431 if ((mIndexCount + 3) >= mIndexData.length) { 432 short t[] = new short[mIndexData.length * 2]; 433 System.arraycopy(mIndexData, 0, t, 0, mIndexData.length); 434 mIndexData = t; 435 } 436 mIndexData[mIndexCount++] = (short)idx1; 437 mIndexData[mIndexCount++] = (short)idx2; 438 mIndexData[mIndexCount++] = (short)idx3; 439 } 440 441 public Mesh create(boolean uploadToBufferObject) { 442 Element.Builder b = new Element.Builder(mRS); 443 int floatCount = mVtxSize; 444 b.add(Element.createVector(mRS, 445 Element.DataType.FLOAT_32, 446 mVtxSize), "position"); 447 if ((mFlags & COLOR) != 0) { 448 floatCount += 4; 449 b.add(Element.F32_4(mRS), "color"); 450 } 451 if ((mFlags & TEXTURE_0) != 0) { 452 floatCount += 2; 453 b.add(Element.F32_2(mRS), "texture0"); 454 } 455 if ((mFlags & NORMAL) != 0) { 456 floatCount += 3; 457 b.add(Element.F32_3(mRS), "normal"); 458 } 459 mElement = b.create(); 460 461 Builder smb = new Builder(mRS); 462 smb.addVertexType(mElement, mVtxCount / floatCount); 463 smb.addIndexType(Element.U16(mRS), mIndexCount, Primitive.TRIANGLE); 464 465 Mesh sm = smb.create(); 466 467 sm.getVertexAllocation(0).data(mVtxData); 468 if(uploadToBufferObject) { 469 sm.getVertexAllocation(0).uploadToBufferObject(); 470 } 471 472 sm.getIndexAllocation(0).data(mIndexData); 473 sm.getIndexAllocation(0).uploadToBufferObject(); 474 475 return sm; 476 } 477 } 478} 479 480