2014-05-19 05:49:16 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2014 Chukong Technologies Inc.
|
|
|
|
|
|
|
|
http://www.cocos2d-x.org
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include "3d/CCSprite3D.h"
|
|
|
|
#include "3d/CCMesh.h"
|
|
|
|
#include "3d/CCObjLoader.h"
|
2014-06-04 18:17:09 +08:00
|
|
|
#include "3d/CCMeshSkin.h"
|
2014-06-05 16:36:01 +08:00
|
|
|
#include "3d/CCBundle3D.h"
|
2014-06-16 20:58:13 +08:00
|
|
|
#include "3d/CCSprite3DMaterial.h"
|
2014-07-29 10:49:06 +08:00
|
|
|
#include "3d/CCSubMesh.h"
|
|
|
|
#include "3d/CCAttachNode.h"
|
|
|
|
#include "3d/CCSubMeshState.h"
|
2014-07-30 18:32:34 +08:00
|
|
|
#include "3d/CCSkeleton3D.h"
|
2014-05-19 05:49:16 +08:00
|
|
|
|
|
|
|
#include "base/CCDirector.h"
|
|
|
|
#include "base/CCPlatformMacros.h"
|
|
|
|
#include "base/ccMacros.h"
|
|
|
|
#include "platform/CCFileUtils.h"
|
|
|
|
#include "renderer/CCTextureCache.h"
|
|
|
|
#include "renderer/CCRenderer.h"
|
|
|
|
#include "renderer/CCGLProgramState.h"
|
|
|
|
#include "renderer/CCGLProgramCache.h"
|
|
|
|
|
|
|
|
#include "deprecated/CCString.h" // For StringUtils::format
|
|
|
|
|
|
|
|
NS_CC_BEGIN
|
|
|
|
|
2014-06-04 18:17:09 +08:00
|
|
|
std::string s_attributeNames[] = {GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::ATTRIBUTE_NAME_COLOR, GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::ATTRIBUTE_NAME_NORMAL, GLProgram::ATTRIBUTE_NAME_BLEND_WEIGHT, GLProgram::ATTRIBUTE_NAME_BLEND_INDEX};
|
2014-05-19 05:49:16 +08:00
|
|
|
|
|
|
|
Sprite3D* Sprite3D::create(const std::string &modelPath)
|
|
|
|
{
|
|
|
|
if (modelPath.length() < 4)
|
|
|
|
CCASSERT(false, "improper name specified when creating Sprite3D");
|
|
|
|
|
|
|
|
auto sprite = new Sprite3D();
|
|
|
|
if (sprite && sprite->initWithFile(modelPath))
|
|
|
|
{
|
|
|
|
sprite->autorelease();
|
|
|
|
return sprite;
|
|
|
|
}
|
|
|
|
CC_SAFE_DELETE(sprite);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
Sprite3D* Sprite3D::create(const std::string &modelPath, const std::string &texturePath)
|
|
|
|
{
|
|
|
|
auto sprite = create(modelPath);
|
|
|
|
if (sprite)
|
|
|
|
{
|
|
|
|
sprite->setTexture(texturePath);
|
|
|
|
}
|
|
|
|
|
|
|
|
return sprite;
|
|
|
|
}
|
|
|
|
|
2014-07-29 10:49:06 +08:00
|
|
|
bool Sprite3D::loadFromCache(const std::string& path)
|
2014-05-19 05:49:16 +08:00
|
|
|
{
|
|
|
|
std::string fullPath = FileUtils::getInstance()->fullPathForFilename(path);
|
|
|
|
|
2014-06-16 20:58:13 +08:00
|
|
|
//find from the cache
|
|
|
|
std::string key = fullPath + "#";
|
|
|
|
auto mesh = MeshCache::getInstance()->getMesh(key);
|
|
|
|
if (mesh)
|
|
|
|
{
|
|
|
|
_mesh = mesh;
|
|
|
|
_mesh->retain();
|
|
|
|
|
2014-07-29 10:49:06 +08:00
|
|
|
char str[20];
|
|
|
|
for (int i = 0; i < (int)_mesh->getSubMeshCount(); i++) {
|
|
|
|
sprintf(str, "submesh%d", i);
|
|
|
|
std::string submeshkey = key + std::string(str);
|
|
|
|
auto tex = Sprite3DMaterialCache::getInstance()->getSprite3DMaterial(submeshkey);
|
|
|
|
auto submeshstate = SubMeshState::create();
|
|
|
|
submeshstate->setTexture(tex);
|
|
|
|
_subMeshStates.pushBack(submeshstate);
|
|
|
|
}
|
|
|
|
|
2014-07-30 18:32:34 +08:00
|
|
|
_skeleton = Skeleton3D::create(fullPath, "");
|
|
|
|
CC_SAFE_RETAIN(_skeleton);
|
|
|
|
_skin = MeshSkin::create(_skeleton, fullPath, "");
|
2014-07-29 10:49:06 +08:00
|
|
|
CC_SAFE_RETAIN(_skin);
|
2014-06-16 20:58:13 +08:00
|
|
|
|
|
|
|
genGLProgramState();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-07-29 10:49:06 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//.mtl file should at the same directory with the same name if exist
|
|
|
|
bool Sprite3D::loadFromObj(const std::string& path)
|
|
|
|
{
|
|
|
|
std::string fullPath = FileUtils::getInstance()->fullPathForFilename(path);
|
|
|
|
std::string key = fullPath + "#";
|
|
|
|
|
2014-08-17 22:49:53 +08:00
|
|
|
MeshDatas meshdatas;
|
|
|
|
MaterialDatas materialdatas;
|
|
|
|
NodeDatas nodeDatas;
|
|
|
|
bool ret = Bundle3D::loadObj(meshdatas, materialdatas, nodeDatas, fullPath);
|
|
|
|
if (ret)
|
2014-05-19 05:49:16 +08:00
|
|
|
{
|
2014-08-17 22:49:53 +08:00
|
|
|
for( int i = 0 ; i < meshdatas.meshDatas.size() ; i++ )
|
|
|
|
{
|
|
|
|
MeshData* meshData= meshdatas.meshDatas[i];
|
|
|
|
if(meshData)
|
|
|
|
{
|
|
|
|
Mesh* mesh = Mesh::create(*meshData);
|
|
|
|
_meshes.pushBack(mesh);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for(int i = 0; i < nodeDatas.nodes.size(); i++ )
|
|
|
|
{
|
|
|
|
NodeData* nodeData= nodeDatas.nodes[i];
|
|
|
|
if(nodeData)
|
|
|
|
{
|
|
|
|
createNode(nodeData, this, materialdatas);
|
|
|
|
}
|
|
|
|
}
|
2014-05-19 05:49:16 +08:00
|
|
|
}
|
2014-08-17 22:49:53 +08:00
|
|
|
// //add mesh to cache
|
|
|
|
// MeshCache::getInstance()->addMesh(key, _mesh);
|
2014-07-29 10:49:06 +08:00
|
|
|
|
2014-05-19 05:49:16 +08:00
|
|
|
genGLProgramState();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2014-08-15 17:46:21 +08:00
|
|
|
bool Sprite3D::loadFromC3x_0_3(const std::string& path)
|
|
|
|
{
|
|
|
|
std::string fullPath = FileUtils::getInstance()->fullPathForFilename(path);
|
|
|
|
std::string key = fullPath + "#";
|
|
|
|
|
|
|
|
//load from .c3b or .c3t
|
|
|
|
auto bundle = Bundle3D::getInstance();
|
|
|
|
if (!bundle->load(fullPath))
|
|
|
|
return false;
|
2014-08-16 14:16:17 +08:00
|
|
|
|
2014-08-15 17:46:21 +08:00
|
|
|
MeshDatas meshdatas;
|
|
|
|
bool ret = bundle->loadMeshDatas(meshdatas);
|
|
|
|
if (!ret)
|
|
|
|
{
|
2014-08-15 18:20:37 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
for( int i = 0 ; i < meshdatas.meshDatas.size() ; i++ )
|
|
|
|
{
|
|
|
|
MeshData* meshData= meshdatas.meshDatas[i];
|
|
|
|
if(meshData)
|
2014-08-15 17:46:21 +08:00
|
|
|
{
|
2014-08-15 20:52:45 +08:00
|
|
|
Mesh* mesh = Mesh::create(*meshData);
|
|
|
|
_meshes.pushBack(mesh);
|
2014-08-15 17:46:21 +08:00
|
|
|
}
|
|
|
|
}
|
2014-08-15 20:52:45 +08:00
|
|
|
|
2014-08-15 17:46:21 +08:00
|
|
|
MaterialDatas materialdatas;
|
|
|
|
ret = bundle->loadMaterials(materialdatas);
|
2014-08-16 14:49:38 +08:00
|
|
|
if (!ret)
|
2014-08-15 17:46:21 +08:00
|
|
|
{
|
2014-08-16 10:41:42 +08:00
|
|
|
return false;
|
2014-08-15 17:46:21 +08:00
|
|
|
}
|
|
|
|
NodeDatas nodeDatas;
|
|
|
|
bundle->loadNodes(nodeDatas);
|
2014-08-15 20:52:45 +08:00
|
|
|
_skeleton = Skeleton3D::create(nodeDatas.skeleton);
|
|
|
|
CC_SAFE_RETAIN(_skeleton);
|
|
|
|
|
2014-08-15 17:46:21 +08:00
|
|
|
for(int i = 0; i < nodeDatas.nodes.size(); i++ )
|
|
|
|
{
|
|
|
|
NodeData* nodeData= nodeDatas.nodes[i];
|
|
|
|
if(nodeData)
|
|
|
|
{
|
2014-08-15 20:52:45 +08:00
|
|
|
createNode(nodeData, this, materialdatas);
|
2014-08-15 17:46:21 +08:00
|
|
|
}
|
|
|
|
}
|
2014-08-15 20:52:45 +08:00
|
|
|
|
2014-08-15 17:46:21 +08:00
|
|
|
genGLProgramState();
|
|
|
|
return true;
|
|
|
|
}
|
2014-06-05 16:36:01 +08:00
|
|
|
bool Sprite3D::loadFromC3x(const std::string& path)
|
2014-06-04 18:17:09 +08:00
|
|
|
{
|
2014-06-05 16:36:01 +08:00
|
|
|
std::string fullPath = FileUtils::getInstance()->fullPathForFilename(path);
|
2014-06-16 20:58:13 +08:00
|
|
|
std::string key = fullPath + "#";
|
|
|
|
|
|
|
|
//load from .c3b or .c3t
|
2014-06-05 18:21:25 +08:00
|
|
|
auto bundle = Bundle3D::getInstance();
|
|
|
|
if (!bundle->load(fullPath))
|
2014-06-05 16:36:01 +08:00
|
|
|
return false;
|
|
|
|
|
2014-06-11 18:24:14 +08:00
|
|
|
MeshData meshdata;
|
2014-06-05 18:21:25 +08:00
|
|
|
bool ret = bundle->loadMeshData("", &meshdata);
|
|
|
|
if (!ret)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-07-29 10:49:06 +08:00
|
|
|
_mesh = Mesh::create(meshdata.vertex, meshdata.vertexSizeInFloat, meshdata.subMeshIndices, meshdata.attribs);
|
|
|
|
|
2014-06-06 19:12:08 +08:00
|
|
|
CC_SAFE_RETAIN(_mesh);
|
2014-07-29 10:49:06 +08:00
|
|
|
//add mesh to cache
|
|
|
|
MeshCache::getInstance()->addMesh(key, _mesh);
|
2014-07-30 18:32:34 +08:00
|
|
|
_skeleton = Skeleton3D::create(fullPath, "");
|
|
|
|
CC_SAFE_RETAIN(_skeleton);
|
|
|
|
_skin = MeshSkin::create(_skeleton, fullPath, "");
|
2014-06-09 18:37:58 +08:00
|
|
|
CC_SAFE_RETAIN(_skin);
|
2014-06-05 18:21:25 +08:00
|
|
|
|
2014-06-11 18:24:14 +08:00
|
|
|
MaterialData materialdata;
|
2014-06-05 18:21:25 +08:00
|
|
|
ret = bundle->loadMaterialData("", &materialdata);
|
2014-06-06 19:12:08 +08:00
|
|
|
if (ret)
|
|
|
|
{
|
2014-07-29 10:49:06 +08:00
|
|
|
std::vector<std::string> texpaths;
|
|
|
|
texpaths.resize(_mesh->getSubMeshCount(), "");
|
|
|
|
for (auto& it : materialdata.texturePaths)
|
|
|
|
{
|
|
|
|
texpaths[it.first] = it.second;
|
|
|
|
}
|
|
|
|
genMaterials(key, texpaths);
|
2014-06-06 19:12:08 +08:00
|
|
|
}
|
2014-08-16 14:16:17 +08:00
|
|
|
|
2014-06-06 19:12:08 +08:00
|
|
|
genGLProgramState();
|
2014-06-16 20:58:13 +08:00
|
|
|
|
2014-06-04 18:17:09 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-05-19 05:49:16 +08:00
|
|
|
Sprite3D::Sprite3D()
|
|
|
|
: _mesh(nullptr)
|
2014-06-04 18:17:09 +08:00
|
|
|
, _skin(nullptr)
|
2014-07-30 18:32:34 +08:00
|
|
|
, _skeleton(nullptr)
|
2014-05-19 05:49:16 +08:00
|
|
|
, _blend(BlendFunc::ALPHA_NON_PREMULTIPLIED)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Sprite3D::~Sprite3D()
|
|
|
|
{
|
2014-07-29 10:49:06 +08:00
|
|
|
_subMeshStates.clear();
|
2014-08-15 20:52:45 +08:00
|
|
|
_meshes.clear();
|
2014-05-19 05:49:16 +08:00
|
|
|
CC_SAFE_RELEASE_NULL(_mesh);
|
2014-06-04 18:17:09 +08:00
|
|
|
CC_SAFE_RELEASE_NULL(_skin);
|
2014-07-30 18:32:34 +08:00
|
|
|
CC_SAFE_RELEASE_NULL(_skeleton);
|
2014-07-29 10:49:06 +08:00
|
|
|
removeAllAttachNode();
|
2014-05-19 05:49:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Sprite3D::initWithFile(const std::string &path)
|
|
|
|
{
|
2014-07-29 10:49:06 +08:00
|
|
|
_subMeshStates.clear();
|
2014-05-19 05:49:16 +08:00
|
|
|
CC_SAFE_RELEASE_NULL(_mesh);
|
2014-06-04 18:17:09 +08:00
|
|
|
CC_SAFE_RELEASE_NULL(_skin);
|
2014-07-30 18:32:34 +08:00
|
|
|
CC_SAFE_RELEASE_NULL(_skeleton);
|
2014-07-29 10:49:06 +08:00
|
|
|
|
|
|
|
if (loadFromCache(path))
|
|
|
|
return true;
|
2014-05-19 05:49:16 +08:00
|
|
|
|
2014-06-16 20:58:13 +08:00
|
|
|
//load from file
|
|
|
|
std::string ext = path.substr(path.length() - 4, 4);
|
|
|
|
std::transform(ext.begin(), ext.end(), ext.begin(), tolower);
|
|
|
|
|
|
|
|
if (ext == ".obj")
|
2014-05-19 05:49:16 +08:00
|
|
|
{
|
2014-06-16 20:58:13 +08:00
|
|
|
return loadFromObj(path);
|
2014-05-19 05:49:16 +08:00
|
|
|
}
|
2014-06-16 20:58:13 +08:00
|
|
|
else if (ext == ".c3b" || ext == ".c3t")
|
2014-05-19 05:49:16 +08:00
|
|
|
{
|
2014-08-16 09:59:08 +08:00
|
|
|
return loadFromC3x_0_3(path);
|
2014-05-19 05:49:16 +08:00
|
|
|
}
|
2014-06-16 20:58:13 +08:00
|
|
|
|
|
|
|
return false;
|
2014-05-19 05:49:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Sprite3D::genGLProgramState()
|
|
|
|
{
|
2014-08-16 16:56:04 +08:00
|
|
|
if (_meshes.size() == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
//all the mesh should have the same attributes, FIX ME
|
|
|
|
auto mesh = _meshes.at(0);
|
|
|
|
|
|
|
|
auto programstate = GLProgramState::getOrCreateWithGLProgram(getDefaultGLProgram(mesh->hasVertexAttrib(GLProgram::VERTEX_ATTRIB_TEX_COORD)));
|
2014-05-19 05:49:16 +08:00
|
|
|
long offset = 0;
|
2014-08-16 16:56:04 +08:00
|
|
|
auto attributeCount = mesh->getMeshVertexAttribCount();
|
2014-05-19 05:49:16 +08:00
|
|
|
for (auto k = 0; k < attributeCount; k++) {
|
2014-08-16 16:56:04 +08:00
|
|
|
auto meshattribute = mesh->getMeshVertexAttribute(k);
|
2014-05-19 05:49:16 +08:00
|
|
|
programstate->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib],
|
|
|
|
meshattribute.size,
|
|
|
|
meshattribute.type,
|
|
|
|
GL_FALSE,
|
2014-08-16 16:56:04 +08:00
|
|
|
mesh->getVertexSizeInBytes(),
|
2014-05-19 05:49:16 +08:00
|
|
|
(GLvoid*)offset);
|
|
|
|
offset += meshattribute.attribSizeBytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
setGLProgramState(programstate);
|
2014-08-16 20:38:00 +08:00
|
|
|
auto count = _subMeshStates.size();
|
2014-07-29 10:49:06 +08:00
|
|
|
_meshCommands.resize(count);
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
auto tex = _subMeshStates.at(i)->getTexture();
|
|
|
|
GLuint texID = tex ? tex->getName() : 0;
|
2014-08-16 20:38:00 +08:00
|
|
|
_meshCommands[i].genMaterialID(texID, programstate, _subMeshStates.at(i)->getSubMesh()->getMesh(), _blend);
|
2014-07-29 10:49:06 +08:00
|
|
|
}
|
2014-05-19 05:49:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
GLProgram* Sprite3D::getDefaultGLProgram(bool textured)
|
|
|
|
{
|
2014-08-16 16:56:04 +08:00
|
|
|
if (_meshes.size() == 0)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
//all the mesh should have the same attributes, FIX ME
|
|
|
|
auto mesh = _meshes.at(0);
|
|
|
|
|
|
|
|
bool hasSkin = mesh->hasVertexAttrib(GLProgram::VERTEX_ATTRIB_BLEND_INDEX)
|
|
|
|
&& mesh->hasVertexAttrib(GLProgram::VERTEX_ATTRIB_BLEND_WEIGHT);
|
2014-06-05 16:36:01 +08:00
|
|
|
|
2014-05-19 05:49:16 +08:00
|
|
|
if(textured)
|
|
|
|
{
|
2014-06-05 16:36:01 +08:00
|
|
|
if (hasSkin)
|
|
|
|
return GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_SKINPOSITION_TEXTURE);
|
|
|
|
|
2014-05-19 05:49:16 +08:00
|
|
|
return GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_POSITION_TEXTURE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_POSITION);
|
|
|
|
}
|
|
|
|
}
|
2014-08-15 20:52:45 +08:00
|
|
|
void Sprite3D::createNode(NodeData* nodedata, Node* root, const MaterialDatas& matrialdatas)
|
2014-08-15 17:46:21 +08:00
|
|
|
{
|
|
|
|
Node* node=nullptr;
|
|
|
|
ModelNodeData* modelNodeData=nodedata->asModelNodeData();
|
|
|
|
if(modelNodeData)
|
|
|
|
{
|
2014-08-18 10:32:23 +08:00
|
|
|
if(modelNodeData->bones.size() > 0)
|
2014-08-15 17:46:21 +08:00
|
|
|
{
|
2014-08-18 10:32:23 +08:00
|
|
|
auto subMeshState = SubMeshState::create(modelNodeData->id);
|
|
|
|
if(subMeshState)
|
2014-08-17 22:49:53 +08:00
|
|
|
{
|
2014-08-18 10:32:23 +08:00
|
|
|
_subMeshStates.pushBack(subMeshState);
|
|
|
|
subMeshState->setSubMesh(getSubMesh(modelNodeData->subMeshId));
|
|
|
|
if (_skeleton && modelNodeData->bones.size())
|
|
|
|
{
|
|
|
|
auto skin = MeshSkin::create(_skeleton, modelNodeData->bones, modelNodeData->invBindPose);
|
|
|
|
subMeshState->setSkin(skin);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (modelNodeData->matrialId == "" && matrialdatas.materials.size())
|
|
|
|
{
|
|
|
|
const NTextureData* textureData = matrialdatas.materials[0].getTextureData(NTextureData::Usage::Diffuse);
|
|
|
|
subMeshState->setTexture(textureData->filename);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const NMaterialData* materialData=matrialdatas.getMaterialData(modelNodeData->matrialId);
|
|
|
|
if(materialData)
|
|
|
|
{
|
|
|
|
const NTextureData* textureData = materialData->getTextureData(NTextureData::Usage::Diffuse);
|
|
|
|
if(textureData)
|
|
|
|
{
|
|
|
|
auto tex = Director::getInstance()->getTextureCache()->addImage(textureData->filename);
|
|
|
|
if(tex)
|
|
|
|
{
|
|
|
|
Texture2D::TexParams texParams;
|
|
|
|
texParams.minFilter = GL_LINEAR;
|
|
|
|
texParams.magFilter = GL_LINEAR;
|
|
|
|
texParams.wrapS = textureData->wrapS;
|
|
|
|
texParams.wrapT = textureData->wrapT;
|
|
|
|
tex->setTexParameters(texParams);
|
|
|
|
subMeshState->setTexture(tex);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-08-16 14:49:38 +08:00
|
|
|
}
|
2014-08-18 10:32:23 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
auto sprite = new Sprite3D();
|
|
|
|
if (sprite)
|
2014-08-16 10:41:42 +08:00
|
|
|
{
|
2014-08-18 10:32:23 +08:00
|
|
|
auto subMeshState = SubMeshState::create(modelNodeData->id);
|
|
|
|
subMeshState->setSubMesh(getSubMesh(modelNodeData->subMeshId));
|
|
|
|
if (modelNodeData->matrialId == "" && matrialdatas.materials.size())
|
|
|
|
{
|
|
|
|
const NTextureData* textureData = matrialdatas.materials[0].getTextureData(NTextureData::Usage::Diffuse);
|
|
|
|
subMeshState->setTexture(textureData->filename);
|
|
|
|
}
|
|
|
|
else
|
2014-08-16 16:56:04 +08:00
|
|
|
{
|
2014-08-18 10:32:23 +08:00
|
|
|
const NMaterialData* materialData=matrialdatas.getMaterialData(modelNodeData->matrialId);
|
|
|
|
if(materialData)
|
2014-08-16 16:56:04 +08:00
|
|
|
{
|
2014-08-18 10:32:23 +08:00
|
|
|
const NTextureData* textureData = materialData->getTextureData(NTextureData::Usage::Diffuse);
|
|
|
|
if(textureData)
|
2014-08-16 16:56:04 +08:00
|
|
|
{
|
2014-08-18 10:32:23 +08:00
|
|
|
auto tex = Director::getInstance()->getTextureCache()->addImage(textureData->filename);
|
|
|
|
if(tex)
|
|
|
|
{
|
|
|
|
Texture2D::TexParams texParams;
|
|
|
|
texParams.minFilter = GL_LINEAR;
|
|
|
|
texParams.magFilter = GL_LINEAR;
|
|
|
|
texParams.wrapS = textureData->wrapS;
|
|
|
|
texParams.wrapT = textureData->wrapT;
|
|
|
|
tex->setTexParameters(texParams);
|
|
|
|
subMeshState->setTexture(tex);
|
|
|
|
}
|
|
|
|
|
2014-08-16 16:56:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-08-18 10:32:23 +08:00
|
|
|
sprite->setAdditionalTransform(&nodedata->transform);
|
|
|
|
sprite->addSubMeshState(subMeshState);
|
|
|
|
sprite->autorelease();
|
|
|
|
sprite->genGLProgramState();
|
|
|
|
if(root)
|
|
|
|
{
|
|
|
|
root->addChild(sprite);
|
|
|
|
}
|
2014-08-16 10:41:42 +08:00
|
|
|
}
|
2014-08-18 10:32:23 +08:00
|
|
|
node=sprite;
|
2014-08-15 17:46:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
node= Node::create();
|
|
|
|
if(node)
|
|
|
|
{
|
|
|
|
node->setAdditionalTransform(&nodedata->transform);
|
2014-08-15 18:20:37 +08:00
|
|
|
if(root)
|
|
|
|
{
|
|
|
|
root->addChild(node);
|
|
|
|
}
|
2014-08-15 17:46:21 +08:00
|
|
|
}
|
|
|
|
}
|
2014-08-15 18:20:37 +08:00
|
|
|
for(int i = 0; i < nodedata->children.size(); i++ )
|
2014-08-15 17:46:21 +08:00
|
|
|
{
|
2014-08-15 18:20:37 +08:00
|
|
|
NodeData* childData = nodedata->children[i];
|
|
|
|
if(childData)
|
|
|
|
{
|
2014-08-15 20:52:45 +08:00
|
|
|
createNode(childData,node, matrialdatas);
|
2014-08-15 18:20:37 +08:00
|
|
|
}
|
2014-08-15 17:46:21 +08:00
|
|
|
}
|
|
|
|
}
|
2014-08-15 20:52:45 +08:00
|
|
|
|
|
|
|
SubMesh* Sprite3D::getSubMesh(const std::string& subMeshId) const
|
|
|
|
{
|
|
|
|
for (auto it : _meshes) {
|
|
|
|
auto subMesh = it->getSubMeshById(subMeshId);
|
|
|
|
if (subMesh)
|
|
|
|
return subMesh;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
2014-08-18 10:32:23 +08:00
|
|
|
void Sprite3D::addSubMeshState(SubMeshState* subMeshState)
|
|
|
|
{
|
|
|
|
_meshes.pushBack(subMeshState->getSubMesh()->getMesh());
|
|
|
|
_subMeshStates.pushBack(subMeshState);
|
|
|
|
}
|
2014-07-29 10:49:06 +08:00
|
|
|
void Sprite3D::genMaterials(const std::string& keyprefix, const std::vector<std::string>& texpaths)
|
|
|
|
{
|
|
|
|
_subMeshStates.clear();
|
|
|
|
|
|
|
|
char str[20];
|
|
|
|
auto cache = Director::getInstance()->getTextureCache();
|
|
|
|
int index = 0;
|
|
|
|
for (auto& it : texpaths) {
|
|
|
|
auto tex = cache->addImage(it);
|
|
|
|
auto subMeshState = SubMeshState::create();
|
|
|
|
subMeshState->setTexture(tex);
|
|
|
|
_subMeshStates.pushBack(subMeshState);
|
|
|
|
|
2014-08-17 22:49:53 +08:00
|
|
|
// //add to cache
|
|
|
|
// sprintf(str, "submesh%d", index);
|
|
|
|
// std::string submeshkey = keyprefix + std::string(str);
|
|
|
|
// Sprite3DMaterialCache::getInstance()->addSprite3DMaterial(submeshkey, tex);
|
2014-07-29 10:49:06 +08:00
|
|
|
index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-19 05:49:16 +08:00
|
|
|
void Sprite3D::setTexture(const std::string& texFile)
|
|
|
|
{
|
|
|
|
auto tex = Director::getInstance()->getTextureCache()->addImage(texFile);
|
2014-06-23 19:08:26 +08:00
|
|
|
setTexture(tex);
|
2014-05-19 05:49:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Sprite3D::setTexture(Texture2D* texture)
|
|
|
|
{
|
2014-07-29 10:49:06 +08:00
|
|
|
_subMeshStates.at(0)->setTexture(texture);
|
|
|
|
}
|
|
|
|
AttachNode* Sprite3D::getAttachNode(const std::string& boneName)
|
|
|
|
{
|
|
|
|
auto it = _attachments.find(boneName);
|
|
|
|
if (it != _attachments.end())
|
|
|
|
return it->second;
|
|
|
|
|
|
|
|
if (_skin)
|
|
|
|
{
|
|
|
|
auto bone = _skin->getBoneByName(boneName);
|
|
|
|
auto attachNode = AttachNode::create(bone);
|
|
|
|
addChild(attachNode);
|
|
|
|
_attachments[boneName] = attachNode;
|
|
|
|
return attachNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sprite3D::removeAttachNode(const std::string& boneName)
|
|
|
|
{
|
|
|
|
auto it = _attachments.find(boneName);
|
|
|
|
if (it != _attachments.end())
|
|
|
|
{
|
|
|
|
removeChild(it->second);
|
|
|
|
_attachments.erase(it);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sprite3D::removeAllAttachNode()
|
|
|
|
{
|
|
|
|
for (auto& it : _attachments) {
|
|
|
|
removeChild(it.second);
|
2014-05-19 05:49:16 +08:00
|
|
|
}
|
2014-07-29 10:49:06 +08:00
|
|
|
_attachments.clear();
|
2014-05-19 05:49:16 +08:00
|
|
|
}
|
|
|
|
|
2014-05-31 07:42:05 +08:00
|
|
|
void Sprite3D::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
|
2014-05-19 05:49:16 +08:00
|
|
|
{
|
2014-08-16 14:16:17 +08:00
|
|
|
if (_skeleton)
|
|
|
|
_skeleton->updateBoneMatrix();
|
2014-07-30 18:32:34 +08:00
|
|
|
|
2014-05-19 05:49:16 +08:00
|
|
|
GLProgramState* programstate = getGLProgramState();
|
|
|
|
Color4F color(getDisplayedColor());
|
|
|
|
color.a = getDisplayedOpacity() / 255.0f;
|
|
|
|
|
2014-08-16 14:16:17 +08:00
|
|
|
int i = 0;
|
|
|
|
for (auto& submeshstate : _subMeshStates) {
|
2014-07-29 10:49:06 +08:00
|
|
|
if (!submeshstate->isVisible())
|
|
|
|
continue;
|
|
|
|
|
2014-08-16 14:16:17 +08:00
|
|
|
auto& meshCommand = _meshCommands[i++];
|
2014-07-29 10:49:06 +08:00
|
|
|
|
|
|
|
GLuint textureID = submeshstate->getTexture() ? submeshstate->getTexture()->getName() : 0;
|
2014-08-16 14:16:17 +08:00
|
|
|
auto submesh = submeshstate->getSubMesh();
|
|
|
|
meshCommand.init(_globalZOrder, textureID, programstate, _blend, submesh->getMesh()->getVertexBuffer(), submesh->getIndexBuffer(), (GLenum)submesh->getPrimitiveType(), (GLenum)submesh->getIndexFormat(), submesh->getIndexCount(), transform);
|
2014-07-29 10:49:06 +08:00
|
|
|
|
|
|
|
meshCommand.setCullFaceEnabled(true);
|
|
|
|
meshCommand.setDepthTestEnabled(true);
|
2014-08-16 14:16:17 +08:00
|
|
|
auto skin = submeshstate->getSkin();
|
|
|
|
if (skin)
|
2014-07-29 10:49:06 +08:00
|
|
|
{
|
2014-08-16 14:16:17 +08:00
|
|
|
meshCommand.setMatrixPaletteSize((int)skin->getMatrixPaletteSize());
|
|
|
|
meshCommand.setMatrixPalette(skin->getMatrixPalette());
|
2014-07-29 10:49:06 +08:00
|
|
|
}
|
|
|
|
//support tint and fade
|
|
|
|
meshCommand.setDisplayColor(Vec4(color.r, color.g, color.b, color.a));
|
2014-08-14 10:29:17 +08:00
|
|
|
renderer->addCommand(&meshCommand);
|
2014-06-05 16:36:01 +08:00
|
|
|
}
|
2014-05-19 05:49:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Sprite3D::setBlendFunc(const BlendFunc &blendFunc)
|
|
|
|
{
|
|
|
|
if(_blend.src != blendFunc.src || _blend.dst != blendFunc.dst)
|
|
|
|
{
|
|
|
|
_blend = blendFunc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const BlendFunc& Sprite3D::getBlendFunc() const
|
|
|
|
{
|
|
|
|
return _blend;
|
|
|
|
}
|
|
|
|
|
2014-08-08 17:54:39 +08:00
|
|
|
AABB Sprite3D::getAABB() const
|
|
|
|
{
|
2014-08-12 13:45:06 +08:00
|
|
|
Mat4 nodeToWorldTransform(getNodeToWorldTransform());
|
2014-08-08 17:54:39 +08:00
|
|
|
|
2014-08-12 13:45:06 +08:00
|
|
|
// If nodeToWorldTransform matrix isn't changed, we don't need to transform aabb.
|
|
|
|
if (memcmp(_nodeToWorldTransform.m, nodeToWorldTransform.m, sizeof(Mat4)) == 0)
|
2014-08-08 17:54:39 +08:00
|
|
|
{
|
2014-08-12 13:45:06 +08:00
|
|
|
return _aabb;
|
2014-08-08 17:54:39 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-08-12 13:45:06 +08:00
|
|
|
Mat4 transform(nodeToWorldTransform);
|
|
|
|
_aabb = _mesh->getOriginAABB();
|
|
|
|
|
|
|
|
if (getSkin() && getSkin()->getRootBone())
|
|
|
|
{
|
|
|
|
transform = nodeToWorldTransform * getSkin()->getRootBone()->getWorldMat();
|
|
|
|
}
|
|
|
|
|
|
|
|
_aabb.transform(transform);
|
|
|
|
_nodeToWorldTransform = nodeToWorldTransform;
|
2014-08-08 17:54:39 +08:00
|
|
|
}
|
|
|
|
|
2014-08-12 13:45:06 +08:00
|
|
|
return _aabb;
|
2014-08-08 17:54:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Rect Sprite3D::getBoundingBox() const
|
|
|
|
{
|
|
|
|
AABB aabb = getAABB();
|
|
|
|
Rect ret(aabb._min.x, aabb._min.y, (aabb._max.x - aabb._min.x), (aabb._max.y - aabb._min.y));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-08-13 17:38:16 +08:00
|
|
|
void Sprite3D::setCullFace(GLenum cullFace)
|
|
|
|
{
|
|
|
|
for (auto& it : _meshCommands) {
|
|
|
|
it.setCullFace(cullFace);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sprite3D::setCullFaceEnabled(bool enable)
|
|
|
|
{
|
|
|
|
for (auto& it : _meshCommands) {
|
|
|
|
it.setCullFaceEnabled(enable);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-19 05:49:16 +08:00
|
|
|
NS_CC_END
|