• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
appendFaceList(std::string name)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.)
appendChannel(std::string name,uint32_t stride)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 
SimpleMesh()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
getRsMesh(Context * rsc)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