2014-05-19 05:49:16 +08:00
|
|
|
/****************************************************************************
|
2018-01-29 16:25:32 +08:00
|
|
|
Copyright (c) 2014-2016 Chukong Technologies Inc.
|
|
|
|
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
2014-05-19 05:49:16 +08:00
|
|
|
|
2022-01-04 12:36:20 +08:00
|
|
|
https://adxeproject.github.io/
|
2014-05-19 05:49:16 +08:00
|
|
|
|
|
|
|
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.
|
|
|
|
****************************************************************************/
|
|
|
|
|
2014-08-22 13:52:03 +08:00
|
|
|
#include "3d/CCMesh.h"
|
|
|
|
#include "3d/CCMeshSkin.h"
|
2014-08-28 17:32:23 +08:00
|
|
|
#include "3d/CCSkeleton3D.h"
|
2014-08-22 13:52:03 +08:00
|
|
|
#include "3d/CCMeshVertexIndexData.h"
|
2019-02-15 14:30:10 +08:00
|
|
|
#include "3d/CCVertexAttribBinding.h"
|
2015-05-06 04:07:32 +08:00
|
|
|
#include "2d/CCLight.h"
|
|
|
|
#include "2d/CCScene.h"
|
2014-06-16 20:58:13 +08:00
|
|
|
#include "base/CCEventDispatcher.h"
|
2014-08-29 15:39:52 +08:00
|
|
|
#include "base/CCDirector.h"
|
2015-05-06 04:07:32 +08:00
|
|
|
#include "base/CCConfiguration.h"
|
2014-08-22 13:52:03 +08:00
|
|
|
#include "renderer/CCTextureCache.h"
|
2015-05-06 04:07:32 +08:00
|
|
|
#include "renderer/CCMaterial.h"
|
|
|
|
#include "renderer/CCTechnique.h"
|
|
|
|
#include "renderer/CCPass.h"
|
|
|
|
#include "renderer/CCRenderer.h"
|
2019-01-30 09:35:17 +08:00
|
|
|
#include "renderer/backend/Buffer.h"
|
2019-03-08 18:48:12 +08:00
|
|
|
#include "renderer/backend/Program.h"
|
2015-05-06 04:07:32 +08:00
|
|
|
#include "math/Mat4.h"
|
|
|
|
|
2014-05-19 05:49:16 +08:00
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
NS_CC_BEGIN
|
|
|
|
|
2015-05-06 04:07:32 +08:00
|
|
|
// Helpers
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
// sampler uniform names, only diffuse and normal texture are supported for now
|
|
|
|
std::string s_uniformSamplerName[] = {
|
|
|
|
"", // NTextureData::Usage::Unknown,
|
|
|
|
"", // NTextureData::Usage::None
|
|
|
|
"", // NTextureData::Usage::Diffuse
|
|
|
|
"", // NTextureData::Usage::Emissive
|
|
|
|
"", // NTextureData::Usage::Ambient
|
|
|
|
"", // NTextureData::Usage::Specular
|
|
|
|
"", // NTextureData::Usage::Shininess
|
|
|
|
"u_normalTex", // NTextureData::Usage::Normal
|
|
|
|
"", // NTextureData::Usage::Bump
|
|
|
|
"", // NTextureData::Usage::Transparency
|
|
|
|
"", // NTextureData::Usage::Reflection
|
2015-12-01 10:37:53 +08:00
|
|
|
};
|
|
|
|
|
2015-05-06 04:07:32 +08:00
|
|
|
// helpers
|
2015-09-16 18:04:52 +08:00
|
|
|
void Mesh::resetLightUniformValues()
|
2015-05-06 04:07:32 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
const auto& conf = Configuration::getInstance();
|
|
|
|
int maxDirLight = conf->getMaxSupportDirLightInShader();
|
2015-05-06 04:07:32 +08:00
|
|
|
int maxPointLight = conf->getMaxSupportPointLightInShader();
|
2021-12-25 10:04:45 +08:00
|
|
|
int maxSpotLight = conf->getMaxSupportSpotLightInShader();
|
2015-05-06 04:07:32 +08:00
|
|
|
|
2015-09-16 18:04:52 +08:00
|
|
|
_dirLightUniformColorValues.assign(maxDirLight, Vec3::ZERO);
|
|
|
|
_dirLightUniformDirValues.assign(maxDirLight, Vec3::ZERO);
|
2015-05-06 04:07:32 +08:00
|
|
|
|
2015-09-16 18:04:52 +08:00
|
|
|
_pointLightUniformColorValues.assign(maxPointLight, Vec3::ZERO);
|
|
|
|
_pointLightUniformPositionValues.assign(maxPointLight, Vec3::ZERO);
|
|
|
|
_pointLightUniformRangeInverseValues.assign(maxPointLight, 0.0f);
|
2015-05-06 04:07:32 +08:00
|
|
|
|
2015-09-16 18:04:52 +08:00
|
|
|
_spotLightUniformColorValues.assign(maxSpotLight, Vec3::ZERO);
|
|
|
|
_spotLightUniformPositionValues.assign(maxSpotLight, Vec3::ZERO);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
|
|
|
// TODO It's strange that init _spotLightUniformDirValues to zeros will cause no light effects on iPhone6 and
|
|
|
|
// iPhone6s, but works well on iPhoneX fix no light effects on iPhone6 and iPhone6s
|
2019-05-28 13:59:37 +08:00
|
|
|
_spotLightUniformDirValues.assign(maxSpotLight, Vec3(FLT_EPSILON, 0.0f, 0.0f));
|
2015-10-08 11:27:02 +08:00
|
|
|
_spotLightUniformInnerAngleCosValues.assign(maxSpotLight, 1.0f);
|
2015-09-16 18:04:52 +08:00
|
|
|
_spotLightUniformOuterAngleCosValues.assign(maxSpotLight, 0.0f);
|
|
|
|
_spotLightUniformRangeInverseValues.assign(maxSpotLight, 0.0f);
|
2015-05-06 04:07:32 +08:00
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
// Generate a dummy texture when the texture file is missing
|
|
|
|
static Texture2D* getDummyTexture()
|
2015-05-06 04:07:32 +08:00
|
|
|
{
|
|
|
|
auto texture = Director::getInstance()->getTextureCache()->getTextureForKey("/dummyTexture");
|
2021-12-25 10:04:45 +08:00
|
|
|
if (!texture)
|
2015-05-06 04:07:32 +08:00
|
|
|
{
|
|
|
|
#ifdef NDEBUG
|
2021-12-25 10:04:45 +08:00
|
|
|
unsigned char data[] = {0, 0, 0, 0}; // 1*1 transparent picture
|
2015-05-06 04:07:32 +08:00
|
|
|
#else
|
2021-12-25 10:04:45 +08:00
|
|
|
unsigned char data[] = {255, 0, 0, 255}; // 1*1 red picture
|
2015-05-06 04:07:32 +08:00
|
|
|
#endif
|
2021-12-25 10:04:45 +08:00
|
|
|
Image* image = new Image();
|
|
|
|
image->initWithRawData(data, sizeof(data), 1, 1, sizeof(unsigned char));
|
|
|
|
texture = Director::getInstance()->getTextureCache()->addImage(image, "/dummyTexture");
|
2015-05-06 04:07:32 +08:00
|
|
|
image->release();
|
|
|
|
}
|
|
|
|
return texture;
|
|
|
|
}
|
|
|
|
|
2014-08-22 13:52:03 +08:00
|
|
|
Mesh::Mesh()
|
2021-12-25 10:04:45 +08:00
|
|
|
: _skin(nullptr)
|
|
|
|
, _visible(true)
|
|
|
|
, _isTransparent(false)
|
|
|
|
, _force2DQueue(false)
|
|
|
|
, _meshIndexData(nullptr)
|
|
|
|
, _blend(BlendFunc::ALPHA_NON_PREMULTIPLIED)
|
|
|
|
, _blendDirty(true)
|
|
|
|
, _material(nullptr)
|
|
|
|
, _texFile("")
|
|
|
|
{}
|
2014-08-22 13:52:03 +08:00
|
|
|
Mesh::~Mesh()
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
for (auto& tex : _textures)
|
|
|
|
{
|
2015-12-01 10:37:53 +08:00
|
|
|
CC_SAFE_RELEASE(tex.second);
|
2015-11-25 10:45:03 +08:00
|
|
|
}
|
2014-08-22 13:52:03 +08:00
|
|
|
CC_SAFE_RELEASE(_skin);
|
|
|
|
CC_SAFE_RELEASE(_meshIndexData);
|
2015-05-06 04:07:32 +08:00
|
|
|
CC_SAFE_RELEASE(_material);
|
2014-08-22 13:52:03 +08:00
|
|
|
}
|
|
|
|
|
2019-01-30 09:35:17 +08:00
|
|
|
backend::Buffer* Mesh::getVertexBuffer() const
|
2014-08-22 13:52:03 +08:00
|
|
|
{
|
2019-01-30 09:35:17 +08:00
|
|
|
return _meshIndexData->getVertexBuffer();
|
2014-08-22 13:52:03 +08:00
|
|
|
}
|
|
|
|
|
2019-01-30 09:35:17 +08:00
|
|
|
bool Mesh::hasVertexAttrib(shaderinfos::VertexKey attrib) const
|
2014-08-22 13:52:03 +08:00
|
|
|
{
|
|
|
|
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
|
|
|
|
{
|
2019-01-30 09:35:17 +08:00
|
|
|
return _meshIndexData->getMeshVertexData()->getSizePerVertex();
|
2014-08-22 13:52:03 +08:00
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
Mesh* Mesh::create(const std::vector<float>& positions,
|
|
|
|
const std::vector<float>& normals,
|
|
|
|
const std::vector<float>& texs,
|
|
|
|
const IndexArray& indices)
|
2014-08-22 13:52:03 +08:00
|
|
|
{
|
|
|
|
int perVertexSizeInFloat = 0;
|
|
|
|
std::vector<float> vertices;
|
|
|
|
std::vector<MeshVertexAttrib> attribs;
|
|
|
|
MeshVertexAttrib att;
|
2019-02-22 14:06:26 +08:00
|
|
|
att.type = backend::VertexFormat::FLOAT3;
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2014-08-22 13:52:03 +08:00
|
|
|
if (positions.size())
|
|
|
|
{
|
|
|
|
perVertexSizeInFloat += 3;
|
2019-01-30 09:35:17 +08:00
|
|
|
att.vertexAttrib = shaderinfos::VertexKey::VERTEX_ATTRIB_POSITION;
|
2014-08-22 13:52:03 +08:00
|
|
|
attribs.push_back(att);
|
|
|
|
}
|
|
|
|
if (normals.size())
|
|
|
|
{
|
|
|
|
perVertexSizeInFloat += 3;
|
2019-01-30 09:35:17 +08:00
|
|
|
att.vertexAttrib = shaderinfos::VertexKey::VERTEX_ATTRIB_NORMAL;
|
2014-08-22 13:52:03 +08:00
|
|
|
attribs.push_back(att);
|
|
|
|
}
|
|
|
|
if (texs.size())
|
|
|
|
{
|
|
|
|
perVertexSizeInFloat += 2;
|
2021-12-25 10:04:45 +08:00
|
|
|
att.type = backend::VertexFormat::FLOAT2;
|
2019-01-30 09:35:17 +08:00
|
|
|
att.vertexAttrib = shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD;
|
2014-08-22 13:52:03 +08:00
|
|
|
attribs.push_back(att);
|
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
|
|
|
|
bool hasNormal = (normals.size() != 0);
|
2014-08-22 13:52:03 +08:00
|
|
|
bool hasTexCoord = (texs.size() != 0);
|
2021-12-25 10:04:45 +08:00
|
|
|
// position, normal, texCoordinate into _vertexs
|
2014-08-22 13:52:03 +08:00
|
|
|
size_t vertexNum = positions.size() / 3;
|
2021-12-25 10:04:45 +08:00
|
|
|
for (size_t i = 0; i < vertexNum; i++)
|
2014-08-22 13:52:03 +08:00
|
|
|
{
|
|
|
|
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]);
|
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2014-08-22 13:52:03 +08:00
|
|
|
if (hasTexCoord)
|
|
|
|
{
|
|
|
|
vertices.push_back(texs[i * 2]);
|
|
|
|
vertices.push_back(texs[i * 2 + 1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return create(vertices, perVertexSizeInFloat, indices, attribs);
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
Mesh* Mesh::create(const std::vector<float>& vertices,
|
|
|
|
int /*perVertexSizeInFloat*/,
|
|
|
|
const IndexArray& indices,
|
|
|
|
const std::vector<MeshVertexAttrib>& attribs)
|
2014-08-22 13:52:03 +08:00
|
|
|
{
|
|
|
|
MeshData meshdata;
|
|
|
|
meshdata.attribs = attribs;
|
2021-12-25 10:04:45 +08:00
|
|
|
meshdata.vertex = vertices;
|
2014-08-22 13:52:03 +08:00
|
|
|
meshdata.subMeshIndices.push_back(indices);
|
|
|
|
meshdata.subMeshIds.push_back("");
|
|
|
|
auto meshvertexdata = MeshVertexData::create(meshdata);
|
2021-12-25 10:04:45 +08:00
|
|
|
auto indexData = meshvertexdata->getMeshIndexDataByIndex(0);
|
|
|
|
|
2014-08-22 13:52:03 +08:00
|
|
|
return create("", indexData);
|
|
|
|
}
|
|
|
|
|
2021-12-26 23:26:34 +08:00
|
|
|
Mesh* Mesh::create(std::string_view name, MeshIndexData* indexData, MeshSkin* skin)
|
2014-08-22 13:52:03 +08:00
|
|
|
{
|
2021-12-08 00:11:53 +08:00
|
|
|
auto state = new Mesh();
|
2014-08-22 13:52:03 +08:00
|
|
|
state->autorelease();
|
|
|
|
state->bindMeshCommand();
|
|
|
|
state->_name = name;
|
|
|
|
state->setMeshIndexData(indexData);
|
|
|
|
state->setSkin(skin);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2014-08-22 13:52:03 +08:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Mesh::setVisible(bool visible)
|
|
|
|
{
|
|
|
|
if (_visible != visible)
|
|
|
|
{
|
|
|
|
_visible = visible;
|
|
|
|
if (_visibleChanged)
|
|
|
|
_visibleChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-06 04:07:32 +08:00
|
|
|
bool Mesh::isVisible() const
|
|
|
|
{
|
|
|
|
return _visible;
|
|
|
|
}
|
|
|
|
|
2021-12-26 23:26:34 +08:00
|
|
|
void Mesh::setTexture(std::string_view texPath)
|
2014-08-22 13:52:03 +08:00
|
|
|
{
|
2015-11-13 17:44:23 +08:00
|
|
|
_texFile = texPath;
|
2014-08-22 13:52:03 +08:00
|
|
|
auto tex = Director::getInstance()->getTextureCache()->addImage(texPath);
|
2015-12-01 10:37:53 +08:00
|
|
|
setTexture(tex, NTextureData::Usage::Diffuse);
|
2014-08-22 13:52:03 +08:00
|
|
|
}
|
|
|
|
|
2015-12-01 10:37:53 +08:00
|
|
|
void Mesh::setTexture(Texture2D* tex)
|
|
|
|
{
|
|
|
|
setTexture(tex, NTextureData::Usage::Diffuse);
|
|
|
|
}
|
|
|
|
|
2015-12-17 16:53:38 +08:00
|
|
|
void Mesh::setTexture(Texture2D* tex, NTextureData::Usage usage, bool cacheFileName)
|
2014-08-22 13:52:03 +08:00
|
|
|
{
|
2015-05-06 04:07:32 +08:00
|
|
|
// 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
|
2015-07-08 17:00:01 +08:00
|
|
|
if (tex == nullptr)
|
|
|
|
tex = getDummyTexture();
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2015-12-01 10:37:53 +08:00
|
|
|
CC_SAFE_RETAIN(tex);
|
|
|
|
CC_SAFE_RELEASE(_textures[usage]);
|
2021-12-25 10:04:45 +08:00
|
|
|
_textures[usage] = tex;
|
|
|
|
|
|
|
|
if (usage == NTextureData::Usage::Diffuse)
|
|
|
|
{
|
|
|
|
if (_material)
|
|
|
|
{
|
2015-11-25 10:45:03 +08:00
|
|
|
auto technique = _material->_currentTechnique;
|
2021-12-25 10:04:45 +08:00
|
|
|
for (auto& pass : technique->_passes)
|
2015-11-25 10:45:03 +08:00
|
|
|
{
|
2019-02-15 14:30:10 +08:00
|
|
|
pass->setUniformTexture(0, tex->getBackendTexture());
|
2015-11-25 10:45:03 +08:00
|
|
|
}
|
2015-05-06 04:07:32 +08:00
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2015-11-25 10:45:03 +08:00
|
|
|
bindMeshCommand();
|
2015-12-17 16:53:38 +08:00
|
|
|
if (cacheFileName)
|
|
|
|
_texFile = tex->getPath();
|
2015-11-25 10:45:03 +08:00
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
else if (usage == NTextureData::Usage::Normal) // currently only diffuse and normal are supported
|
2015-12-01 10:37:53 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
if (_material)
|
|
|
|
{
|
2015-12-01 10:37:53 +08:00
|
|
|
auto technique = _material->_currentTechnique;
|
2021-12-25 10:04:45 +08:00
|
|
|
for (auto& pass : technique->_passes)
|
2015-12-01 10:37:53 +08:00
|
|
|
{
|
2019-02-28 15:20:23 +08:00
|
|
|
pass->setUniformNormTexture(1, tex->getBackendTexture());
|
2015-12-01 10:37:53 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-05-06 04:07:32 +08:00
|
|
|
}
|
|
|
|
|
2021-12-26 23:26:34 +08:00
|
|
|
void Mesh::setTexture(std::string_view texPath, NTextureData::Usage usage)
|
2015-05-06 04:07:32 +08:00
|
|
|
{
|
2015-12-01 10:37:53 +08:00
|
|
|
auto tex = Director::getInstance()->getTextureCache()->addImage(texPath);
|
|
|
|
setTexture(tex, usage);
|
|
|
|
}
|
|
|
|
|
|
|
|
Texture2D* Mesh::getTexture() const
|
|
|
|
{
|
|
|
|
return _textures.at(NTextureData::Usage::Diffuse);
|
|
|
|
}
|
|
|
|
|
|
|
|
Texture2D* Mesh::getTexture(NTextureData::Usage usage)
|
|
|
|
{
|
|
|
|
return _textures[usage];
|
2015-05-06 04:07:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Mesh::setMaterial(Material* material)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
if (_material != material)
|
|
|
|
{
|
2015-05-06 04:07:32 +08:00
|
|
|
CC_SAFE_RELEASE(_material);
|
|
|
|
_material = material;
|
|
|
|
CC_SAFE_RETAIN(_material);
|
|
|
|
}
|
2019-03-14 16:22:54 +08:00
|
|
|
_meshCommands.clear();
|
2015-05-13 10:58:09 +08:00
|
|
|
|
|
|
|
if (_material)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
for (auto technique : _material->getTechniques())
|
2015-05-13 10:58:09 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
// allocate MeshCommand vector for technique
|
|
|
|
// allocate MeshCommand for each pass
|
2019-03-14 16:22:54 +08:00
|
|
|
_meshCommands[technique->getName()] = std::vector<MeshCommand>(technique->getPasses().size());
|
2021-12-25 10:04:45 +08:00
|
|
|
auto& list = _meshCommands[technique->getName()];
|
|
|
|
|
2019-03-14 16:22:54 +08:00
|
|
|
int i = 0;
|
2021-12-25 10:04:45 +08:00
|
|
|
for (auto pass : technique->getPasses())
|
2015-05-13 10:58:09 +08:00
|
|
|
{
|
2019-03-08 18:48:12 +08:00
|
|
|
#ifdef COCOS2D_DEBUG
|
2021-12-25 10:04:45 +08:00
|
|
|
// make it crashed when missing attribute data
|
|
|
|
if (_material->getTechnique()->getName().compare(technique->getName()) == 0)
|
2019-03-08 18:48:12 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
auto program = pass->getProgramState()->getProgram();
|
2021-12-27 19:18:36 +08:00
|
|
|
auto attributes = program->getActiveAttributes();
|
2019-03-08 18:48:12 +08:00
|
|
|
auto meshVertexData = _meshIndexData->getMeshVertexData();
|
|
|
|
auto attributeCount = meshVertexData->getMeshVertexAttribCount();
|
|
|
|
CCASSERT(attributes.size() <= attributeCount, "missing attribute data");
|
|
|
|
}
|
|
|
|
#endif
|
2021-12-25 10:04:45 +08:00
|
|
|
// TODO
|
2019-03-14 16:22:54 +08:00
|
|
|
auto vertexAttribBinding = VertexAttribBinding::create(_meshIndexData, pass, &list[i]);
|
2015-05-13 10:58:09 +08:00
|
|
|
pass->setVertexAttribBinding(vertexAttribBinding);
|
2019-03-14 16:22:54 +08:00
|
|
|
i += 1;
|
2015-05-13 10:58:09 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-09-06 10:14:14 +08:00
|
|
|
// Was the texture set before the GLProgramState ? Set it
|
2021-12-25 10:04:45 +08:00
|
|
|
for (auto& tex : _textures)
|
2015-12-01 10:37:53 +08:00
|
|
|
setTexture(tex.second, tex.first);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2015-09-07 13:59:38 +08:00
|
|
|
if (_blendDirty)
|
|
|
|
setBlendFunc(_blend);
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2015-09-07 13:59:38 +08:00
|
|
|
bindMeshCommand();
|
2015-05-06 04:07:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Material* Mesh::getMaterial() const
|
|
|
|
{
|
|
|
|
return _material;
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
void Mesh::draw(Renderer* renderer,
|
|
|
|
float globalZOrder,
|
|
|
|
const Mat4& transform,
|
|
|
|
uint32_t flags,
|
|
|
|
unsigned int lightMask,
|
|
|
|
const Vec4& color,
|
|
|
|
bool forceDepthWrite)
|
2015-05-06 04:07:32 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
if (!isVisible())
|
2015-05-06 04:07:32 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
bool isTransparent = (_isTransparent || color.w < 1.f);
|
2021-12-25 10:04:45 +08:00
|
|
|
float globalZ = isTransparent ? 0 : globalZOrder;
|
2015-05-06 04:07:32 +08:00
|
|
|
if (isTransparent)
|
|
|
|
flags |= Node::FLAGS_RENDER_AS_3D;
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
// TODO
|
|
|
|
// _meshCommand.init(globalZ,
|
|
|
|
// _material,
|
|
|
|
// getVertexBuffer(),
|
|
|
|
// getIndexBuffer(),
|
|
|
|
// getPrimitiveType(),
|
|
|
|
// getIndexFormat(),
|
|
|
|
// getIndexCount(),
|
|
|
|
// transform,
|
|
|
|
// flags);
|
2015-05-06 04:07:32 +08:00
|
|
|
|
2019-03-20 14:34:35 +08:00
|
|
|
if (isTransparent && !forceDepthWrite)
|
|
|
|
_material->getStateBlock().setDepthWrite(false);
|
|
|
|
else
|
2019-02-15 14:30:10 +08:00
|
|
|
_material->getStateBlock().setDepthWrite(true);
|
2015-05-06 04:07:32 +08:00
|
|
|
|
2019-02-15 14:30:10 +08:00
|
|
|
_material->getStateBlock().setBlend(_force2DQueue || isTransparent);
|
2015-05-06 04:07:32 +08:00
|
|
|
|
|
|
|
// set default uniforms for Mesh
|
|
|
|
// 'u_color' and others
|
2015-05-14 08:39:39 +08:00
|
|
|
const auto scene = Director::getInstance()->getRunningScene();
|
2021-12-25 10:04:45 +08:00
|
|
|
auto technique = _material->_currentTechnique;
|
|
|
|
for (const auto pass : technique->_passes)
|
2015-05-06 04:07:32 +08:00
|
|
|
{
|
2019-02-15 14:30:10 +08:00
|
|
|
pass->setUniformColor(&color, sizeof(color));
|
|
|
|
|
2015-05-06 04:07:32 +08:00
|
|
|
if (_skin)
|
2019-02-15 14:30:10 +08:00
|
|
|
pass->setUniformMatrixPalette(_skin->getMatrixPalette(), _skin->getMatrixPaletteSizeInBytes());
|
2015-05-06 04:07:32 +08:00
|
|
|
|
2020-08-18 14:29:09 +08:00
|
|
|
if (scene && !scene->getLights().empty())
|
2019-02-15 14:30:10 +08:00
|
|
|
{
|
2015-05-13 10:58:09 +08:00
|
|
|
setLightUniforms(pass, scene, color, lightMask);
|
2019-02-15 14:30:10 +08:00
|
|
|
}
|
2015-05-06 04:07:32 +08:00
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
auto& commands = _meshCommands[technique->getName()];
|
2019-03-20 14:34:35 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
for (auto& command : commands)
|
2019-03-20 14:34:35 +08:00
|
|
|
{
|
|
|
|
command.init(globalZ, transform);
|
|
|
|
command.setSkipBatching(isTransparent);
|
|
|
|
command.setTransparent(isTransparent);
|
|
|
|
command.set3D(!_force2DQueue);
|
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
_material->draw(commands.data(), globalZ, getVertexBuffer(), getIndexBuffer(), getPrimitiveType(), getIndexFormat(),
|
|
|
|
getIndexCount(), transform);
|
2014-08-22 13:52:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Mesh::setSkin(MeshSkin* skin)
|
|
|
|
{
|
|
|
|
if (_skin != skin)
|
|
|
|
{
|
|
|
|
CC_SAFE_RETAIN(skin);
|
|
|
|
CC_SAFE_RELEASE(_skin);
|
|
|
|
_skin = skin;
|
2015-03-20 17:20:22 +08:00
|
|
|
calculateAABB();
|
2014-08-22 13:52:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Mesh::setMeshIndexData(MeshIndexData* subMesh)
|
|
|
|
{
|
|
|
|
if (_meshIndexData != subMesh)
|
|
|
|
{
|
|
|
|
CC_SAFE_RETAIN(subMesh);
|
|
|
|
CC_SAFE_RELEASE(_meshIndexData);
|
|
|
|
_meshIndexData = subMesh;
|
2015-03-20 17:20:22 +08:00
|
|
|
calculateAABB();
|
2014-08-22 13:52:03 +08:00
|
|
|
bindMeshCommand();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-30 09:35:17 +08:00
|
|
|
void Mesh::setProgramState(backend::ProgramState* programState)
|
2014-08-22 13:52:03 +08:00
|
|
|
{
|
2019-01-30 09:35:17 +08:00
|
|
|
auto material = Material::createWithProgramState(programState);
|
2015-10-29 14:22:13 +08:00
|
|
|
if (_material)
|
2019-01-30 09:35:17 +08:00
|
|
|
{
|
2015-10-29 14:22:13 +08:00
|
|
|
material->setStateBlock(_material->getStateBlock());
|
2019-01-30 09:35:17 +08:00
|
|
|
}
|
2015-05-06 04:07:32 +08:00
|
|
|
setMaterial(material);
|
|
|
|
}
|
|
|
|
|
2019-01-30 09:35:17 +08:00
|
|
|
backend::ProgramState* Mesh::getProgramState() const
|
2015-05-06 04:07:32 +08:00
|
|
|
{
|
2019-01-30 09:35:17 +08:00
|
|
|
return _material ? _material->_currentTechnique->_passes.at(0)->getProgramState() : nullptr;
|
2014-08-22 13:52:03 +08:00
|
|
|
}
|
|
|
|
|
2015-03-20 17:20:22 +08:00
|
|
|
void Mesh::calculateAABB()
|
2014-08-22 13:52:03 +08:00
|
|
|
{
|
|
|
|
if (_meshIndexData)
|
|
|
|
{
|
|
|
|
_aabb = _meshIndexData->getAABB();
|
|
|
|
if (_skin)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
// get skin root
|
2014-10-20 22:53:24 +08:00
|
|
|
Bone3D* root = nullptr;
|
|
|
|
Mat4 invBindPose;
|
|
|
|
if (_skin->_skinBones.size())
|
|
|
|
{
|
|
|
|
root = _skin->_skinBones.at(0);
|
2021-12-25 10:04:45 +08:00
|
|
|
while (root)
|
|
|
|
{
|
|
|
|
auto parent = root->getParentBone();
|
2014-10-20 22:53:24 +08:00
|
|
|
bool parentInSkinBone = false;
|
2021-12-25 10:04:45 +08:00
|
|
|
for (const auto& bone : _skin->_skinBones)
|
|
|
|
{
|
2014-10-20 22:53:24 +08:00
|
|
|
if (bone == parent)
|
|
|
|
{
|
|
|
|
parentInSkinBone = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!parentInSkinBone)
|
|
|
|
break;
|
|
|
|
root = parent;
|
|
|
|
}
|
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
|
2014-08-22 13:52:03 +08:00
|
|
|
if (root)
|
|
|
|
{
|
2014-10-20 22:53:24 +08:00
|
|
|
_aabb.transform(root->getWorldMat() * _skin->getInvBindPose(root));
|
2014-08-22 13:52:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Mesh::bindMeshCommand()
|
|
|
|
{
|
2015-05-06 04:07:32 +08:00
|
|
|
if (_material && _meshIndexData)
|
|
|
|
{
|
2019-02-15 14:30:10 +08:00
|
|
|
_material->getStateBlock().setCullFace(true);
|
|
|
|
_material->getStateBlock().setDepthTest(true);
|
2015-05-06 04:07:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-13 10:58:09 +08:00
|
|
|
void Mesh::setLightUniforms(Pass* pass, Scene* scene, const Vec4& color, unsigned int lightmask)
|
2015-05-06 04:07:32 +08:00
|
|
|
{
|
2015-05-13 10:58:09 +08:00
|
|
|
CCASSERT(pass, "Invalid Pass");
|
2015-05-06 04:07:32 +08:00
|
|
|
CCASSERT(scene, "Invalid scene");
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
const auto& conf = Configuration::getInstance();
|
|
|
|
int maxDirLight = conf->getMaxSupportDirLightInShader();
|
2019-02-15 14:30:10 +08:00
|
|
|
int maxPointLight = conf->getMaxSupportPointLightInShader();
|
2021-12-25 10:04:45 +08:00
|
|
|
int maxSpotLight = conf->getMaxSupportSpotLightInShader();
|
|
|
|
auto& lights = scene->getLights();
|
2019-02-15 14:30:10 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
auto bindings = pass->getVertexAttributeBinding();
|
2019-02-15 14:30:10 +08:00
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
if (bindings && bindings->hasAttribute(shaderinfos::VertexKey::VERTEX_ATTRIB_NORMAL))
|
2019-02-15 14:30:10 +08:00
|
|
|
{
|
|
|
|
resetLightUniformValues();
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
int enabledDirLightNum = 0;
|
2019-06-05 17:58:33 +08:00
|
|
|
int enabledPointLightNum = 0;
|
2021-12-25 10:04:45 +08:00
|
|
|
int enabledSpotLightNum = 0;
|
2019-02-15 14:30:10 +08:00
|
|
|
Vec3 ambientColor;
|
|
|
|
for (const auto& light : lights)
|
|
|
|
{
|
|
|
|
bool useLight = light->isEnabled() && ((unsigned int)light->getLightFlag() & lightmask);
|
|
|
|
if (useLight)
|
|
|
|
{
|
|
|
|
float intensity = light->getIntensity();
|
|
|
|
switch (light->getLightType())
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
case LightType::DIRECTIONAL:
|
|
|
|
{
|
|
|
|
if (enabledDirLightNum < maxDirLight)
|
2019-02-15 14:30:10 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
auto dirLight = static_cast<DirectionLight*>(light);
|
|
|
|
Vec3 dir = dirLight->getDirectionInWorld();
|
|
|
|
dir.normalize();
|
|
|
|
const Color3B& col = dirLight->getDisplayedColor();
|
|
|
|
_dirLightUniformColorValues[enabledDirLightNum].set(
|
|
|
|
col.r / 255.0f * intensity, col.g / 255.0f * intensity, col.b / 255.0f * intensity);
|
|
|
|
_dirLightUniformDirValues[enabledDirLightNum] = dir;
|
|
|
|
++enabledDirLightNum;
|
2019-02-15 14:30:10 +08:00
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LightType::POINT:
|
|
|
|
{
|
|
|
|
if (enabledPointLightNum < maxPointLight)
|
2019-02-15 14:30:10 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
auto pointLight = static_cast<PointLight*>(light);
|
|
|
|
Mat4 mat = pointLight->getNodeToWorldTransform();
|
|
|
|
const Color3B& col = pointLight->getDisplayedColor();
|
|
|
|
_pointLightUniformColorValues[enabledPointLightNum].set(
|
|
|
|
col.r / 255.0f * intensity, col.g / 255.0f * intensity, col.b / 255.0f * intensity);
|
|
|
|
_pointLightUniformPositionValues[enabledPointLightNum].set(mat.m[12], mat.m[13], mat.m[14]);
|
|
|
|
_pointLightUniformRangeInverseValues[enabledPointLightNum] = 1.0f / pointLight->getRange();
|
|
|
|
++enabledPointLightNum;
|
2019-02-15 14:30:10 +08:00
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LightType::SPOT:
|
|
|
|
{
|
|
|
|
if (enabledSpotLightNum < maxSpotLight)
|
2019-02-15 14:30:10 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
auto spotLight = static_cast<SpotLight*>(light);
|
|
|
|
Vec3 dir = spotLight->getDirectionInWorld();
|
|
|
|
dir.normalize();
|
|
|
|
Mat4 mat = light->getNodeToWorldTransform();
|
|
|
|
const Color3B& col = spotLight->getDisplayedColor();
|
|
|
|
_spotLightUniformColorValues[enabledSpotLightNum].set(
|
|
|
|
col.r / 255.0f * intensity, col.g / 255.0f * intensity, col.b / 255.0f * intensity);
|
|
|
|
_spotLightUniformPositionValues[enabledSpotLightNum].set(mat.m[12], mat.m[13], mat.m[14]);
|
|
|
|
_spotLightUniformDirValues[enabledSpotLightNum] = dir;
|
|
|
|
_spotLightUniformInnerAngleCosValues[enabledSpotLightNum] = spotLight->getCosInnerAngle();
|
|
|
|
_spotLightUniformOuterAngleCosValues[enabledSpotLightNum] = spotLight->getCosOuterAngle();
|
|
|
|
_spotLightUniformRangeInverseValues[enabledSpotLightNum] = 1.0f / spotLight->getRange();
|
|
|
|
++enabledSpotLightNum;
|
2019-02-15 14:30:10 +08:00
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LightType::AMBIENT:
|
|
|
|
{
|
|
|
|
auto ambLight = static_cast<AmbientLight*>(light);
|
|
|
|
const Color3B& col = ambLight->getDisplayedColor();
|
|
|
|
ambientColor.add(col.r / 255.0f * intensity, col.g / 255.0f * intensity,
|
|
|
|
col.b / 255.0f * intensity);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2019-02-15 14:30:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (0 < maxDirLight)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
pass->setUniformDirLightColor(&_dirLightUniformColorValues[0],
|
|
|
|
_dirLightUniformColorValues.size() * sizeof(_dirLightUniformColorValues[0]));
|
|
|
|
pass->setUniformDirLightDir(&_dirLightUniformDirValues[0],
|
|
|
|
_dirLightUniformDirValues.size() * sizeof(_dirLightUniformDirValues[0]));
|
2019-02-15 14:30:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (0 < maxPointLight)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
pass->setUniformPointLightColor(
|
|
|
|
&_pointLightUniformColorValues[0],
|
|
|
|
_pointLightUniformColorValues.size() * sizeof(_pointLightUniformColorValues[0]));
|
|
|
|
pass->setUniformPointLightPosition(
|
|
|
|
&_pointLightUniformPositionValues[0],
|
|
|
|
_pointLightUniformPositionValues.size() * sizeof(_pointLightUniformPositionValues[0]));
|
|
|
|
pass->setUniformPointLightRangeInverse(
|
|
|
|
&_pointLightUniformRangeInverseValues[0],
|
|
|
|
_pointLightUniformRangeInverseValues.size() * sizeof(_pointLightUniformRangeInverseValues[0]));
|
2019-02-15 14:30:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (0 < maxSpotLight)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
pass->setUniformSpotLightColor(
|
|
|
|
&_spotLightUniformColorValues[0],
|
|
|
|
_spotLightUniformColorValues.size() * sizeof(_spotLightUniformColorValues[0]));
|
|
|
|
pass->setUniformSpotLightPosition(
|
|
|
|
&_spotLightUniformPositionValues[0],
|
|
|
|
_spotLightUniformPositionValues.size() * sizeof(_spotLightUniformPositionValues[0]));
|
|
|
|
pass->setUniformSpotLightDir(&_spotLightUniformDirValues[0],
|
|
|
|
_spotLightUniformDirValues.size() * sizeof(_spotLightUniformDirValues[0]));
|
|
|
|
pass->setUniformSpotLightInnerAngleCos(
|
|
|
|
&_spotLightUniformInnerAngleCosValues[0],
|
|
|
|
_spotLightUniformInnerAngleCosValues.size() * sizeof(_spotLightUniformInnerAngleCosValues[0]));
|
|
|
|
pass->setUniformSpotLightOuterAngleCos(
|
|
|
|
&_spotLightUniformOuterAngleCosValues[0],
|
|
|
|
_spotLightUniformOuterAngleCosValues.size() * sizeof(_spotLightUniformOuterAngleCosValues[0]));
|
|
|
|
pass->setUniformSpotLightRangeInverse(
|
|
|
|
&_spotLightUniformRangeInverseValues[0],
|
|
|
|
_spotLightUniformRangeInverseValues.size() * sizeof(_spotLightUniformRangeInverseValues[0]));
|
2019-02-15 14:30:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
auto ambientLightColor = Vec3(ambientColor.x, ambientColor.y, ambientColor.z);
|
|
|
|
pass->setUniformAmbientLigthColor(&ambientLightColor, sizeof(ambientLightColor));
|
|
|
|
}
|
2021-12-25 10:04:45 +08:00
|
|
|
else // normal does not exist
|
2019-02-15 14:30:10 +08:00
|
|
|
{
|
|
|
|
Vec3 ambient(0.0f, 0.0f, 0.0f);
|
|
|
|
bool hasAmbient = false;
|
|
|
|
for (const auto& light : lights)
|
|
|
|
{
|
|
|
|
if (light->getLightType() == LightType::AMBIENT)
|
|
|
|
{
|
|
|
|
bool useLight = light->isEnabled() && ((unsigned int)light->getLightFlag() & lightmask);
|
|
|
|
if (useLight)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
hasAmbient = true;
|
|
|
|
const Color3B& col = light->getDisplayedColor();
|
2019-02-15 14:30:10 +08:00
|
|
|
ambient.x += col.r * light->getIntensity();
|
|
|
|
ambient.y += col.g * light->getIntensity();
|
|
|
|
ambient.z += col.b * light->getIntensity();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (hasAmbient)
|
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
ambient.x /= 255.f;
|
|
|
|
ambient.y /= 255.f;
|
|
|
|
ambient.z /= 255.f;
|
|
|
|
// override the uniform value of u_color using the calculated color
|
2019-02-15 14:30:10 +08:00
|
|
|
auto fcolor = Vec4(color.x * ambient.x, color.y * ambient.y, color.z * ambient.z, color.w);
|
|
|
|
pass->setUniformColor(&fcolor, sizeof(fcolor));
|
|
|
|
}
|
|
|
|
}
|
2014-08-22 13:52:03 +08:00
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
void Mesh::setBlendFunc(const BlendFunc& blendFunc)
|
2014-08-22 13:52:03 +08:00
|
|
|
{
|
2015-05-06 04:07:32 +08:00
|
|
|
// Blend 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
|
2021-12-25 10:04:45 +08:00
|
|
|
if (_blend != blendFunc)
|
2015-05-06 04:07:32 +08:00
|
|
|
{
|
|
|
|
_blendDirty = true;
|
2021-12-25 10:04:45 +08:00
|
|
|
_blend = blendFunc;
|
2015-05-06 04:07:32 +08:00
|
|
|
}
|
|
|
|
|
2021-12-25 10:04:45 +08:00
|
|
|
if (_material)
|
|
|
|
{
|
|
|
|
// TODO set blend to Pass
|
2019-02-15 14:30:10 +08:00
|
|
|
_material->getStateBlock().setBlendFunc(blendFunc);
|
2015-05-06 04:07:32 +08:00
|
|
|
bindMeshCommand();
|
|
|
|
}
|
2014-08-22 13:52:03 +08:00
|
|
|
}
|
2015-05-06 06:59:41 +08:00
|
|
|
|
2015-05-06 04:07:32 +08:00
|
|
|
const BlendFunc& Mesh::getBlendFunc() const
|
2014-08-22 13:52:03 +08:00
|
|
|
{
|
2021-12-25 10:04:45 +08:00
|
|
|
// return _material->_currentTechnique->_passes.at(0)->getBlendFunc();
|
2014-08-22 13:52:03 +08:00
|
|
|
return _blend;
|
|
|
|
}
|
|
|
|
|
2019-01-30 09:35:17 +08:00
|
|
|
CustomCommand::PrimitiveType Mesh::getPrimitiveType() const
|
2014-08-22 13:52:03 +08:00
|
|
|
{
|
|
|
|
return _meshIndexData->getPrimitiveType();
|
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t Mesh::getIndexCount() const
|
|
|
|
{
|
2019-01-30 09:35:17 +08:00
|
|
|
return _meshIndexData->getIndexBuffer()->getSize() / sizeof(uint16_t);
|
2014-08-22 13:52:03 +08:00
|
|
|
}
|
|
|
|
|
2019-01-30 09:35:17 +08:00
|
|
|
CustomCommand::IndexFormat Mesh::getIndexFormat() const
|
2014-08-22 13:52:03 +08:00
|
|
|
{
|
2019-01-30 09:35:17 +08:00
|
|
|
return CustomCommand::IndexFormat::U_SHORT;
|
2014-08-22 13:52:03 +08:00
|
|
|
}
|
|
|
|
|
2019-01-30 09:35:17 +08:00
|
|
|
backend::Buffer* Mesh::getIndexBuffer() const
|
2014-08-22 13:52:03 +08:00
|
|
|
{
|
2019-01-30 09:35:17 +08:00
|
|
|
return _meshIndexData->getIndexBuffer();
|
2014-08-22 13:52:03 +08:00
|
|
|
}
|
2014-05-19 05:49:16 +08:00
|
|
|
NS_CC_END
|