1 /* 2 * Copyright (C) 2011 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 17 #ifndef _SIMPLE_MESH_H_ 18 #define _SIMPLE_MESH_H_ 19 20 #include <rsContext.h> 21 #include <rsMesh.h> 22 #include <string> 23 using namespace android; 24 using namespace android::renderscript; 25 26 class SimpleMesh { 27 public: 28 struct Channel { 29 std::vector<float> mData; 30 std::string mName; 31 uint32_t mStride; 32 }; 33 34 // Vertex channels (position, normal) 35 // This assumes all the data array are the same size 36 std::vector<Channel> mChannels; 37 38 // Triangle list index data 39 std::vector<std::vector<uint32_t> > mTriangleLists; 40 // Names of all the triangle lists 41 std::vector<std::string> mTriangleListNames; 42 // Name of the entire object 43 std::string mName; 44 45 // Adds another index set to the mesh 46 void appendFaceList(std::string name) { 47 mTriangleListNames.push_back(name); 48 mTriangleLists.push_back(std::vector<uint32_t>()); 49 } 50 51 // Adds another data channel (position, normal, etc.) 52 void appendChannel(std::string name, uint32_t stride) { 53 mChannels.push_back(Channel()); 54 static const uint32_t reserveVtx = 128; 55 mChannels.back().mData.reserve(reserveVtx*stride); 56 mChannels.back().mName = name; 57 mChannels.back().mStride = stride; 58 } 59 60 SimpleMesh() { 61 // reserve some data in the vectors 62 // simply letting it grow by itself tends to waste a lot of time on 63 // rallocations / copies when dealing with geometry data 64 static const uint32_t reserveFaces = 8; 65 static const uint32_t reserveChannels = 8; 66 mTriangleLists.reserve(reserveFaces); 67 mTriangleListNames.reserve(reserveFaces); 68 mChannels.reserve(reserveChannels); 69 } 70 71 // Generates a renderscript mesh that could be used for a3d serialization 72 Mesh *getRsMesh(Context *rsc) { 73 if (mChannels.size() == 0) { 74 return NULL; 75 } 76 77 // Generate the element that describes our channel layout 78 Element::Builder vtxBuilder; 79 for (uint32_t c = 0; c < mChannels.size(); c ++) { 80 // Skip empty channels 81 if (mChannels[c].mData.size() == 0) { 82 continue; 83 } 84 ObjectBaseRef<const Element> subElem = Element::createRef(rsc, 85 RS_TYPE_FLOAT_32, 86 RS_KIND_USER, 87 false, 88 mChannels[c].mStride); 89 vtxBuilder.add(subElem.get(), mChannels[c].mName.c_str(), 1); 90 } 91 ObjectBaseRef<const Element> vertexDataElem = vtxBuilder.create(rsc); 92 93 uint32_t numVerts = mChannels[0].mData.size()/mChannels[0].mStride; 94 ObjectBaseRef<Type> vertexDataType = Type::getTypeRef(rsc, vertexDataElem.get(), 95 numVerts, 0, 0, false, false); 96 vertexDataType->compute(); 97 98 Allocation *vertexAlloc = Allocation::createAllocation(rsc, vertexDataType.get(), 99 RS_ALLOCATION_USAGE_SCRIPT); 100 101 uint32_t vertexSize = vertexDataElem->getSizeBytes()/sizeof(float); 102 // Fill this allocation with some data 103 float *dataPtr = (float*)vertexAlloc->getPtr(); 104 for (uint32_t i = 0; i < numVerts; i ++) { 105 // Find the pointer to the current vertex's data 106 uint32_t vertexPos = i*vertexSize; 107 float *vertexPtr = dataPtr + vertexPos; 108 109 for (uint32_t c = 0; c < mChannels.size(); c ++) { 110 // Skip empty channels 111 if (mChannels[c].mData.size() == 0) { 112 continue; 113 } 114 for (uint32_t cStride = 0; cStride < mChannels[c].mStride; cStride ++) { 115 *(vertexPtr++) = mChannels[c].mData[i * mChannels[c].mStride + cStride]; 116 } 117 } 118 } 119 120 // Now lets write index data 121 ObjectBaseRef<const Element> indexElem = Element::createRef(rsc, RS_TYPE_UNSIGNED_16, 122 RS_KIND_USER, false, 1); 123 124 Mesh *mesh = new Mesh(rsc, 1, mTriangleLists.size()); 125 mesh->setName(mName.c_str()); 126 mesh->setVertexBuffer(vertexAlloc, 0); 127 128 // load all primitives 129 for (uint32_t pCount = 0; pCount < mTriangleLists.size(); pCount ++) { 130 131 uint32_t numIndicies = mTriangleLists[pCount].size(); 132 ObjectBaseRef<Type> indexType = Type::getTypeRef(rsc, indexElem.get(), 133 numIndicies, 0, 0, false, false ); 134 135 indexType->compute(); 136 137 Allocation *indexAlloc = Allocation::createAllocation(rsc, indexType.get(), 138 RS_ALLOCATION_USAGE_SCRIPT); 139 uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); 140 const std::vector<uint32_t> &indexList = mTriangleLists[pCount]; 141 uint32_t numTries = numIndicies / 3; 142 143 for (uint32_t i = 0; i < numTries; i ++) { 144 indexPtr[i * 3 + 0] = (uint16_t)indexList[i * 3 + 0]; 145 indexPtr[i * 3 + 1] = (uint16_t)indexList[i * 3 + 1]; 146 indexPtr[i * 3 + 2] = (uint16_t)indexList[i * 3 + 2]; 147 } 148 indexAlloc->setName(mTriangleListNames[pCount].c_str()); 149 mesh->setPrimitive(indexAlloc, RS_PRIMITIVE_TRIANGLE, pCount); 150 } 151 152 return mesh; 153 } 154 }; 155 156 #endif 157