Mesh.java revision d4b23b54445b13dacaafad97d100999abb36ea6f
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 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.setX(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 rs.nMeshInitVertexAttribs(id); 216 217 return newMesh; 218 } 219 220 public Mesh create() { 221 mRS.validate(); 222 Mesh sm = internalCreate(mRS, this); 223 return sm; 224 } 225 } 226 227 public static class AllocationBuilder { 228 RenderScript mRS; 229 230 class Entry { 231 Allocation a; 232 Primitive prim; 233 } 234 235 int mVertexTypeCount; 236 Entry[] mVertexTypes; 237 238 Vector mIndexTypes; 239 240 public AllocationBuilder(RenderScript rs) { 241 mRS = rs; 242 mVertexTypeCount = 0; 243 mVertexTypes = new Entry[16]; 244 mIndexTypes = new Vector(); 245 } 246 247 public int addVertexAllocation(Allocation a) throws IllegalStateException { 248 if (mVertexTypeCount >= mVertexTypes.length) { 249 throw new IllegalStateException("Max vertex types exceeded."); 250 } 251 252 int addedIndex = mVertexTypeCount; 253 mVertexTypes[mVertexTypeCount] = new Entry(); 254 mVertexTypes[mVertexTypeCount].a = a; 255 mVertexTypeCount++; 256 return addedIndex; 257 } 258 259 public int addIndexAllocation(Allocation a, Primitive p) { 260 int addedIndex = mIndexTypes.size(); 261 Entry indexType = new Entry(); 262 indexType.a = a; 263 indexType.prim = p; 264 mIndexTypes.addElement(indexType); 265 return addedIndex; 266 } 267 268 public int addIndexType(Primitive p) { 269 int addedIndex = mIndexTypes.size(); 270 Entry indexType = new Entry(); 271 indexType.a = null; 272 indexType.prim = p; 273 mIndexTypes.addElement(indexType); 274 return addedIndex; 275 } 276 277 static synchronized Mesh internalCreate(RenderScript rs, AllocationBuilder b) { 278 279 int id = rs.nMeshCreate(b.mVertexTypeCount, b.mIndexTypes.size()); 280 Mesh newMesh = new Mesh(id, rs); 281 newMesh.mIndexBuffers = new Allocation[b.mIndexTypes.size()]; 282 newMesh.mPrimitives = new Primitive[b.mIndexTypes.size()]; 283 newMesh.mVertexBuffers = new Allocation[b.mVertexTypeCount]; 284 285 for(int ct = 0; ct < b.mIndexTypes.size(); ct ++) { 286 Entry entry = (Entry)b.mIndexTypes.elementAt(ct); 287 int allocID = (entry.a == null) ? 0 : entry.a.getID(); 288 rs.nMeshBindIndex(id, allocID, entry.prim.mID, ct); 289 newMesh.mIndexBuffers[ct] = entry.a; 290 newMesh.mPrimitives[ct] = entry.prim; 291 } 292 293 for(int ct = 0; ct < b.mVertexTypeCount; ct ++) { 294 Entry entry = b.mVertexTypes[ct]; 295 rs.nMeshBindVertex(id, entry.a.getID(), ct); 296 newMesh.mVertexBuffers[ct] = entry.a; 297 } 298 rs.nMeshInitVertexAttribs(id); 299 300 return newMesh; 301 } 302 303 public Mesh create() { 304 mRS.validate(); 305 Mesh sm = internalCreate(mRS, this); 306 return sm; 307 } 308 } 309 310 311 public static class TriangleMeshBuilder { 312 float mVtxData[]; 313 int mVtxCount; 314 short mIndexData[]; 315 int mIndexCount; 316 RenderScript mRS; 317 Element mElement; 318 319 float mNX = 0; 320 float mNY = 0; 321 float mNZ = -1; 322 float mS0 = 0; 323 float mT0 = 0; 324 float mR = 1; 325 float mG = 1; 326 float mB = 1; 327 float mA = 1; 328 329 int mVtxSize; 330 int mFlags; 331 332 public static final int COLOR = 0x0001; 333 public static final int NORMAL = 0x0002; 334 public static final int TEXTURE_0 = 0x0100; 335 336 public TriangleMeshBuilder(RenderScript rs, int vtxSize, int flags) { 337 mRS = rs; 338 mVtxCount = 0; 339 mIndexCount = 0; 340 mVtxData = new float[128]; 341 mIndexData = new short[128]; 342 mVtxSize = vtxSize; 343 mFlags = flags; 344 345 if (vtxSize < 2 || vtxSize > 3) { 346 throw new IllegalArgumentException("Vertex size out of range."); 347 } 348 } 349 350 private void makeSpace(int count) { 351 if ((mVtxCount + count) >= mVtxData.length) { 352 float t[] = new float[mVtxData.length * 2]; 353 System.arraycopy(mVtxData, 0, t, 0, mVtxData.length); 354 mVtxData = t; 355 } 356 } 357 358 private void latch() { 359 if ((mFlags & COLOR) != 0) { 360 makeSpace(4); 361 mVtxData[mVtxCount++] = mR; 362 mVtxData[mVtxCount++] = mG; 363 mVtxData[mVtxCount++] = mB; 364 mVtxData[mVtxCount++] = mA; 365 } 366 if ((mFlags & TEXTURE_0) != 0) { 367 makeSpace(2); 368 mVtxData[mVtxCount++] = mS0; 369 mVtxData[mVtxCount++] = mT0; 370 } 371 if ((mFlags & NORMAL) != 0) { 372 makeSpace(3); 373 mVtxData[mVtxCount++] = mNX; 374 mVtxData[mVtxCount++] = mNY; 375 mVtxData[mVtxCount++] = mNZ; 376 } 377 } 378 379 public void addVertex(float x, float y) { 380 if (mVtxSize != 2) { 381 throw new IllegalStateException("add mistmatch with declared components."); 382 } 383 makeSpace(2); 384 mVtxData[mVtxCount++] = x; 385 mVtxData[mVtxCount++] = y; 386 latch(); 387 } 388 389 public void addVertex(float x, float y, float z) { 390 if (mVtxSize != 3) { 391 throw new IllegalStateException("add mistmatch with declared components."); 392 } 393 makeSpace(3); 394 mVtxData[mVtxCount++] = x; 395 mVtxData[mVtxCount++] = y; 396 mVtxData[mVtxCount++] = z; 397 latch(); 398 } 399 400 public void setTexture(float s, float t) { 401 if ((mFlags & TEXTURE_0) == 0) { 402 throw new IllegalStateException("add mistmatch with declared components."); 403 } 404 mS0 = s; 405 mT0 = t; 406 } 407 408 public void setNormal(float x, float y, float z) { 409 if ((mFlags & NORMAL) == 0) { 410 throw new IllegalStateException("add mistmatch with declared components."); 411 } 412 mNX = x; 413 mNY = y; 414 mNZ = z; 415 } 416 417 public void setColor(float r, float g, float b, float a) { 418 if ((mFlags & COLOR) == 0) { 419 throw new IllegalStateException("add mistmatch with declared components."); 420 } 421 mR = r; 422 mG = g; 423 mB = b; 424 mA = a; 425 } 426 427 public void addTriangle(int idx1, int idx2, int idx3) { 428 if((idx1 >= mVtxCount) || (idx1 < 0) || 429 (idx2 >= mVtxCount) || (idx2 < 0) || 430 (idx3 >= mVtxCount) || (idx3 < 0)) { 431 throw new IllegalStateException("Index provided greater than vertex count."); 432 } 433 if ((mIndexCount + 3) >= mIndexData.length) { 434 short t[] = new short[mIndexData.length * 2]; 435 System.arraycopy(mIndexData, 0, t, 0, mIndexData.length); 436 mIndexData = t; 437 } 438 mIndexData[mIndexCount++] = (short)idx1; 439 mIndexData[mIndexCount++] = (short)idx2; 440 mIndexData[mIndexCount++] = (short)idx3; 441 } 442 443 public Mesh create(boolean uploadToBufferObject) { 444 Element.Builder b = new Element.Builder(mRS); 445 int floatCount = mVtxSize; 446 b.add(Element.createVector(mRS, 447 Element.DataType.FLOAT_32, 448 mVtxSize), "position"); 449 if ((mFlags & COLOR) != 0) { 450 floatCount += 4; 451 b.add(Element.F32_4(mRS), "color"); 452 } 453 if ((mFlags & TEXTURE_0) != 0) { 454 floatCount += 2; 455 b.add(Element.F32_2(mRS), "texture0"); 456 } 457 if ((mFlags & NORMAL) != 0) { 458 floatCount += 3; 459 b.add(Element.F32_3(mRS), "normal"); 460 } 461 mElement = b.create(); 462 463 Builder smb = new Builder(mRS); 464 smb.addVertexType(mElement, mVtxCount / floatCount); 465 smb.addIndexType(Element.U16(mRS), mIndexCount, Primitive.TRIANGLE); 466 467 Mesh sm = smb.create(); 468 469 sm.getVertexAllocation(0).copyFrom(mVtxData); 470 if(uploadToBufferObject) { 471 sm.getVertexAllocation(0).uploadToBufferObject(); 472 } 473 474 sm.getIndexAllocation(0).copyFrom(mIndexData); 475 sm.getIndexAllocation(0).uploadToBufferObject(); 476 477 return sm; 478 } 479 } 480} 481 482