| /* |
| * 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 <rsContext.h> |
| #include <rsMesh.h> |
| #include <string> |
| using namespace android; |
| using namespace android::renderscript; |
| |
| class SimpleMesh { |
| public: |
| struct Channel { |
| std::vector<float> mData; |
| std::string mName; |
| uint32_t mStride; |
| }; |
| |
| // Vertex channels (position, normal) |
| // This assumes all the data array are the same size |
| std::vector<Channel> mChannels; |
| |
| // Triangle list index data |
| std::vector<std::vector<uint32_t> > mTriangleLists; |
| // Names of all the triangle lists |
| std::vector<std::string> 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<uint32_t>()); |
| } |
| |
| // 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 *getRsMesh(Context *rsc) { |
| if (mChannels.size() == 0) { |
| return NULL; |
| } |
| |
| // Generate the element that describes our channel layout |
| Element::Builder vtxBuilder; |
| for (uint32_t c = 0; c < mChannels.size(); c ++) { |
| // Skip empty channels |
| if (mChannels[c].mData.size() == 0) { |
| continue; |
| } |
| ObjectBaseRef<const Element> subElem = Element::createRef(rsc, |
| RS_TYPE_FLOAT_32, |
| RS_KIND_USER, |
| false, |
| mChannels[c].mStride); |
| vtxBuilder.add(subElem.get(), mChannels[c].mName.c_str(), 1); |
| } |
| ObjectBaseRef<const Element> vertexDataElem = vtxBuilder.create(rsc); |
| |
| uint32_t numVerts = mChannels[0].mData.size()/mChannels[0].mStride; |
| ObjectBaseRef<Type> vertexDataType = Type::getTypeRef(rsc, vertexDataElem.get(), |
| numVerts, 0, 0, false, false); |
| vertexDataType->compute(); |
| |
| Allocation *vertexAlloc = Allocation::createAllocation(rsc, vertexDataType.get(), |
| 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 |
| ObjectBaseRef<const Element> indexElem = Element::createRef(rsc, RS_TYPE_UNSIGNED_16, |
| RS_KIND_USER, false, 1); |
| |
| Mesh *mesh = new Mesh(rsc, 1, mTriangleLists.size()); |
| mesh->setName(mName.c_str()); |
| mesh->setVertexBuffer(vertexAlloc, 0); |
| |
| // load all primitives |
| for (uint32_t pCount = 0; pCount < mTriangleLists.size(); pCount ++) { |
| |
| uint32_t numIndicies = mTriangleLists[pCount].size(); |
| ObjectBaseRef<Type> indexType = Type::getTypeRef(rsc, indexElem.get(), |
| numIndicies, 0, 0, false, false ); |
| |
| indexType->compute(); |
| |
| Allocation *indexAlloc = Allocation::createAllocation(rsc, indexType.get(), |
| RS_ALLOCATION_USAGE_SCRIPT); |
| uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr(); |
| const std::vector<uint32_t> &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()); |
| mesh->setPrimitive(indexAlloc, RS_PRIMITIVE_TRIANGLE, pCount); |
| } |
| |
| return mesh; |
| } |
| }; |
| |
| #endif |