mirror of https://github.com/axmolengine/axmol.git
308 lines
8.2 KiB
C++
308 lines
8.2 KiB
C++
/****************************************************************************
|
|
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/CCMesh.h"
|
|
#include "3d/CCMeshSkin.h"
|
|
#include "3d/CCSkeleton3D.h"
|
|
#include "3d/CCMeshVertexIndexData.h"
|
|
#include "base/CCEventDispatcher.h"
|
|
#include "base/CCDirector.h"
|
|
#include "renderer/CCTextureCache.h"
|
|
#include "renderer/CCGLProgramState.h"
|
|
|
|
using namespace std;
|
|
|
|
NS_CC_BEGIN
|
|
|
|
Mesh::Mesh()
|
|
: _texture(nullptr)
|
|
, _skin(nullptr)
|
|
, _visible(true)
|
|
, _isTransparent(false)
|
|
, _meshIndexData(nullptr)
|
|
, _glProgramState(nullptr)
|
|
, _blend(BlendFunc::ALPHA_NON_PREMULTIPLIED)
|
|
, _visibleChanged(nullptr)
|
|
{
|
|
|
|
}
|
|
Mesh::~Mesh()
|
|
{
|
|
CC_SAFE_RELEASE(_texture);
|
|
CC_SAFE_RELEASE(_skin);
|
|
CC_SAFE_RELEASE(_meshIndexData);
|
|
CC_SAFE_RELEASE(_glProgramState);
|
|
}
|
|
|
|
GLuint Mesh::getVertexBuffer() const
|
|
{
|
|
return _meshIndexData->getVertexBuffer()->getVBO();
|
|
}
|
|
|
|
bool Mesh::hasVertexAttrib(int attrib) const
|
|
{
|
|
return _meshIndexData->getMeshVertexData()->hasVertexAttrib(attrib);
|
|
}
|
|
|
|
ssize_t Mesh::getMeshVertexAttribCount() const
|
|
{
|
|
return _meshIndexData->getMeshVertexData()->getMeshVertexAttribCount();
|
|
}
|
|
|
|
const MeshVertexAttrib& Mesh::getMeshVertexAttribute(int idx)
|
|
{
|
|
return _meshIndexData->getMeshVertexData()->getMeshVertexAttrib(idx);
|
|
}
|
|
|
|
int Mesh::getVertexSizeInBytes() const
|
|
{
|
|
return _meshIndexData->getVertexBuffer()->getSizePerVertex();
|
|
}
|
|
|
|
Mesh* Mesh::create(const std::vector<float>& positions, const std::vector<float>& normals, const std::vector<float>& texs, const IndexArray& indices)
|
|
{
|
|
int perVertexSizeInFloat = 0;
|
|
std::vector<float> vertices;
|
|
std::vector<MeshVertexAttrib> attribs;
|
|
MeshVertexAttrib att;
|
|
att.size = 3;
|
|
att.type = GL_FLOAT;
|
|
att.attribSizeBytes = att.size * sizeof(float);
|
|
|
|
if (positions.size())
|
|
{
|
|
perVertexSizeInFloat += 3;
|
|
att.vertexAttrib = GLProgram::VERTEX_ATTRIB_POSITION;
|
|
attribs.push_back(att);
|
|
}
|
|
if (normals.size())
|
|
{
|
|
perVertexSizeInFloat += 3;
|
|
att.vertexAttrib = GLProgram::VERTEX_ATTRIB_NORMAL;
|
|
attribs.push_back(att);
|
|
}
|
|
if (texs.size())
|
|
{
|
|
perVertexSizeInFloat += 2;
|
|
att.vertexAttrib = GLProgram::VERTEX_ATTRIB_TEX_COORD;
|
|
att.size = 2;
|
|
att.attribSizeBytes = att.size * sizeof(float);
|
|
attribs.push_back(att);
|
|
}
|
|
|
|
bool hasNormal = (normals.size() != 0);
|
|
bool hasTexCoord = (texs.size() != 0);
|
|
//position, normal, texCoordinate into _vertexs
|
|
size_t vertexNum = positions.size() / 3;
|
|
for(size_t i = 0; i < vertexNum; i++)
|
|
{
|
|
vertices.push_back(positions[i * 3]);
|
|
vertices.push_back(positions[i * 3 + 1]);
|
|
vertices.push_back(positions[i * 3 + 2]);
|
|
|
|
if (hasNormal)
|
|
{
|
|
vertices.push_back(normals[i * 3]);
|
|
vertices.push_back(normals[i * 3 + 1]);
|
|
vertices.push_back(normals[i * 3 + 2]);
|
|
}
|
|
|
|
if (hasTexCoord)
|
|
{
|
|
vertices.push_back(texs[i * 2]);
|
|
vertices.push_back(texs[i * 2 + 1]);
|
|
}
|
|
}
|
|
return create(vertices, perVertexSizeInFloat, indices, attribs);
|
|
}
|
|
|
|
Mesh* Mesh::create(const std::vector<float>& vertices, int perVertexSizeInFloat, const IndexArray& indices, const std::vector<MeshVertexAttrib>& attribs)
|
|
{
|
|
MeshData meshdata;
|
|
meshdata.attribs = attribs;
|
|
meshdata.vertex = vertices;
|
|
meshdata.subMeshIndices.push_back(indices);
|
|
meshdata.subMeshIds.push_back("");
|
|
auto meshvertexdata = MeshVertexData::create(meshdata);
|
|
auto indexData = meshvertexdata->getMeshIndexDataByIndex(0);
|
|
|
|
return create("", indexData);
|
|
}
|
|
|
|
Mesh* Mesh::create(const std::string& name, MeshIndexData* indexData, MeshSkin* skin)
|
|
{
|
|
auto state = new (std::nothrow) Mesh();
|
|
state->autorelease();
|
|
state->bindMeshCommand();
|
|
state->_name = name;
|
|
state->setMeshIndexData(indexData);
|
|
state->setSkin(skin);
|
|
|
|
return state;
|
|
}
|
|
|
|
void Mesh::setVisible(bool visible)
|
|
{
|
|
if (_visible != visible)
|
|
{
|
|
_visible = visible;
|
|
if (_visibleChanged)
|
|
_visibleChanged();
|
|
}
|
|
}
|
|
|
|
void Mesh::setTexture(const std::string& texPath)
|
|
{
|
|
auto tex = Director::getInstance()->getTextureCache()->addImage(texPath);
|
|
setTexture(tex);
|
|
}
|
|
|
|
void Mesh::setTexture(Texture2D* tex)
|
|
{
|
|
if (tex != _texture)
|
|
{
|
|
CC_SAFE_RETAIN(tex);
|
|
CC_SAFE_RELEASE(_texture);
|
|
_texture = tex;
|
|
bindMeshCommand();
|
|
}
|
|
}
|
|
|
|
void Mesh::setSkin(MeshSkin* skin)
|
|
{
|
|
if (_skin != skin)
|
|
{
|
|
CC_SAFE_RETAIN(skin);
|
|
CC_SAFE_RELEASE(_skin);
|
|
_skin = skin;
|
|
calculateAABB();
|
|
}
|
|
}
|
|
|
|
void Mesh::setMeshIndexData(MeshIndexData* subMesh)
|
|
{
|
|
if (_meshIndexData != subMesh)
|
|
{
|
|
CC_SAFE_RETAIN(subMesh);
|
|
CC_SAFE_RELEASE(_meshIndexData);
|
|
_meshIndexData = subMesh;
|
|
calculateAABB();
|
|
bindMeshCommand();
|
|
}
|
|
}
|
|
|
|
void Mesh::setGLProgramState(GLProgramState* glProgramState)
|
|
{
|
|
if (_glProgramState != glProgramState)
|
|
{
|
|
CC_SAFE_RETAIN(glProgramState);
|
|
CC_SAFE_RELEASE(_glProgramState);
|
|
_glProgramState = glProgramState;
|
|
bindMeshCommand();
|
|
}
|
|
}
|
|
|
|
void Mesh::calculateAABB()
|
|
{
|
|
if (_meshIndexData)
|
|
{
|
|
_aabb = _meshIndexData->getAABB();
|
|
if (_skin)
|
|
{
|
|
//get skin root
|
|
Bone3D* root = nullptr;
|
|
Mat4 invBindPose;
|
|
if (_skin->_skinBones.size())
|
|
{
|
|
root = _skin->_skinBones.at(0);
|
|
while (root) {
|
|
auto parent = root->getParentBone();
|
|
bool parentInSkinBone = false;
|
|
for (const auto& bone : _skin->_skinBones) {
|
|
if (bone == parent)
|
|
{
|
|
parentInSkinBone = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!parentInSkinBone)
|
|
break;
|
|
root = parent;
|
|
}
|
|
}
|
|
|
|
if (root)
|
|
{
|
|
_aabb.transform(root->getWorldMat() * _skin->getInvBindPose(root));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Mesh::bindMeshCommand()
|
|
{
|
|
if (_glProgramState && _meshIndexData && _texture)
|
|
{
|
|
GLuint texID = _texture ? _texture->getName() : 0;
|
|
_meshCommand.genMaterialID(texID, _glProgramState, _meshIndexData->getVertexBuffer()->getVBO(), _meshIndexData->getIndexBuffer()->getVBO(), _blend);
|
|
_meshCommand.setCullFaceEnabled(true);
|
|
_meshCommand.setDepthTestEnabled(true);
|
|
}
|
|
}
|
|
|
|
void Mesh::setBlendFunc(const BlendFunc &blendFunc)
|
|
{
|
|
if(_blend.src != blendFunc.src || _blend.dst != blendFunc.dst)
|
|
{
|
|
_blend = blendFunc;
|
|
bindMeshCommand();
|
|
}
|
|
}
|
|
const BlendFunc &Mesh::getBlendFunc() const
|
|
{
|
|
return _blend;
|
|
}
|
|
|
|
GLenum Mesh::getPrimitiveType() const
|
|
{
|
|
return _meshIndexData->getPrimitiveType();
|
|
}
|
|
|
|
ssize_t Mesh::getIndexCount() const
|
|
{
|
|
return _meshIndexData->getIndexBuffer()->getIndexNumber();
|
|
}
|
|
|
|
GLenum Mesh::getIndexFormat() const
|
|
{
|
|
return GL_UNSIGNED_SHORT;
|
|
}
|
|
|
|
GLuint Mesh::getIndexBuffer() const
|
|
{
|
|
return _meshIndexData->getIndexBuffer()->getVBO();
|
|
}
|
|
|
|
NS_CC_END
|