mirror of https://github.com/axmolengine/axmol.git
Merge pull request #12738 from super626/v3.7-release
Update tiny obj loader and fix empty textrue
This commit is contained in:
commit
a2da5d5f9d
|
@ -216,73 +216,24 @@ bool Bundle3D::loadObj(MeshDatas& meshdatas, MaterialDatas& materialdatas, NodeD
|
|||
else
|
||||
mtlPath = fullPath.substr(0, fullPath.find_last_of("\\/") + 1).c_str();
|
||||
|
||||
ObjLoader::shapes_t shapes;
|
||||
auto ret = ObjLoader::LoadObj(shapes, fullPath.c_str(), mtlPath.c_str());
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
auto ret = tinyobj::LoadObj(shapes, materials, fullPath.c_str(), mtlPath.c_str());
|
||||
if (ret.empty())
|
||||
{
|
||||
//fill data
|
||||
MeshData* meshdata = new (std::nothrow) MeshData();
|
||||
MeshVertexAttrib attrib;
|
||||
attrib.size = 3;
|
||||
attrib.type = GL_FLOAT;
|
||||
if (shapes.positions.size())
|
||||
{
|
||||
attrib.vertexAttrib = GLProgram::VERTEX_ATTRIB_POSITION;
|
||||
attrib.attribSizeBytes = attrib.size * sizeof(float);
|
||||
meshdata->attribs.push_back(attrib);
|
||||
|
||||
}
|
||||
bool hasnormal = false, hastex = false;
|
||||
if (shapes.normals.size())
|
||||
{
|
||||
hasnormal = true;
|
||||
attrib.vertexAttrib = GLProgram::VERTEX_ATTRIB_NORMAL;
|
||||
attrib.attribSizeBytes = attrib.size * sizeof(float);;
|
||||
meshdata->attribs.push_back(attrib);
|
||||
}
|
||||
if (shapes.texcoords.size())
|
||||
{
|
||||
hastex = true;
|
||||
attrib.size = 2;
|
||||
attrib.vertexAttrib = GLProgram::VERTEX_ATTRIB_TEX_COORD;
|
||||
attrib.attribSizeBytes = attrib.size * sizeof(float);
|
||||
meshdata->attribs.push_back(attrib);
|
||||
}
|
||||
auto vertexNum = shapes.positions.size() / 3;
|
||||
for(unsigned int i = 0; i < vertexNum; i++)
|
||||
{
|
||||
meshdata->vertex.push_back(shapes.positions[i * 3]);
|
||||
meshdata->vertex.push_back(shapes.positions[i * 3 + 1]);
|
||||
meshdata->vertex.push_back(shapes.positions[i * 3 + 2]);
|
||||
|
||||
if (hasnormal)
|
||||
{
|
||||
meshdata->vertex.push_back(shapes.normals[i * 3]);
|
||||
meshdata->vertex.push_back(shapes.normals[i * 3 + 1]);
|
||||
meshdata->vertex.push_back(shapes.normals[i * 3 + 2]);
|
||||
}
|
||||
|
||||
if (hastex)
|
||||
{
|
||||
meshdata->vertex.push_back(shapes.texcoords[i * 2]);
|
||||
meshdata->vertex.push_back(shapes.texcoords[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
meshdatas.meshDatas.push_back(meshdata);
|
||||
|
||||
//convert material
|
||||
int i = 0;
|
||||
char str[20];
|
||||
std::string dir = "";
|
||||
auto last = fullPath.rfind("/");
|
||||
if (last != -1)
|
||||
dir = fullPath.substr(0, last + 1);
|
||||
|
||||
for (const auto& it : shapes.shapes)
|
||||
{
|
||||
for (auto& material : materials) {
|
||||
NMaterialData materialdata;
|
||||
|
||||
NTextureData tex;
|
||||
tex.filename = it.material.diffuse_texname.empty() ? it.material.diffuse_texname : dir + it.material.diffuse_texname;
|
||||
tex.filename = material.diffuse_texname.empty() ? material.diffuse_texname : dir + material.diffuse_texname;
|
||||
tex.type = NTextureData::Usage::Diffuse;
|
||||
tex.wrapS = GL_CLAMP_TO_EDGE;
|
||||
tex.wrapT = GL_CLAMP_TO_EDGE;
|
||||
|
@ -290,19 +241,91 @@ bool Bundle3D::loadObj(MeshDatas& meshdatas, MaterialDatas& materialdatas, NodeD
|
|||
sprintf(str, "%d", i++);
|
||||
materialdata.textures.push_back(tex);
|
||||
materialdata.id = str;
|
||||
material.name = str;
|
||||
materialdatas.materials.push_back(materialdata);
|
||||
|
||||
meshdata->subMeshIndices.push_back(it.mesh.indices);
|
||||
meshdata->subMeshAABB.push_back(calculateAABB(meshdata->vertex, meshdata->getPerVertexSize(), it.mesh.indices));
|
||||
meshdata->subMeshIds.push_back(str);
|
||||
auto node = new (std::nothrow) NodeData();
|
||||
auto modelnode = new (std::nothrow) ModelData();
|
||||
modelnode->matrialId = str;
|
||||
modelnode->subMeshId = str;
|
||||
node->id = it.name;
|
||||
node->modelNodeDatas.push_back(modelnode);
|
||||
nodedatas.nodes.push_back(node);
|
||||
}
|
||||
|
||||
//convert mesh
|
||||
i = 0;
|
||||
for (auto& shape : shapes) {
|
||||
auto mesh = shape.mesh;
|
||||
MeshData* meshdata = new (std::nothrow) MeshData();
|
||||
MeshVertexAttrib attrib;
|
||||
attrib.size = 3;
|
||||
attrib.type = GL_FLOAT;
|
||||
|
||||
if (mesh.positions.size())
|
||||
{
|
||||
attrib.vertexAttrib = GLProgram::VERTEX_ATTRIB_POSITION;
|
||||
attrib.attribSizeBytes = attrib.size * sizeof(float);
|
||||
meshdata->attribs.push_back(attrib);
|
||||
|
||||
}
|
||||
bool hasnormal = false, hastex = false;
|
||||
if (mesh.normals.size())
|
||||
{
|
||||
hasnormal = true;
|
||||
attrib.vertexAttrib = GLProgram::VERTEX_ATTRIB_NORMAL;
|
||||
attrib.attribSizeBytes = attrib.size * sizeof(float);;
|
||||
meshdata->attribs.push_back(attrib);
|
||||
}
|
||||
if (mesh.texcoords.size())
|
||||
{
|
||||
hastex = true;
|
||||
attrib.size = 2;
|
||||
attrib.vertexAttrib = GLProgram::VERTEX_ATTRIB_TEX_COORD;
|
||||
attrib.attribSizeBytes = attrib.size * sizeof(float);
|
||||
meshdata->attribs.push_back(attrib);
|
||||
}
|
||||
|
||||
auto vertexNum = mesh.positions.size() / 3;
|
||||
for(unsigned int k = 0; k < vertexNum; k++)
|
||||
{
|
||||
meshdata->vertex.push_back(mesh.positions[k * 3]);
|
||||
meshdata->vertex.push_back(mesh.positions[k * 3 + 1]);
|
||||
meshdata->vertex.push_back(mesh.positions[k * 3 + 2]);
|
||||
|
||||
if (hasnormal)
|
||||
{
|
||||
meshdata->vertex.push_back(mesh.normals[k * 3]);
|
||||
meshdata->vertex.push_back(mesh.normals[k * 3 + 1]);
|
||||
meshdata->vertex.push_back(mesh.normals[k * 3 + 2]);
|
||||
}
|
||||
|
||||
if (hastex)
|
||||
{
|
||||
meshdata->vertex.push_back(mesh.texcoords[k * 2]);
|
||||
meshdata->vertex.push_back(mesh.texcoords[k * 2 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
//split into submesh according to material
|
||||
std::map<int, std::vector<unsigned short> > subMeshMap;
|
||||
for (size_t k = 0; k < mesh.material_ids.size(); k++) {
|
||||
int id = mesh.material_ids[k];
|
||||
size_t idx = k * 3;
|
||||
subMeshMap[id].push_back(mesh.indices[idx]);
|
||||
subMeshMap[id].push_back(mesh.indices[idx + 1]);
|
||||
subMeshMap[id].push_back(mesh.indices[idx + 2]);
|
||||
}
|
||||
|
||||
auto node = new (std::nothrow) NodeData();
|
||||
node->id = shape.name;
|
||||
for (auto& submesh : subMeshMap) {
|
||||
meshdata->subMeshIndices.push_back(submesh.second);
|
||||
meshdata->subMeshAABB.push_back(calculateAABB(meshdata->vertex, meshdata->getPerVertexSize(), submesh.second));
|
||||
sprintf(str, "%d", i++);
|
||||
meshdata->subMeshIds.push_back(str);
|
||||
|
||||
auto modelnode = new (std::nothrow) ModelData();
|
||||
modelnode->matrialId = submesh.first == -1 ? "" : materials[submesh.first].name;
|
||||
modelnode->subMeshId = str;
|
||||
node->modelNodeDatas.push_back(modelnode);
|
||||
}
|
||||
nodedatas.nodes.push_back(node);
|
||||
meshdatas.meshDatas.push_back(meshdata);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
CCLOG("warning: load %s file error: %s", fullPath.c_str(), ret.c_str());
|
||||
|
|
|
@ -273,6 +273,9 @@ void Mesh::setTexture(Texture2D* tex)
|
|||
// Texture must be saved for future use
|
||||
// it doesn't matter if the material is already set or not
|
||||
// This functionality is added for compatibility issues
|
||||
if (tex == nullptr)
|
||||
tex = getDummyTexture();
|
||||
|
||||
if (tex != _texture)
|
||||
{
|
||||
CC_SAFE_RETAIN(tex);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,40 +1,19 @@
|
|||
//
|
||||
// Copyright 2012-2013, Syoyo Fujita.
|
||||
// Copyright 2012-2015, Syoyo Fujita.
|
||||
//
|
||||
// Licensed under 2-clause BSD liecense.
|
||||
//
|
||||
// copied from Syoyo Fujita
|
||||
// https://github.com/syoyo/tinyobjloader
|
||||
|
||||
#ifndef __CCOBJLOADER_H__
|
||||
#define __CCOBJLOADER_H__
|
||||
//https://github.com/syoyo/tinyobjloader
|
||||
#ifndef _TINY_OBJ_LOADER_H
|
||||
#define _TINY_OBJ_LOADER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "base/ccTypes.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
/**
|
||||
* @addtogroup _3d
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief .obj file Loader
|
||||
* @js NA
|
||||
* @lua NA
|
||||
**/
|
||||
class ObjLoader
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* model's material struct
|
||||
**/
|
||||
typedef struct
|
||||
{
|
||||
namespace tinyobj {
|
||||
|
||||
typedef struct {
|
||||
std::string name;
|
||||
|
||||
float ambient[3];
|
||||
|
@ -43,8 +22,8 @@ public:
|
|||
float transmittance[3];
|
||||
float emission[3];
|
||||
float shininess;
|
||||
float ior; // index of refraction
|
||||
float dissolve; // 1 == opaque; 0 == fully transparent
|
||||
float ior; // index of refraction
|
||||
float dissolve; // 1 == opaque; 0 == fully transparent
|
||||
// illumination model (see http://www.fileformat.info/format/material/)
|
||||
int illum;
|
||||
|
||||
|
@ -55,61 +34,62 @@ public:
|
|||
std::map<std::string, std::string> unknown_parameter;
|
||||
} material_t;
|
||||
|
||||
/**
|
||||
* model's indices struct
|
||||
**/
|
||||
typedef struct
|
||||
{
|
||||
std::vector<unsigned short> indices;
|
||||
typedef struct {
|
||||
std::vector<float> positions;
|
||||
std::vector<float> normals;
|
||||
std::vector<float> texcoords;
|
||||
std::vector<unsigned short> indices;
|
||||
std::vector<int> material_ids; // per-mesh material ID
|
||||
} mesh_t;
|
||||
|
||||
/**
|
||||
* model's shape struct
|
||||
**/
|
||||
typedef struct
|
||||
{
|
||||
std::string name;
|
||||
material_t material;
|
||||
mesh_t mesh;
|
||||
typedef struct {
|
||||
std::string name;
|
||||
mesh_t mesh;
|
||||
} shape_t;
|
||||
|
||||
/**
|
||||
* model's shapes struct
|
||||
**/
|
||||
typedef struct
|
||||
{
|
||||
std::vector<float> positions;
|
||||
std::vector<float> normals;
|
||||
std::vector<float> texcoords;
|
||||
class MaterialReader {
|
||||
public:
|
||||
MaterialReader() {}
|
||||
virtual ~MaterialReader() {}
|
||||
|
||||
std::vector<shape_t> shapes;
|
||||
|
||||
void reset()
|
||||
{
|
||||
positions.clear();
|
||||
normals.clear();
|
||||
texcoords.clear();
|
||||
shapes.clear();
|
||||
}
|
||||
}shapes_t;
|
||||
virtual std::string operator()(const std::string &matId,
|
||||
std::vector<material_t> &materials,
|
||||
std::map<std::string, int> &matMap) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads .obj from a file.
|
||||
* @param shapes will be filled with parsed shape data
|
||||
* @param filename the .obj file path .
|
||||
* @param mtl_basepath It's optional, and used for base path for .mtl file
|
||||
* @return The function returns error string, return empty string when loading .obj success.
|
||||
*/
|
||||
static std::string LoadObj(
|
||||
shapes_t& shapes, // [output]
|
||||
const char* filename,
|
||||
const char* mtl_basepath = NULL);
|
||||
class MaterialFileReader : public MaterialReader {
|
||||
public:
|
||||
MaterialFileReader(const std::string &mtl_basepath)
|
||||
: m_mtlBasePath(mtl_basepath) {}
|
||||
virtual ~MaterialFileReader() {}
|
||||
virtual std::string operator()(const std::string &matId,
|
||||
std::vector<material_t> &materials,
|
||||
std::map<std::string, int> &matMap);
|
||||
|
||||
private:
|
||||
std::string m_mtlBasePath;
|
||||
};
|
||||
|
||||
/// Loads .obj from a file.
|
||||
/// 'shapes' will be filled with parsed shape data
|
||||
/// The function returns error string.
|
||||
/// Returns empty string when loading .obj success.
|
||||
/// 'mtl_basepath' is optional, and used for base path for .mtl file.
|
||||
std::string LoadObj(std::vector<shape_t> &shapes, // [output]
|
||||
std::vector<material_t> &materials, // [output]
|
||||
const char *filename, const char *mtl_basepath = NULL);
|
||||
|
||||
/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve
|
||||
/// std::istream for materials.
|
||||
/// Returns empty string when loading .obj success.
|
||||
std::string LoadObj(std::vector<shape_t> &shapes, // [output]
|
||||
std::vector<material_t> &materials, // [output]
|
||||
std::istream &inStream, MaterialReader &readMatFn);
|
||||
|
||||
/// Loads materials into std::map
|
||||
/// Returns an empty string if successful
|
||||
std::string LoadMtl(std::map<std::string, int> &material_map,
|
||||
std::vector<material_t> &materials, std::istream &inStream);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// end of 3d group
|
||||
/// @}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif // _TINY_OBJ_LOADER_H
|
||||
#endif // _TINY_OBJ_LOADER_H
|
||||
|
|
|
@ -352,8 +352,7 @@ Sprite3D* Sprite3D::createSprite3DNode(NodeData* nodedata,ModelData* modeldata,c
|
|||
if (modeldata->matrialId == "" && materialdatas.materials.size())
|
||||
{
|
||||
const NTextureData* textureData = materialdatas.materials[0].getTextureData(NTextureData::Usage::Diffuse);
|
||||
if (!textureData->filename.empty())
|
||||
mesh->setTexture(textureData->filename);
|
||||
mesh->setTexture(textureData->filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -361,9 +360,10 @@ Sprite3D* Sprite3D::createSprite3DNode(NodeData* nodedata,ModelData* modeldata,c
|
|||
if(materialData)
|
||||
{
|
||||
const NTextureData* textureData = materialData->getTextureData(NTextureData::Usage::Diffuse);
|
||||
if(textureData && !textureData->filename.empty())
|
||||
if(textureData)
|
||||
{
|
||||
auto tex = Director::getInstance()->getTextureCache()->addImage(textureData->filename);
|
||||
mesh->setTexture(textureData->filename);
|
||||
auto tex = mesh->getTexture();
|
||||
if(tex)
|
||||
{
|
||||
Texture2D::TexParams texParams;
|
||||
|
@ -372,10 +372,8 @@ Sprite3D* Sprite3D::createSprite3DNode(NodeData* nodedata,ModelData* modeldata,c
|
|||
texParams.wrapS = textureData->wrapS;
|
||||
texParams.wrapT = textureData->wrapT;
|
||||
tex->setTexParameters(texParams);
|
||||
mesh->setTexture(tex);
|
||||
mesh->_isTransparent = (materialData->getTextureData(NTextureData::Usage::Transparency) != nullptr);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -506,9 +504,10 @@ void Sprite3D::createNode(NodeData* nodedata, Node* root, const MaterialDatas& m
|
|||
if(materialData)
|
||||
{
|
||||
const NTextureData* textureData = materialData->getTextureData(NTextureData::Usage::Diffuse);
|
||||
if(textureData && !textureData->filename.empty())
|
||||
if(textureData)
|
||||
{
|
||||
auto tex = Director::getInstance()->getTextureCache()->addImage(textureData->filename);
|
||||
mesh->setTexture(textureData->filename);
|
||||
auto tex = mesh->getTexture();
|
||||
if(tex)
|
||||
{
|
||||
Texture2D::TexParams texParams;
|
||||
|
@ -517,10 +516,8 @@ void Sprite3D::createNode(NodeData* nodedata, Node* root, const MaterialDatas& m
|
|||
texParams.wrapS = textureData->wrapS;
|
||||
texParams.wrapT = textureData->wrapT;
|
||||
tex->setTexParameters(texParams);
|
||||
mesh->setTexture(tex);
|
||||
mesh->_isTransparent = (materialData->getTextureData(NTextureData::Usage::Transparency) != nullptr);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue