c++ Assimp::嵌入纹理未在glb 2/gltf 2中导出

h4cxqtbf  于 2022-12-24  发布在  其他
关注(0)|答案(1)|浏览(574)

使用立方体创建一个新的场景,在其上添加嵌入纹理,将场景导出到glb 2。输出文件(test_1.glb)有一个破碎的纹理,纹理-〉mheight = 0,格式为nullimage texture file output.jpg纹理来自JPEG文件(“output.jpg”),宽度为200像素,高度为300像素。

// Create fresh secen
aiScene *scene_1 = new aiScene;
scene_1->mRootNode = new aiNode();

// add 2 materials
scene_1->mMaterials = new aiMaterial*[ 2 ];
scene_1->mMaterials[ 0 ] = nullptr;
scene_1->mMaterials[ 1 ] = nullptr;
scene_1->mNumMaterials = 2;

scene_1->mMaterials[ 0 ] = new aiMaterial();
scene_1->mMaterials[ 1 ] = new aiMaterial();

    
// add 2 textures
scene_1->mTextures = new aiTexture*[ 2 ];
scene_1->mTextures[ 0 ] = nullptr;
scene_1->mTextures[ 1 ] = nullptr;
scene_1->mNumTextures = 2;

scene_1->mTextures[ 0 ] = new aiTexture();
scene_1->mTextures[ 1 ] = new aiTexture();

scene_1->mMeshes = new aiMesh*[ 1 ];
scene_1->mMeshes[ 0 ] = nullptr;
scene_1->mNumMeshes = 1;

scene_1->mMeshes[ 0 ] = new aiMesh();
scene_1->mMeshes[ 0 ]->mMaterialIndex = 1;

scene_1->mRootNode->mMeshes = new unsigned int[ 1 ];
scene_1->mRootNode->mMeshes[ 0 ] = 0;
scene_1->mRootNode->mNumMeshes = 1;

auto pMesh = scene_1->mMeshes[ 0 ];
pMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;

std::vector<glm::vec3> vertices;
std::vector<glm::vec3> normals;
std::vector<glm::vec2> uvs;

//Default Fill Location Vector                                   
int draw_order[36] =                                             
{                                                                
    0,2,1,      2,3,1,                                           
    1,3,5,      3,7,5,                                           
    5,7,4,      7,6,4,                                           
    4,6,0,      6,2,0,                                           
    4,0,5,      0,1,5,                                           
    2,6,3,      6,7,3                                            
};                                                               

glm::vec3 data[8] =                                              
{                                                                
    glm::vec3(-1.0f/2.0f,1.0f/2.0f,1.0f/2.0f),                       
    glm::vec3(1.0f/2.0f,1.0f/2.0f,1.0f/2.0f),                        
    glm::vec3(-1.0f/2.0f,-1.0f/2.0f,1.0f/2.0f),                      
    glm::vec3(1.0f/2.0f,-1.0f/2.0f,1.0f/2.0f),                       
    glm::vec3(-1.0f/2.0f,1.0f/2.0f,-1.0f/2.0f),                      
    glm::vec3(1.0f/2.0f,1.0f/2.0f,-1.0f/2.0f),                       
    glm::vec3(-1.0f/2.0f,-1.0f/2.0f,-1.0f/2.0f),
    glm::vec3(1.0f/2.0f,-1.0f/2.0f,-1.0f/2.0f)  
};

for(int i = 0; i < 36; i++)
{
    vertices.push_back(data[draw_order[i]]);
}

//Default Fill Normal Vector
for(int i = 0; i < 36; i++)
{
    if(i < 6)       {normals.push_back(glm::vec3(0,0,1));}
    else if(i < 12) {normals.push_back(glm::vec3(1,0,0));}
    else if(i < 18) {normals.push_back(glm::vec3(0,0,-1));}
    else if(i < 24) {normals.push_back(glm::vec3(-1,0,0));}
    else if(i < 30) {normals.push_back(glm::vec3(0,1,0));}
    else if(i < 36) {normals.push_back(glm::vec3(0,- 1,0));}
}

//Default Fill UV Vector
for(int i = 0; i < 6; i++)
{
    uvs.push_back(glm::vec2(0,1));
    uvs.push_back(glm::vec2(0,0));
    uvs.push_back(glm::vec2(1,1));
    uvs.push_back(glm::vec2(0,0));
    uvs.push_back(glm::vec2(1,0));
    uvs.push_back(glm::vec2(1,1));
}

const auto& vVertices = vertices;

pMesh->mVertices = new aiVector3D[ vVertices.size() ];
pMesh->mNormals = new aiVector3D[ vVertices.size() ];
pMesh->mNumVertices = vVertices.size();

pMesh->mTextureCoords[ 0 ] = new aiVector3D[ vVertices.size() ];
pMesh->mNumUVComponents[ 0 ] = vVertices.size();

int j = 0;
for ( auto itr = vVertices.begin(); itr != vVertices.end(); ++itr ) 
{
    pMesh->mVertices[ itr - vVertices.begin() ] = aiVector3D( vVertices[j].x, vVertices[j].y, vVertices[j].z );
    pMesh->mNormals[ itr - vVertices.begin() ] = aiVector3D( normals[j].x, normals[j].y, normals[j].z );
    pMesh->mTextureCoords[0][ itr - vVertices.begin() ] = aiVector3D( uvs[j].x, uvs[j].y, 0 );
    j++;
}

