Ejemplo n.º 1
0
int testEncode(const std::string & fileName, int qcoord, int qtexCoord, int qnormal, O3DGCSC3DMCStreamType streamType)
{
    std::string folder;
    long found = (long) fileName.find_last_of(PATH_SEP);
    if (found != -1)
    {
        folder = fileName.substr(0,found);
    }
    if (folder == "")
    {
        folder = ".";
    }
    std::string file(fileName.substr(found+1));
    std::string outFileName = folder + PATH_SEP + file.substr(0, file.find_last_of(".")) + ".s3d";
    std::vector< Vec3<Real> > points;
    std::vector< Vec3<Real> > normals;
    std::vector< Vec2<Real> > texCoords;
    std::vector< Vec3<Index> > triangles;
    std::vector< unsigned long > matIDs;
    std::vector< Material > materials;
    std::string materialLib;
    std::cout << "Loading " << fileName << " ..." << std::endl;
    bool ret = LoadOBJ(fileName, points, texCoords, normals, triangles, matIDs, materials, materialLib);
    if (!ret)
    {
        std::cout << "Error: LoadOBJ()\n" << std::endl;
        return -1;
    }
    if (points.size() == 0 || triangles.size() == 0)
    {
        std::cout <<  "Error: points.size() == 0 || triangles.size() == 0 \n" << std::endl;
        return -1;
    }
    std::cout << "Done." << std::endl;

    if (materials.size() > 0)
    {
        std::string matFileName = folder + PATH_SEP + file.substr(0, file.find_last_of(".")) + ".mat";
        ret = SaveMaterials(matFileName.c_str(), materials, materialLib);
    }
    if (!ret)
    {
        std::cout << "Error: SaveMatrials()\n" << std::endl;
        return -1;
    }
/*
    ret = SaveOBJ("debug.obj", points, texCoords, normals, triangles, materials, matIDs, materialLib);
    if (!ret)
    {
        std::cout << "Error: SaveOBJ()\n" << std::endl;
        return -1;
    }
*/
    SC3DMCEncodeParams params;
    params.SetStreamType(streamType);
    IndexedFaceSet<Index> ifs;
    params.SetCoordQuantBits(qcoord);
    params.SetNormalQuantBits(qnormal);
    params.SetTexCoordQuantBits(qtexCoord);

    ifs.SetNCoord((unsigned long) points.size());
    ifs.SetNNormal((unsigned long)normals.size());
    ifs.SetNTexCoord((unsigned long)texCoords.size());
    ifs.SetNCoordIndex((unsigned long)triangles.size());

    std::cout << "Mesh info "<< std::endl;
    std::cout << "\t# coords    " << ifs.GetNCoord() << std::endl;
    std::cout << "\t# normals   " << ifs.GetNNormal() << std::endl;
    std::cout << "\t# texcoords " << ifs.GetNTexCoord() << std::endl;
    std::cout << "\t# triangles " << ifs.GetNCoordIndex() << std::endl;

    ifs.SetCoord((Real * const) & (points[0]));
    ifs.SetCoordIndex((Index * const ) &(triangles[0]));
    if (materials.size() > 1)
    {
        ifs.SetMatID((unsigned long * const ) &(matIDs[0]));
    }
    if (normals.size() > 0)
    {
        ifs.SetNormal((Real * const) & (normals[0]));
    }
    if (texCoords.size() > 0)
    {
        ifs.SetTexCoord((Real * const ) & (texCoords[0]));
    }

    // compute min/max
    ifs.ComputeMinMax(O3DGC_SC3DMC_MAX_ALL_DIMS); // O3DGC_SC3DMC_DIAG_BB

    BinaryStream bstream((unsigned long)points.size()*8);

    
    SC3DMCEncoder<Index> encoder;
    Timer timer;
    timer.Tic();
    encoder.Encode(params, ifs, bstream);
    timer.Toc();
    std::cout << "Encode time (ms) " << timer.GetElapsedTime() << std::endl;

    FILE * fout = fopen(outFileName.c_str(), "wb");
    if (!fout)
    {
        return -1;
    }
    fwrite(bstream.GetBuffer(), 1, bstream.GetSize(), fout);
    fclose(fout);
    std::cout << "Bitstream size (bytes) " << bstream.GetSize() << std::endl;

    std::cout << "Details" << std::endl;
    const SC3DMCStats & stats = encoder.GetStats();
    std::cout << "\t CoordIndex         " << stats.m_timeCoordIndex     << " ms, " << stats.m_streamSizeCoordIndex     <<" bytes (" << 8.0 * stats.m_streamSizeCoordIndex     / ifs.GetNCoord() <<" bpv)" <<std::endl;
    std::cout << "\t Coord              " << stats.m_timeCoord          << " ms, " << stats.m_streamSizeCoord          <<" bytes (" << 8.0 * stats.m_streamSizeCoord          / ifs.GetNCoord() <<" bpv)" <<std::endl;
    std::cout << "\t Normal             " << stats.m_timeNormal         << " ms, " << stats.m_streamSizeNormal         <<" bytes (" << 8.0 * stats.m_streamSizeNormal         / ifs.GetNCoord() <<" bpv)" <<std::endl;
    std::cout << "\t TexCoord           " << stats.m_timeTexCoord       << " ms, " << stats.m_streamSizeTexCoord       <<" bytes (" << 8.0 * stats.m_streamSizeTexCoord       / ifs.GetNCoord() <<" bpv)" <<std::endl;
    std::cout << "\t Color              " << stats.m_timeColor          << " ms, " << stats.m_streamSizeColor          <<" bytes (" << 8.0 * stats.m_streamSizeColor          / ifs.GetNCoord() <<" bpv)" <<std::endl;
    std::cout << "\t Float Attributes   " << stats.m_timeFloatAttribute << " ms, " << stats.m_streamSizeFloatAttribute <<" bytes (" << 8.0 * stats.m_streamSizeFloatAttribute / ifs.GetNCoord() <<" bpv)" <<std::endl;
    std::cout << "\t Integer Attributes " << stats.m_timeFloatAttribute << " ms, " << stats.m_streamSizeFloatAttribute <<" bytes (" << 8.0 * stats.m_streamSizeFloatAttribute / ifs.GetNCoord() <<" bpv)" <<std::endl;

    return 0;
}
Ejemplo n.º 2
0
    void encodeOpen3DGCMesh(shared_ptr <GLTFMesh> mesh,
                            shared_ptr<JSONObject> floatAttributeIndexMapping,
                            const GLTFConverterContext& converterContext)
    {
        o3dgc::SC3DMCEncodeParams params;
        o3dgc::IndexedFaceSet <unsigned short> ifs;

        //setup options
        int qcoord    = 12;
        int qtexCoord = 10;
        int qnormal   = 10;
        int qcolor   = 10;
        int qWeights = 8;
        
        GLTFOutputStream *outputStream = converterContext._compressionOutputStream;
        size_t bufferOffset = outputStream->length();
        
        O3DGCSC3DMCPredictionMode floatAttributePrediction = O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION;
        
        unsigned int nFloatAttributes = 0;
        
        PrimitiveVector primitives = mesh->getPrimitives();
        unsigned int primitivesCount =  (unsigned int)primitives.size();
        unsigned int allIndicesCount = 0;
        unsigned int allTrianglesCount = 0;
        
        std::vector <unsigned int> trianglesPerPrimitive;
        
        //First run through primitives to gather the number of indices and infer the number of triangles.
        for (unsigned int i = 0 ; i < primitivesCount ; i++) {
            shared_ptr<GLTF::GLTFPrimitive> primitive = primitives[i];
            shared_ptr <GLTF::GLTFIndices> uniqueIndices = primitive->getUniqueIndices();
            unsigned int indicesCount = (unsigned int)(uniqueIndices->getCount());
            //FIXME: assumes triangles, but we are guarded from issues by canEncodeOpen3DGCMesh
            allIndicesCount += indicesCount;
            trianglesPerPrimitive.push_back(indicesCount / 3);
        }
        
        //Then we setup the matIDs array and at the same time concatenate all triangle indices
        unsigned long *primitiveIDs = (unsigned long*)malloc(sizeof(unsigned long) * (allIndicesCount / 3));
        unsigned long *primitiveIDsPtr = primitiveIDs;
        unsigned short* allConcatenatedIndices = (unsigned short*)malloc(allIndicesCount * sizeof(unsigned short));
        unsigned short* allConcatenatedIndicesPtr = allConcatenatedIndices;
        
        for (unsigned int i = 0 ; i < trianglesPerPrimitive.size() ; i++) {
            unsigned int trianglesCount = trianglesPerPrimitive[i];
            for (unsigned int j = 0 ; j < trianglesCount ; j++) {
                primitiveIDsPtr[j] = i;
            }
            primitiveIDsPtr += trianglesCount;
            allTrianglesCount += trianglesCount;
            shared_ptr<GLTF::GLTFPrimitive> primitive = primitives[i];
            shared_ptr <GLTF::GLTFIndices> uniqueIndices = primitive->getUniqueIndices();
            unsigned int indicesCount = (unsigned int)(uniqueIndices->getCount());
            unsigned int* indicesPtr = (unsigned int*)uniqueIndices->getBufferView()->getBufferDataByApplyingOffset();
            for (unsigned int j = 0 ; j < indicesCount ; j++) {
                allConcatenatedIndicesPtr[j] = indicesPtr[j];
            }
            allConcatenatedIndicesPtr += indicesCount;
        }
        
        //FIXME:Open3DGC SetNCoordIndex is not a good name here (file against o3dgc)
        ifs.SetNCoordIndex(allTrianglesCount);
        ifs.SetCoordIndex((unsigned short * const ) allConcatenatedIndices);
        ifs.SetIndexBufferID(primitiveIDs);
        
        size_t vertexCount = 0;
        
        std::vector <GLTF::Semantic> semantics = mesh->allSemantics();
        for (unsigned int i = 0 ; i < semantics.size() ; i ++) {
            GLTF::Semantic semantic  = semantics[i];
            
            size_t attributesCount = mesh->getMeshAttributesCountForSemantic(semantic);
            
            for (size_t j = 0 ; j < attributesCount ; j++) {
                shared_ptr <GLTFMeshAttribute> meshAttribute = mesh->getMeshAttribute(semantic, j);
                vertexCount = meshAttribute->getCount();
                size_t componentsPerAttribute = meshAttribute->getComponentsPerAttribute();
                char *buffer = (char*)meshAttribute->getBufferView()->getBufferDataByApplyingOffset();
                switch (semantic) {
                    case POSITION:
                        params.SetCoordQuantBits(qcoord);
                        params.SetCoordPredMode(floatAttributePrediction);
                        ifs.SetNCoord(vertexCount);
                        ifs.SetCoord((Real * const)buffer);
                        break;
                    case NORMAL:
                        params.SetNormalQuantBits(qnormal);
                        params.SetNormalPredMode(O3DGC_SC3DMC_SURF_NORMALS_PREDICTION);
                        ifs.SetNNormal(vertexCount);
                        ifs.SetNormal((Real * const)buffer);
                        break;
                    case TEXCOORD:
                        params.SetFloatAttributeQuantBits(nFloatAttributes, qtexCoord);
                        params.SetFloatAttributePredMode(nFloatAttributes, floatAttributePrediction);
                        ifs.SetNFloatAttribute(nFloatAttributes, vertexCount);
                        ifs.SetFloatAttributeDim(nFloatAttributes, componentsPerAttribute);
                        ifs.SetFloatAttributeType(nFloatAttributes, O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_TEXCOORD);
                        ifs.SetFloatAttribute(nFloatAttributes, (Real * const)buffer);
                        floatAttributeIndexMapping->setUnsignedInt32(meshAttribute->getID(), nFloatAttributes);
                        nFloatAttributes++;
                        break;
                    case COLOR:
                        params.SetFloatAttributeQuantBits(nFloatAttributes, qcolor);
                        params.SetFloatAttributePredMode(nFloatAttributes, floatAttributePrediction);
                        ifs.SetNFloatAttribute(nFloatAttributes, vertexCount);
                        ifs.SetFloatAttributeDim(nFloatAttributes, componentsPerAttribute);
                        ifs.SetFloatAttributeType(nFloatAttributes, O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_COLOR);
                        ifs.SetFloatAttribute(nFloatAttributes, (Real * const)buffer);
                        floatAttributeIndexMapping->setUnsignedInt32(meshAttribute->getID(), nFloatAttributes);
                        nFloatAttributes++;
                        break;
                    case WEIGHT:
                        params.SetFloatAttributeQuantBits(nFloatAttributes, qWeights);
                        params.SetFloatAttributePredMode(nFloatAttributes, O3DGC_SC3DMC_DIFFERENTIAL_PREDICTION);
                        ifs.SetNFloatAttribute(nFloatAttributes, vertexCount);
                        ifs.SetFloatAttributeDim(nFloatAttributes, componentsPerAttribute);
                        ifs.SetFloatAttributeType(nFloatAttributes, O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_WEIGHT);
                        ifs.SetFloatAttribute(nFloatAttributes, (Real * const)buffer);
                        floatAttributeIndexMapping->setUnsignedInt32(meshAttribute->getID(), nFloatAttributes);
                        nFloatAttributes++;
                        break;
                    case JOINT:
                        /*
                         params.SetIntAttributePredMode(nIntAttributes, O3DGC_SC3DMC_DIFFERENTIAL_PREDICTION);
                         ifs.SetNIntAttribute(nIntAttributes, jointIDs.size() / numJointsPerVertex);
                         ifs.SetIntAttributeDim(nIntAttributes, numJointsPerVertex);
                         ifs.SetIntAttributeType(nIntAttributes, O3DGC_IFS_INT_ATTRIBUTE_TYPE_JOINT_ID);
                         ifs.SetIntAttribute(nIntAttributes, (long * const ) & (jointIDs[0]));
                         nIntAttributes++;
                         */
                        params.SetFloatAttributeQuantBits(nFloatAttributes, 10);
                        params.SetFloatAttributePredMode(nFloatAttributes, O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION);
                        ifs.SetNFloatAttribute(nFloatAttributes, vertexCount);
                        ifs.SetFloatAttributeDim(nFloatAttributes, componentsPerAttribute);
                        ifs.SetFloatAttributeType(nFloatAttributes, O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_UNKOWN);
                        ifs.SetFloatAttribute(nFloatAttributes, (Real * const)buffer);
                        floatAttributeIndexMapping->setUnsignedInt32(meshAttribute->getID(), nFloatAttributes);
                        nFloatAttributes++;
                        break;
                    default:
                        break;
                }
            }
        }
        
        params.SetNumFloatAttributes(nFloatAttributes);
        ifs.SetNumFloatAttributes(nFloatAttributes);
        shared_ptr<JSONObject> compressionObject = static_pointer_cast<JSONObject>(mesh->getExtensions()->createObjectIfNeeded("Open3DGC-compression"));
        
        ifs.ComputeMinMax(O3DGC_SC3DMC_MAX_ALL_DIMS);
        BinaryStream bstream(vertexCount * 8);
        SC3DMCEncoder <unsigned short> encoder;
        shared_ptr<JSONObject> compressedData(new JSONObject());
        compressedData->setInt32("verticesCount", vertexCount);
        compressedData->setInt32("indicesCount", allIndicesCount);
        //Open3DGC binary is disabled
        params.SetStreamType(converterContext.compressionMode == "binary" ? O3DGC_STREAM_TYPE_BINARY : O3DGC_STREAM_TYPE_ASCII);
#if DUMP_O3DGC_OUTPUT
        static int dumpedId = 0;
        COLLADABU::URI outputURI(converterContext.outputFilePath.c_str());
        std::string outputFilePath = outputURI.getPathDir() + GLTFUtils::toString(dumpedId) + ".txt";
        dumpedId++;
        SaveIFS(outputFilePath, ifs);
#endif
        encoder.Encode(params, ifs, bstream);
        
        compressedData->setString("mode", converterContext.compressionMode);
        compressedData->setUnsignedInt32("count", bstream.GetSize());
        compressedData->setUnsignedInt32("type", converterContext.profile->getGLenumForString("UNSIGNED_BYTE"));
        compressedData->setUnsignedInt32("byteOffset", bufferOffset);
        compressedData->setValue("floatAttributesIndexes", floatAttributeIndexMapping);
        
        compressionObject->setValue("compressedData", compressedData);
        
        //testDecode(mesh, bstream);
        outputStream->write((const char*)bstream.GetBuffer(0), bstream.GetSize());
        
        if (ifs.GetCoordIndex()) {
            free(ifs.GetCoordIndex());
        }
        
        if (primitiveIDs) {
            free(primitiveIDs);
        }
    }