Last active
June 27, 2017 03:50
-
-
Save victorholt/955ae2f76173d1a5d3b9f65fefcbb47e to your computer and use it in GitHub Desktop.
CustomMesh Src Refactored
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Created by Victor Holt on 3/18/2017. | |
// | |
#include <gs-graphics/CustomMesh.h> | |
using namespace Urho3D; | |
using namespace Sencha; | |
//! Constructor. | |
//! \param context | |
//! \param isDynamic | |
CustomMesh::CustomMesh(Context* context, bool isDynamic) | |
: Object(context) | |
{ | |
scale_ = 1.0f; | |
isDynamic_ = isDynamic; | |
calcNormals_ = false; | |
calcTangents_ = false; | |
model_ = nullptr; | |
geometry_ = nullptr; | |
vertexBuffer_ = nullptr; | |
indexBuffer_ = nullptr; | |
manualAddIndex_ = false; | |
useLargeIndices_ = false; | |
useRawDataOnly_ = false; | |
} | |
//! Destructor. | |
CustomMesh::~CustomMesh() | |
{ | |
// Delete the faces. | |
for (auto face : faces_) { | |
delete face; | |
} | |
faces_.Clear(); | |
for (auto vert : meshVertexList_) { | |
delete vert; | |
} | |
meshVertexList_.Clear(); | |
vertexData_.Clear(); | |
indexData_.Clear(); | |
} | |
//! Adds a face to the mesh. | |
//! \param v0 | |
//! \param v1 | |
//! \param v2 | |
MeshFace* CustomMesh::AddFace(const Vector3& v0, const Vector3& v1, const Vector3& v2, const MeshUVType& uvType) | |
{ | |
MeshVertex* vert0 = AddVertex(v0, uvType); | |
MeshVertex* vert1 = AddVertex(v1, uvType); | |
MeshVertex* vert2 = AddVertex(v2, uvType); | |
MeshFace* face = CreateFace(vert0, vert1, vert2); | |
return face; | |
} | |
//! Adds a vertex. | |
//! \param v | |
//! \param uvType | |
MeshVertex* CustomMesh::AddVertex(const Vector3& v, const MeshUVType& uvType) | |
{ | |
MutexLock lock(meshLock_); | |
MeshVertex* vert = new MeshVertex(); | |
vert->vertex_ = v; | |
vert->normal_ = Vector3::ZERO; | |
vert->uv_ = Vector2::ZERO; | |
vert->tangent_ = Vector4::ZERO; | |
vert->uvType_ = uvType; | |
meshVertexList_.Push(vert); | |
useRawDataOnly_ = false; | |
return vert; | |
} | |
//! Adds an index. | |
//! \param index | |
void CustomMesh::AddIndex(uint16_t index) | |
{ | |
MutexLock lock(meshLock_); | |
indexData_.Push(index); | |
manualAddIndex_ = true; | |
useLargeIndices_ = false; | |
} | |
//! Adds an index. | |
//! \param index | |
void CustomMesh::AddLargeIndex(uint32_t index) | |
{ | |
MutexLock lock(meshLock_); | |
largeIndexData_.Push(index); | |
useLargeIndices_ = true; | |
manualAddIndex_ = true; | |
} | |
//! Sets the face of the mesh based on the given index. | |
//! \param i | |
//! \param face | |
void CustomMesh::SetFace(unsigned int i, const MeshFace& face) | |
{ | |
MutexLock lock(meshLock_); | |
faces_[i]->v0_ = face.v0_; | |
faces_[i]->v1_ = face.v1_; | |
faces_[i]->v2_ = face.v2_; | |
} | |
//! Returns the face of the mesh from a given index. | |
//! \param i | |
//! \return | |
MeshFace* CustomMesh::GetFace(unsigned int i) | |
{ | |
return faces_[i]; | |
} | |
//! Commits changes to the mesh. | |
//! \param updateNormals | |
//! \param updateTangents | |
void CustomMesh::Commit(bool updateNormals, bool updateTangents) | |
{ | |
if (IsNullObject(model_)) { | |
CreateMesh(updateNormals, updateTangents); | |
} else { | |
UpdateMesh(updateNormals, updateTangents); | |
} | |
} | |
//! Builds the mesh. | |
//! \param updateNormals | |
//! \param updateTangents | |
void CustomMesh::CreateMesh(bool updateNormals, bool updateTangents) | |
{ | |
MutexLock lock(meshLock_); | |
if (updateNormals) { | |
CalculateNormals(false); | |
} | |
GenerateVertexData(); | |
if (updateTangents) { | |
CalculateTangents(false); | |
UpdateVertexData(); | |
} | |
if(IsNullObject(model_)) | |
model_ = new Model(context_); | |
if (IsNullObject(vertexBuffer_)) | |
vertexBuffer_ = new VertexBuffer(context_); | |
if (IsNullObject(indexBuffer_)) | |
indexBuffer_ = new IndexBuffer(context_); | |
if (IsNullObject(geometry_)) | |
geometry_ = new Geometry(context_); | |
vertexBuffer_->SetShadowed(true); | |
indexBuffer_->SetShadowed(true); | |
uint32_t numIndices = 0; | |
if (useRawDataOnly_) { | |
numIndices = rawData_.numIndices_; | |
PODVector<VertexElement> elements = rawData_.elements_; | |
vertexBuffer_->SetSize(rawData_.numVerts_, rawData_.elements_, isDynamic_); | |
indexBuffer_->SetSize(rawData_.numIndices_, useLargeIndices_, isDynamic_); | |
vertexBuffer_->SetData(rawData_.vertexData_); | |
if (useLargeIndices_) { | |
indexBuffer_->SetData(rawData_.largeIndexData_); | |
} else { | |
indexBuffer_->SetData(rawData_.indexData_); | |
} | |
model_->SetBoundingBox(rawData_.boundingBox_); | |
} else { | |
if (useLargeIndices_) { | |
numIndices = largeIndexData_.Size(); | |
} else { | |
numIndices = indexData_.Size(); | |
} | |
PODVector<VertexElement> elements; | |
elements.Push(VertexElement(TYPE_VECTOR3, SEM_POSITION)); | |
elements.Push(VertexElement(TYPE_VECTOR3, SEM_NORMAL)); | |
elements.Push(VertexElement(TYPE_VECTOR2, SEM_TEXCOORD)); | |
elements.Push(VertexElement(TYPE_VECTOR4, SEM_TANGENT)); | |
vertexBuffer_->SetSize(numIndices, elements, isDynamic_); | |
indexBuffer_->SetSize(numIndices, useLargeIndices_, isDynamic_); | |
vertexBuffer_->SetData(vertexData_.Buffer()); | |
if (useLargeIndices_) { | |
indexBuffer_->SetData(largeIndexData_.Buffer()); | |
} else { | |
indexBuffer_->SetData(indexData_.Buffer()); | |
} | |
model_->SetBoundingBox(boundingBox_); | |
} | |
geometry_->SetNumVertexBuffers(1); | |
geometry_->SetVertexBuffer(0, vertexBuffer_); | |
geometry_->SetIndexBuffer(indexBuffer_); | |
geometry_->SetDrawRange(TRIANGLE_LIST, 0, numIndices); | |
model_->SetNumGeometries(1); | |
model_->SetGeometry(0, 0, geometry_); | |
Vector<SharedPtr<VertexBuffer>> vertexBuffers; | |
Vector<SharedPtr<IndexBuffer>> indexBuffers; | |
vertexBuffers.Push(vertexBuffer_); | |
indexBuffers.Push(indexBuffer_); | |
PODVector<unsigned> morphRangeStarts; | |
PODVector<unsigned> morphRangeCounts; | |
morphRangeStarts.Push(0); | |
morphRangeCounts.Push(0); | |
model_->SetVertexBuffers(vertexBuffers, morphRangeStarts, morphRangeCounts); | |
model_->SetIndexBuffers(indexBuffers); | |
} | |
void CustomMesh::GenerateVertexData() | |
{ | |
if (useRawDataOnly_) return; | |
boundingBox_.Clear(); | |
if (!manualAddIndex_) { | |
if (useLargeIndices_) { | |
largeIndexData_.Clear(); | |
largeIndexData_.Reserve(meshVertexList_.Size() / 3); | |
} else { | |
indexData_.Clear(); | |
indexData_.Reserve(meshVertexList_.Size() / 3); | |
} | |
} | |
// Create faces. | |
uint16_t lastFaceVertIndexStart = 0; | |
unsigned faceIndex = 0; | |
for (unsigned int i = 0; i < meshVertexList_.Size(); i += 3) { | |
MeshVertex* v0 = meshVertexList_[i]; | |
MeshVertex* v1 = meshVertexList_[i + 1]; | |
MeshVertex* v2 = meshVertexList_[i + 2]; | |
boundingBox_.Merge(v0->vertex_); | |
boundingBox_.Merge(v1->vertex_); | |
boundingBox_.Merge(v2->vertex_); | |
if (faces_.Size() > 0) { | |
MeshFace* face = faces_[faceIndex]; | |
if (!IsNullObject(face)) { | |
face->vertIndexStart_ = i * 12; | |
faceIndex++; | |
} | |
} | |
if (!manualAddIndex_) { | |
if (useLargeIndices_) { | |
largeIndexData_.Push(lastFaceVertIndexStart); | |
largeIndexData_.Push(static_cast<uint32_t>(lastFaceVertIndexStart + 1)); | |
largeIndexData_.Push(static_cast<uint32_t>(lastFaceVertIndexStart + 2)); | |
} else { | |
indexData_.Push(lastFaceVertIndexStart); | |
indexData_.Push(static_cast<uint16_t>(lastFaceVertIndexStart + 1)); | |
indexData_.Push(static_cast<uint16_t>(lastFaceVertIndexStart + 2)); | |
} | |
lastFaceVertIndexStart += 3; | |
} | |
} | |
// Update vertex data. | |
UpdateVertexData(); | |
} | |
void CustomMesh::UpdateVertexData() | |
{ | |
if (useRawDataOnly_) return; | |
vertexData_.Clear(); | |
// MeshVertex = 12 | |
vertexData_.Reserve(meshVertexList_.Size() * 12); | |
// Update vertex data. | |
int numFaces = faces_.Size(); | |
for (unsigned int i = 0; i < numFaces; i++) { | |
// Update vertices. | |
// Face #1 | |
vertexData_.Push(faces_[i]->v0_->vertex_.x_); | |
vertexData_.Push(faces_[i]->v0_->vertex_.y_); | |
vertexData_.Push(faces_[i]->v0_->vertex_.z_); | |
vertexData_.Push(faces_[i]->v0_->normal_.x_); | |
vertexData_.Push(faces_[i]->v0_->normal_.y_); | |
vertexData_.Push(faces_[i]->v0_->normal_.z_); | |
vertexData_.Push(faces_[i]->v0_->uv_.x_); | |
vertexData_.Push(faces_[i]->v0_->uv_.y_); | |
vertexData_.Push(faces_[i]->v0_->tangent_.x_); | |
vertexData_.Push(faces_[i]->v0_->tangent_.y_); | |
vertexData_.Push(faces_[i]->v0_->tangent_.z_); | |
vertexData_.Push(faces_[i]->v0_->tangent_.w_); | |
// Face #2 | |
vertexData_.Push(faces_[i]->v1_->vertex_.x_); | |
vertexData_.Push(faces_[i]->v1_->vertex_.y_); | |
vertexData_.Push(faces_[i]->v1_->vertex_.z_); | |
vertexData_.Push(faces_[i]->v1_->normal_.x_); | |
vertexData_.Push(faces_[i]->v1_->normal_.y_); | |
vertexData_.Push(faces_[i]->v1_->normal_.z_); | |
vertexData_.Push(faces_[i]->v1_->uv_.x_); | |
vertexData_.Push(faces_[i]->v1_->uv_.y_); | |
vertexData_.Push(faces_[i]->v1_->tangent_.x_); | |
vertexData_.Push(faces_[i]->v1_->tangent_.y_); | |
vertexData_.Push(faces_[i]->v1_->tangent_.z_); | |
vertexData_.Push(faces_[i]->v1_->tangent_.w_); | |
// Face #3 | |
vertexData_.Push(faces_[i]->v2_->vertex_.x_); | |
vertexData_.Push(faces_[i]->v2_->vertex_.y_); | |
vertexData_.Push(faces_[i]->v2_->vertex_.z_); | |
vertexData_.Push(faces_[i]->v2_->normal_.x_); | |
vertexData_.Push(faces_[i]->v2_->normal_.y_); | |
vertexData_.Push(faces_[i]->v2_->normal_.z_); | |
vertexData_.Push(faces_[i]->v2_->uv_.x_); | |
vertexData_.Push(faces_[i]->v2_->uv_.y_); | |
vertexData_.Push(faces_[i]->v2_->tangent_.x_); | |
vertexData_.Push(faces_[i]->v2_->tangent_.y_); | |
vertexData_.Push(faces_[i]->v2_->tangent_.z_); | |
vertexData_.Push(faces_[i]->v2_->tangent_.w_); | |
} | |
} | |
MeshFace* CustomMesh::CreateFace(MeshVertex* v0, MeshVertex* v1, MeshVertex* v2) | |
{ | |
MeshFace* face = new MeshFace(); | |
face->v0_ = v0; | |
face->v1_ = v1; | |
face->v2_ = v2; | |
MeshUVType uvType = v0->uvType_; | |
if (uvType == MeshUVType::UV_XY) { | |
face->v0_->uv_ = Vector2(v0->vertex_.x_ / scale_, v0->vertex_.y_ / scale_); | |
face->v1_->uv_ = Vector2(v1->vertex_.x_ / scale_, v1->vertex_.y_ / scale_); | |
face->v2_->uv_ = Vector2(v2->vertex_.x_ / scale_, v2->vertex_.y_ / scale_); | |
} else if (uvType == MeshUVType::UV_XZ) { | |
face->v0_->uv_ = Vector2(v0->vertex_.x_ / scale_, v0->vertex_.z_ / scale_); | |
face->v1_->uv_ = Vector2(v1->vertex_.x_ / scale_, v1->vertex_.z_ / scale_); | |
face->v2_->uv_ = Vector2(v2->vertex_.x_ / scale_, v2->vertex_.z_ / scale_); | |
} else if (uvType == MeshUVType::UV_YZ) { | |
face->v0_->uv_ = Vector2(v0->vertex_.y_ / scale_, v0->vertex_.z_ / scale_); | |
face->v1_->uv_ = Vector2(v1->vertex_.y_ / scale_, v1->vertex_.z_ / scale_); | |
face->v2_->uv_ = Vector2(v2->vertex_.y_ / scale_, v2->vertex_.z_ / scale_); | |
} else if (uvType == MeshUVType::UV_ZY) { | |
face->v0_->uv_ = Vector2(v0->vertex_.z_ / scale_, v0->vertex_.y_ / scale_); | |
face->v1_->uv_ = Vector2(v1->vertex_.z_ / scale_, v1->vertex_.y_ / scale_); | |
face->v2_->uv_ = Vector2(v2->vertex_.z_ / scale_, v2->vertex_.y_ / scale_); | |
} | |
face->vertIndexStart_ = 0; | |
faces_.Push(face); | |
return face; | |
} | |
//! Updates the mesh. | |
//! \param updateNormals | |
//! \param updateTangents | |
void CustomMesh::UpdateMesh(bool updateNormals, bool updateTangents) | |
{ | |
MutexLock lock(meshLock_); | |
if (updateNormals) { | |
CalculateNormals(false); | |
} | |
GenerateVertexData(); | |
if (updateTangents) { | |
CalculateTangents(false); | |
UpdateVertexData(); | |
} | |
unsigned char* vertexData = (unsigned char*)vertexBuffer_->Lock(0, vertexBuffer_->GetVertexCount()); | |
if (!vertexData) return; | |
uint32_t numIndices = 0; | |
if (useRawDataOnly_) { | |
PODVector<VertexElement> elements = rawData_.elements_; | |
vertexBuffer_->SetSize(rawData_.numVerts_, rawData_.elements_, isDynamic_); | |
indexBuffer_->SetSize(rawData_.numIndices_, useLargeIndices_, isDynamic_); | |
vertexBuffer_->SetData(rawData_.vertexData_); | |
if (useLargeIndices_) { | |
indexBuffer_->SetData(rawData_.largeIndexData_); | |
} else { | |
indexBuffer_->SetData(rawData_.indexData_); | |
} | |
model_->SetBoundingBox(rawData_.boundingBox_); | |
} else { | |
numIndices = faces_.Size() * 3; | |
PODVector<VertexElement> elements; | |
elements.Push(VertexElement(TYPE_VECTOR3, SEM_POSITION)); | |
elements.Push(VertexElement(TYPE_VECTOR3, SEM_NORMAL)); | |
elements.Push(VertexElement(TYPE_VECTOR2, SEM_TEXCOORD)); | |
elements.Push(VertexElement(TYPE_VECTOR4, SEM_TANGENT)); | |
vertexBuffer_->SetSize(numIndices, elements, isDynamic_); | |
indexBuffer_->SetSize(numIndices, useLargeIndices_, isDynamic_); | |
vertexBuffer_->SetData(vertexData_.Buffer()); | |
if (useLargeIndices_) { | |
indexBuffer_->SetData(largeIndexData_.Buffer()); | |
} else { | |
indexBuffer_->SetData(indexData_.Buffer()); | |
} | |
model_->SetBoundingBox(boundingBox_); | |
} | |
vertexBuffer_->Unlock(); | |
} | |
//! Updates the bounding box for the mesh. | |
void CustomMesh::UpdateBoundingBox() | |
{ | |
MutexLock lock(calcMeshLock_); | |
boundingBox_.Clear(); | |
for (unsigned int i = 0; i < meshVertexList_.Size(); i += 3) { | |
boundingBox_.Merge(meshVertexList_[i]->vertex_); | |
boundingBox_.Merge(meshVertexList_[i + 1]->vertex_); | |
boundingBox_.Merge(meshVertexList_[i + 2]->vertex_); | |
} | |
} | |
//! Calculates the mesh normals. | |
//! \param check | |
void CustomMesh::CalculateNormals(bool check) | |
{ | |
MutexLock lock(calcMeshLock_); | |
if (check && calcNormals_) return; | |
calcNormals_ = true; | |
for (unsigned int i = 0; i < meshVertexList_.Size(); i) { | |
MeshVertex* v0 = meshVertexList_[i++]; | |
MeshVertex* v1 = meshVertexList_[i++]; | |
MeshVertex* v2 = meshVertexList_[i++]; | |
Vector3 edge1 = v0->vertex_ - v1->vertex_; | |
Vector3 edge2 = v0->vertex_ - v2->vertex_; | |
v0->normal_ = v1->normal_ = v2->normal_ = edge1.CrossProduct(edge2).Normalized(); | |
} | |
} | |
//! Calculates the mesh tangents. | |
//! \param check | |
void CustomMesh::CalculateTangents(bool check) | |
{ | |
if (useRawDataOnly_) return; | |
MutexLock lock(calcMeshLock_); | |
if (check && calcTangents_) return; | |
calcTangents_ = true; | |
float* vertData = vertexData_.Buffer(); | |
uint16_t* indexData = indexData_.Buffer(); | |
uint32_t* largeIndexData = largeIndexData_.Buffer(); | |
if (IsNullObject(vertData) || IsNullObject(indexData)) return; | |
if (!useLargeIndices_) { | |
GenerateTangents(vertData, 12 * sizeof(float), indexData, sizeof(uint16_t), 0, faces_.Size() * 3, | |
3 * sizeof(float), 6 * sizeof(float), 8 * sizeof(float)); | |
} else { | |
GenerateTangents(vertData, 12 * sizeof(float), largeIndexData, sizeof(uint32_t), 0, faces_.Size() * 3, | |
3 * sizeof(float), 6 * sizeof(float), 8 * sizeof(float)); | |
} | |
unsigned j = 0; | |
for (unsigned int i = 0; i < faces_.Size(); i++) { | |
faces_[i]->v0_->tangent_ = *(reinterpret_cast<Vector4*>(&vertData[faces_[i]->vertIndexStart_ + 8])); | |
faces_[i]->v1_->tangent_ = *(reinterpret_cast<Vector4*>(&vertData[faces_[i]->vertIndexStart_ + 12])); | |
faces_[i]->v2_->tangent_ = *(reinterpret_cast<Vector4*>(&vertData[faces_[i]->vertIndexStart_ + 16])); | |
j += 3; | |
} | |
} | |
//! Updates the texture coordinates. | |
void CustomMesh::UpdateTexCoords() | |
{ | |
MutexLock lock(calcMeshLock_); | |
for (unsigned int i = 0; i < faces_.Size(); i++) { | |
MeshFace* face = faces_[i]; | |
MeshVertex* v0 = face->v0_; | |
MeshVertex* v1 = face->v1_; | |
MeshVertex* v2 = face->v2_; | |
MeshUVType uvType = face->v0_->uvType_; | |
if (uvType == MeshUVType::UV_XY) { | |
face->v0_->uv_ = Vector2(v0->vertex_.x_, v0->vertex_.y_); | |
face->v1_->uv_ = Vector2(v1->vertex_.x_, v1->vertex_.y_); | |
face->v2_->uv_ = Vector2(v2->vertex_.x_, v2->vertex_.y_); | |
} else if (uvType == MeshUVType::UV_XZ) { | |
face->v0_->uv_ = Vector2(v0->vertex_.x_, v0->vertex_.z_); | |
face->v1_->uv_ = Vector2(v1->vertex_.x_, v1->vertex_.z_); | |
face->v2_->uv_ = Vector2(v2->vertex_.x_, v2->vertex_.z_); | |
} else if (uvType == MeshUVType::UV_YZ) { | |
face->v0_->uv_ = Vector2(v0->vertex_.y_, v0->vertex_.z_); | |
face->v1_->uv_ = Vector2(v1->vertex_.y_, v1->vertex_.z_); | |
face->v2_->uv_ = Vector2(v2->vertex_.y_, v2->vertex_.z_); | |
} else if (uvType == MeshUVType::UV_ZY) { | |
face->v0_->uv_ = Vector2(v0->vertex_.z_, v0->vertex_.y_); | |
face->v1_->uv_ = Vector2(v1->vertex_.z_, v1->vertex_.y_); | |
face->v2_->uv_ = Vector2(v2->vertex_.z_, v2->vertex_.y_); | |
} | |
// if (uvType == MeshUVType::UV_XY) { | |
// face->v0_->uv_ = Vector2(face->v0_->vertex_.x_, face->v0_->vertex_.y_); | |
// face->v1_->uv_ = Vector2(face->v1_->vertex_.x_, face->v1_->vertex_.y_); | |
// face->v2_->uv_ = Vector2(face->v2_->vertex_.x_, face->v2_->vertex_.y_); | |
// } else if (uvType == MeshUVType::UV_XZ) { | |
// face->v0_->uv_ = Vector2(face->v0_->vertex_.x_, face->v0_->vertex_.z_); | |
// face->v1_->uv_ = Vector2(face->v1_->vertex_.x_, face->v1_->vertex_.z_); | |
// face->v2_->uv_ = Vector2(face->v2_->vertex_.x_, face->v2_->vertex_.z_); | |
// } else if (uvType == MeshUVType::UV_YZ) { | |
// face->v0_->uv_ = Vector2(face->v0_->vertex_.y_, face->v0_->vertex_.z_); | |
// face->v1_->uv_ = Vector2(face->v1_->vertex_.y_, face->v1_->vertex_.z_); | |
// face->v2_->uv_ = Vector2(face->v2_->vertex_.y_, face->v2_->vertex_.z_); | |
// } else if (uvType == MeshUVType::UV_ZY) { | |
// face->v0_->uv_ = Vector2(face->v0_->vertex_.z_, face->v0_->vertex_.y_); | |
// face->v1_->uv_ = Vector2(face->v1_->vertex_.z_, face->v1_->vertex_.y_); | |
// face->v2_->uv_ = Vector2(face->v2_->vertex_.z_, face->v2_->vertex_.y_); | |
// } | |
} | |
} | |
//! Clears all vertex data of the mesh. | |
void CustomMesh::Clear() | |
{ | |
MutexLock lock(meshLock_); | |
for (auto face : faces_) { | |
delete face; | |
} | |
for (auto vert : meshVertexList_) { | |
delete vert; | |
} | |
faces_.Clear(); | |
meshVertexList_.Clear(); | |
vertexData_.Clear(); | |
indexData_.Clear(); | |
largeIndexData_.Clear(); | |
boundingBox_.Clear(); | |
} | |
//! Saves the mesh to a file. | |
//! \param path | |
void CustomMesh::Save(const String& path) | |
{ | |
if (IsNullObject(model_)) | |
{ | |
URHO3D_LOGERROR("CustomMesh::Save Mesh is not built"); | |
return; | |
} | |
File file(context_, path, FILE_WRITE); | |
if (file.IsOpen()) { | |
model_->Save(file); | |
} | |
file.Close(); | |
} | |
//! Returns the mesh geometry. | |
//! \return | |
Geometry* CustomMesh::GetGeometry() | |
{ | |
return geometry_; | |
} | |
//! Returns the mesh model. | |
//! \return | |
Model* CustomMesh::GetModel() | |
{ | |
return model_; | |
} | |
void CustomMesh::SetRawData(const MeshRawData& rawData) | |
{ | |
rawData_ = rawData; | |
} | |
//! Returns the mesh vertex buffer. | |
//! \return | |
VertexBuffer* CustomMesh::GetVertexBuffer() | |
{ | |
return vertexBuffer_; | |
} | |
//! Returns the mesh index buffer. | |
//! \return | |
IndexBuffer* CustomMesh::GetIndexBuffer() | |
{ | |
return indexBuffer_; | |
} | |
void CustomMesh::RotateFace(MeshFace* face, const Quaternion& rot) | |
{ | |
if (IsNullObject(face)) return; | |
MeshVertex* v0 = face->v0_; | |
MeshVertex* v1 = face->v1_; | |
MeshVertex* v2 = face->v2_; | |
Matrix3x4 transform = Matrix3x4::IDENTITY; | |
transform.SetRotation(rot.RotationMatrix()); | |
BoundingBox boundingBox; | |
boundingBox.Merge(v0->vertex_); | |
boundingBox.Merge(v1->vertex_); | |
boundingBox.Merge(v2->vertex_); | |
Vector3 center = boundingBox.Center(); | |
v0->vertex_ = transform.Rotation().Inverse() * (v0->vertex_ - center); | |
v1->vertex_ = transform.Rotation().Inverse() * (v1->vertex_ - center); | |
v2->vertex_ = transform.Rotation().Inverse() * (v2->vertex_ - center); | |
} | |
void CustomMesh::RotateFaceByIndex(unsigned faceIndex, const Quaternion& rot) | |
{ | |
if (faces_.Size() < faceIndex) return; | |
MeshFace* face = faces_[faceIndex]; | |
RotateFace(face, rot); | |
} | |
void CustomMesh::Rotate(const Quaternion& rot) | |
{ | |
// Go through the vertices and rotate them. | |
transform_.SetRotation(rot.RotationMatrix()); | |
for (unsigned int i = 0; i < meshVertexList_.Size(); i) { | |
MeshVertex* v0 = meshVertexList_[i++]; | |
MeshVertex* v1 = meshVertexList_[i++]; | |
MeshVertex* v2 = meshVertexList_[i++]; | |
BoundingBox boundingBox; | |
boundingBox.Merge(v0->vertex_); | |
boundingBox.Merge(v1->vertex_); | |
boundingBox.Merge(v2->vertex_); | |
Vector3 center = boundingBox.Center(); | |
v0->vertex_ = transform_.Rotation().Inverse() * (v0->vertex_ - center); | |
v1->vertex_ = transform_.Rotation().Inverse() * (v1->vertex_ - center); | |
v2->vertex_ = transform_.Rotation().Inverse() * (v2->vertex_ - center); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment