Home | History | Annotate | Download | only in a3dconvert
      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