pMesh->mFaces = new aiFace[ vVertices.size() / 3 ];
pMesh->mNumFaces = (unsigned int)(vVertices.size() / 3);

int k = 0;

// create all faces
for(int i = 0; i < (vVertices.size() / 3); i++)
{
    aiFace &face = pMesh->mFaces[i];
    face.mIndices = new unsigned int[3];
    face.mNumIndices = 3;

    face.mIndices[0] = k;
    face.mIndices[1] = k+1;
    face.mIndices[2] = k+2;
    k = k + 3;
}

if(pMesh->HasTextureCoords(0)){

    // read data from JPEG file using libjpeg 
    std::string filename = "output.jpg";

    const char* file_to_open = &filename[0];

    struct jpeg_decompress_struct cinfo;

    struct jpeg_error_mgr jerr;

    FILE * outfile;

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);

    if ((outfile = fopen(file_to_open, "rb")) == NULL) {
        fprintf(stderr, "can't open %s\n", file_to_open);
    }

    jpeg_stdio_src(&cinfo, outfile);    
    jpeg_read_header(&cinfo, TRUE);   // read jpeg file header

    jpeg_start_decompress(&cinfo);    // decompress the file

    int img_width = cinfo.output_width;
    int img_height = cinfo.output_height;

    int channels = cinfo.num_components;

    std::vector<int> color_data;

    unsigned long data_size = img_width * img_height * channels;

    unsigned char * rowptr[1];    // pointer to an row array
    unsigned char * jdata;        // pixel data of image
    jdata = (unsigned char *)malloc(data_size);

    while (cinfo.output_scanline < cinfo.image_height) {

        rowptr[0] = (unsigned char *)jdata +  3* cinfo.image_width * cinfo.output_scanline; 

        jpeg_read_scanlines(&cinfo, rowptr, 1);

    }
    
    // embed texture from the image

    auto texture_1 = scene_1->mTextures[ 0 ];

    texture_1->mWidth = img_width;
    texture_1->mHeight = img_height;

    // specify format hint 
    texture_1->achFormatHint[0] = 'r';
    texture_1->achFormatHint[1] = 'g';
    texture_1->achFormatHint[2] = 'b';
    texture_1->achFormatHint[3] = 'a';
    texture_1->achFormatHint[4] = '8';
    texture_1->achFormatHint[5] = '8';
    texture_1->achFormatHint[6] = '8';
    texture_1->achFormatHint[7] = '0';

    
    aiTexel *temp_1 = new aiTexel [img_width*img_height];
    unsigned int count_1 = 0;
    for(int j = 0; j < img_height; j++){
        for(int k = 0; k < img_width; k++){
            temp_1[count_1].r = jdata[count_1*3 + 0];
            temp_1[count_1].g = jdata[count_1*3 + 1];
            temp_1[count_1].b = jdata[count_1*3 + 2];
            count_1++;
        }
    }

    texture_1->pcData = temp_1; 
    auto temp_material = scene_1->mMaterials[ 1 ];

    aiColor3D color_red(0.6f,0.1f,0.1f);
    int two_sided = 1;
    int uv_mapping = 0;
    aiString mat_1("mat_1");
    temp_material->AddProperty(&mat_1, AI_MATKEY_NAME);
    temp_material->AddProperty<aiColor3D>(&color_red,1, AI_MATKEY_COLOR_DIFFUSE);
    temp_material->AddProperty<int>(&two_sided,1,AI_MATKEY_TWOSIDED);
    temp_material->AddProperty<int>(&uv_mapping,1,AI_MATKEY_MAPPING(aiTextureMapping_UV,0));
    temp_material->AddProperty<int>(&uv_mapping,1,AI_MATKEY_TEXFLAGS(aiTextureFlags_IgnoreAlpha,0)); // TEXFLAGS
    temp_material->AddProperty<int>(&uv_mapping,1,AI_MATKEY_MAPPINGMODE_U(aiTextureMapMode_Wrap,0)); // MAPPINGMODE_U
    temp_material->AddProperty<int>(&uv_mapping,1,AI_MATKEY_MAPPINGMODE_V(aiTextureMapMode_Wrap,0)); // MAPPINGMODE_V
    temp_material->AddProperty<int>(&uv_mapping,1,AI_MATKEY_TEXOP(aiTextureOp_Add,0)); // TEXOP

    aiString dummy_tex("*0");
    
    // add texture "0" (index of the texture in scene_1->mTextures) to the materail "1" (index of the material in scene_1->mMaterials)  
    temp_material->AddProperty(&dummy_tex, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE,0));
    
}

char* mFilePath = " ";

// create exporter
Assimp::Exporter exporter;

mFilePath = "test_1.glb";

exporter.Export(scene_1, "glb2", mFilePath, aiProcess_Triangulate);
r7knjye2

r7knjye21#

您可能已经知道了,但如果嵌入/导出的纹理高度为0,则宽度为贴图的大小,并且数据存储为压缩文件格式(如PNG)。

相关问题