/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _SIMPLE_MESH_H_ #define _SIMPLE_MESH_H_ #include #include using namespace android; using namespace android::renderscript; class SimpleMesh { public: struct Channel { std::vector mData; std::string mName; uint32_t mStride; }; // Vertex channels (position, normal) // This assumes all the data array are the same size std::vector mChannels; // Triangle list index data std::vector > mTriangleLists; // Names of all the triangle lists std::vector mTriangleListNames; // Name of the entire object std::string mName; // Adds another index set to the mesh void appendFaceList(std::string name) { mTriangleListNames.push_back(name); mTriangleLists.push_back(std::vector()); } // Adds another data channel (position, normal, etc.) void appendChannel(std::string name, uint32_t stride) { mChannels.push_back(Channel()); static const uint32_t reserveVtx = 128; mChannels.back().mData.reserve(reserveVtx*stride); mChannels.back().mName = name; mChannels.back().mStride = stride; } SimpleMesh() { // reserve some data in the vectors // simply letting it grow by itself tends to waste a lot of time on // rallocations / copies when dealing with geometry data static const uint32_t reserveFaces = 8; static const uint32_t reserveChannels = 8; mTriangleLists.reserve(reserveFaces); mTriangleListNames.reserve(reserveFaces); mChannels.reserve(reserveChannels); } // Generates a renderscript mesh that could be used for a3d serialization Mesh *getMesh(Context *rsc) { if (mChannels.size() == 0) { return NULL; } // Generate the element that describes our channel layout rsc->mStateElement.elementBuilderBegin(); for (uint32_t c = 0; c < mChannels.size(); c ++) { // Skip empty channels if (mChannels[c].mData.size() == 0) { continue; } const Element *subElem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, mChannels[c].mStride); rsc->mStateElement.elementBuilderAdd(subElem, mChannels[c].mName.c_str(), 1); } const Element *vertexDataElem = rsc->mStateElement.elementBuilderCreate(rsc); uint32_t numVerts = mChannels[0].mData.size()/mChannels[0].mStride; Type *vertexDataType = Type::getType(rsc, vertexDataElem, numVerts, 0, 0, false, false); vertexDataType->compute(); Allocation *vertexAlloc = new Allocation(rsc, vertexDataType, RS_ALLOCATION_USAGE_SCRIPT); uint32_t vertexSize = vertexDataElem->getSizeBytes()/sizeof(float); // Fill this allocation with some data float *dataPtr = (float*)vertexAlloc->getPtr(); for (uint32_t i = 0; i < numVerts; i ++) { // Find the pointer to the current vertex's data uint32_t vertexPos = i*vertexSize; float *vertexPtr = dataPtr + vertexPos; for (uint32_t c = 0; c < mChannels.size(); c ++) { // Skip empty channels if (mChannels[c].mData.size() == 0) { continue; } for (uint32_t cStride = 0; cStride < mChannels[c].mStride; cStride ++) { *(vertexPtr++) = mChannels[c].mData[i * mChannels[c].mStride + cStride]; } } } // Now lets write index data const Element *indexElem = Element::create(rsc, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1); Mesh *mesh = new Mesh(rsc); mesh->setName(mName.c_str()); mesh->mVertexBufferCount = 1; mesh->mVertexBuffers = new ObjectBaseRef[1]; mesh->mVertexBuffers[0].set(vertexAlloc); mesh->mPrimitivesCount = mTriangleLists.size(); mesh->mPrimitives = new Mesh::Primitive_t *[mesh->mPrimitivesCount]; // load all primitives for (uint32_t pCount = 0; pCount < mesh->mPrimitivesCount; pCount ++) { Mesh::Primitive_t *prim = new Mesh::Primitive_t; mesh->mPrimitives[pCount] = prim; uint32_t numIndicies = mTriangleLists[pCount].size(); Type *indexType = Type::getType(rsc, indexElem, numIndicies, 0, 0, false, false ); indexType->compute(); Allocation *indexAlloc = new Allocation(rsc, indexType, RS_ALLOCATION_USAGE_SCRIPT); uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); const std::vector &indexList = mTriangleLists[pCount]; uint32_t numTries = numIndicies / 3; for (uint32_t i = 0; i < numTries; i ++) { indexPtr[i * 3 + 0] = (uint16_t)indexList[i * 3 + 0]; indexPtr[i * 3 + 1] = (uint16_t)indexList[i * 3 + 1]; indexPtr[i * 3 + 2] = (uint16_t)indexList[i * 3 + 2]; } indexAlloc->setName(mTriangleListNames[pCount].c_str()); prim->mIndexBuffer.set(indexAlloc); prim->mPrimitive = RS_PRIMITIVE_TRIANGLE; } return mesh; } }; #endif