Page MenuHomePhorge

SubMesh.cpp
No OneTemporary

Size
11 KB
Referenced Files
None
Subscribers
None

SubMesh.cpp

#include <echo/Graphics/SubMesh.h>
#include <echo/Graphics/Mesh.h>
#include <iostream>
#include <echo/Graphics/RenderTarget.h>
namespace Echo
{
SubMesh::SubMesh(const std::string& name, Mesh& parent) : mParent(parent), mName(name), mVisible(true), mMinMaxOutOfDate(true), mType(MeshTypes::TRIANGLES)
{
mMin.SetZero();
mMax.SetZero();
mNormals = shared_ptr< std::vector<Vector3> >(new std::vector<Vector3>);
mVertices = shared_ptr< std::vector<Vector3> >(new std::vector<Vector3>);
mColours = shared_ptr< std::vector<VertexColour> >(new std::vector<VertexColour>);
mIndices = shared_ptr< std::vector<u16> >(new std::vector<u16>());
mTextureCoordinates = shared_ptr< std::vector< shared_ptr< std::vector<TextureUV> > > >(new std::vector< shared_ptr< std::vector<TextureUV> > >);
}
shared_ptr<SubMesh> SubMesh::Clone(Mesh& clonesParent) const
{
SubMesh* newMesh = new SubMesh(mName, clonesParent);
if(mMaterial)
{
newMesh->mMaterial = mMaterial->Clone();
}
if(mNormals)
{
newMesh->mNormals = shared_ptr< std::vector<Vector3> >(new std::vector<Vector3>(*mNormals));
}
if(mVertices)
{
newMesh->mVertices = shared_ptr< std::vector<Vector3> >(new std::vector<Vector3>(*mVertices));
}
if(mOriginalVertices)
{
newMesh->mOriginalVertices = shared_ptr< std::vector<Vector3> >(new std::vector<Vector3>(*mOriginalVertices));
}
if(mBoneWeights)
{
newMesh->mBoneWeights = shared_ptr< std::vector<BoneBinding*> >(new std::vector<BoneBinding*>(*mBoneWeights));
}
if(mColours)
{
newMesh->mColours = shared_ptr< std::vector<VertexColour> >(new std::vector<VertexColour>(*mColours));
}
if(mIndices)
{
newMesh->mIndices = shared_ptr< std::vector<u16> >(new std::vector<u16>(*mIndices));
}
if(mTextureCoordinates)
{
std::vector< shared_ptr< std::vector<TextureUV> > >* newVect = new std::vector< shared_ptr< std::vector<TextureUV> > >();
newVect->reserve(mTextureCoordinates->size());
BOOST_FOREACH(shared_ptr< std::vector<TextureUV> >& ptr, *mTextureCoordinates)
{
if(ptr)
{
newVect->push_back(shared_ptr< std::vector<TextureUV> >(new std::vector<TextureUV>(*ptr)));
}
}
newMesh->mTextureCoordinates = shared_ptr< std::vector< shared_ptr< std::vector<TextureUV> > > >(newVect);
}
newMesh->mMin = mMin;
newMesh->mMax = mMax;
newMesh->mType = mType;
return shared_ptr<SubMesh> (newMesh);
}
void SubMesh::CalculateAABB()
{
if(mVertices->empty())
{
mMin.SetZero();
mMax.SetZero();
}else
{
mMin.Set(9999999000.0f, 9999999000.0f, 9999999000.0f);
mMax.Set(-9999999000.0f, -9999999000.0f, -9999999000.0f);
for(size_t i = 0; i < mVertices->size(); ++i)
{
Vector3& vert = (*mVertices)[i];
mMin.x = std::min(mMin.x,vert.x);
mMin.y = std::min(mMin.y,vert.y);
mMin.z = std::min(mMin.z,vert.z);
mMax.x = std::max(mMax.x,vert.x);
mMax.y = std::max(mMax.y,vert.y);
mMax.z = std::max(mMax.z,vert.z);
}
}
mMinMaxOutOfDate = false;
}
void SubMesh::TranslateVertices(const Vector3& translation)
{
//This is faster than performing a matrix operation on each vertex.
if(mVertices)
{
BOOST_FOREACH(Vector3& vertex,*mVertices)
{
vertex+=translation;
}
}
}
SubMesh::~SubMesh()
{
}
void SubMesh::Clear()
{
if(mNormals)
mNormals->clear();
if(mVertices)
mVertices->clear();
if(mColours)
mColours->clear();
if(mIndices)
mIndices->clear();
if(mTextureCoordinates)
mTextureCoordinates->clear();
mMin.SetZero();
mMax.SetZero();
}
void SubMesh::SetTextureCoordinateSet(shared_ptr< std::vector<TextureUV> > val, size_t i)
{
if(i >= (*mTextureCoordinates).size())
(*mTextureCoordinates).push_back(val);
else
(*mTextureCoordinates)[i] = val;
}
shared_ptr< std::vector<TextureUV> > SubMesh::GetTextureCoordinateSet(size_t i)
{
if(i < mTextureCoordinates->size())
return(*mTextureCoordinates)[i];
return shared_ptr< std::vector<TextureUV> >();
}
void SubMesh::SetMaterial(shared_ptr<Material> material)
{
mMaterial = material;
}
void SubMesh::CalculateNormals()
{
if(mType!=MeshTypes::TRIANGLES)
{
assert(mType==MeshTypes::TRIANGLES && "CalculateNormals only supports triangle meshes, either add your own support for this type of mesh or request the feature.");
return;
}
// Some standard mesh information that you should have lying around.
// vertex is your vertex structure that just contains a normal and position here.
// mVertices is a pointer to the first vertex
// indices is a pointer to the first index
// num_verts is number of mVertices
// num_indices is number of indices
// each face of the mesh is made up of three mVertices.
size_t num_indices = (*mIndices).size();
size_t num_vertices = (*mVertices).size();
(*mNormals) = (*mVertices);
std::vector<Vector3>* normal_buffer = new std::vector<Vector3>[num_vertices];
for(size_t i = 0; i < num_indices; i += 3)
{
// get the three mVertices that make the mFaces
Vector3 p1 = (*mVertices)[ (*mIndices)[i] ];
Vector3 p2 = (*mVertices)[ (*mIndices)[i+1] ];
Vector3 p3 = (*mVertices)[ (*mIndices)[i+2] ];
Vector3 v1 = p2 - p1;
Vector3 v2 = p3 - p1;
Vector3 normal = v1.Cross(v2);
normal.Normalise();
// Store the face's normal for each of the mVertices that make up the face.
normal_buffer[(*mIndices)[i]].push_back(normal);
normal_buffer[(*mIndices)[i+1]].push_back(normal);
normal_buffer[(*mIndices)[i+2]].push_back(normal);
}
// Now loop through each vertex vector, and average out all the mNormals stored.
for(size_t i = 0; i < num_vertices; ++i)
{
for(size_t j = 0; j < normal_buffer[i].size(); ++j)
{
(*mNormals)[i] += normal_buffer[i][j];
}
if(normal_buffer[i].size()!=0)
{
(*mNormals)[i] /= (f32) (normal_buffer[i].size());
}
(*mNormals)[i].Normalise();
}
delete [] normal_buffer;
}
void SubMesh::AddVertex(const Vector3& vertex)
{
(*mVertices).push_back(vertex);
mMinMaxOutOfDate = true;
}
void SubMesh::AddVertex(const Vector3& vertex, const Vector3& normal, const VertexColour& colour, const TextureUV& uv, u32 uvSet)
{
AddVertex(vertex);
AddNormal(normal);
AddColour(colour);
AddTextureUV(uv, uvSet);
}
void SubMesh::AddFaceSafe(const IndexedTriangle& face)
{
size_t vsize = (*mVertices).size();
if(face.a >= vsize || face.b >= vsize || face.c >= vsize)
return;
(*mIndices).push_back(face.a);
(*mIndices).push_back(face.b);
(*mIndices).push_back(face.c);
}
Vector3 SubMesh::GetCentre()
{
if(mMinMaxOutOfDate)
{
CalculateAABB();
}
return((mMax - mMin) / 2);
}
void SubMesh::AddColour(const VertexColour& colour)
{
(*mColours).push_back(colour);
}
void SubMesh::AddNormal(const Vector3& normal)
{
(*mNormals).push_back(normal);
}
void SubMesh::AddTextureUV(const TextureUV& uv, size_t set)
{
if((*mTextureCoordinates).empty())
(*mTextureCoordinates).push_back(shared_ptr< std::vector<TextureUV> >(new std::vector<TextureUV>()));
if(set >= (*mTextureCoordinates).size())
{
set = ((*mTextureCoordinates).size() - 1);
}
(*mTextureCoordinates)[set]->push_back(uv);
}
void SubMesh::AddFace(const IndexedTriangle& face)
{
(*mIndices).push_back(face.a);
(*mIndices).push_back(face.b);
(*mIndices).push_back(face.c);
}
void SubMesh::Render(const Matrix4& viewWorld, RenderTarget& renderTarget)
{
if(!mVisible || (*mVertices).empty() || (*mIndices).empty() || !mMaterial)
{
return;
}
if(mParent.GetUseSkeleton())
{
ApplyVertexBoneTransforms();
}
mMaterial->ApplyAndRender(*this, viewWorld, renderTarget);
}
void SubMesh::GenerateTransformBuffers()
{
std::vector<Vector3>* newBuffer = new std::vector<Vector3>(*mVertices);
mOriginalVertices = shared_ptr< std::vector<Vector3> >(newBuffer);
}
void SubMesh::ApplyVertexBoneTransforms()
{
std::vector<Vector3>& originalVerts = *mOriginalVertices;
std::vector<Vector3>& newVerts = *mVertices;
u32 numVerts = mVertices->size();
for(u32 v = 0; v < numVerts; ++v)
{
BoneBinding& binding = *(*mBoneWeights)[v];
newVerts[v].SetZero();
std::map< size_t, f32 >::iterator it = binding.mBoneWeights.begin();
std::map< size_t, f32 >::iterator itEnd = binding.mBoneWeights.end();
while(it != itEnd)
{
const Matrix4& trans = mParent.GetSkeleton()->GetBone(it->first)->GetOffsetTransform();
f32& weight = it->second;
newVerts[v].x += (trans[0][0] * originalVerts[v].x +
trans[0][1] * originalVerts[v].y +
trans[0][2] * originalVerts[v].z +
trans[0][3])
* weight;
newVerts[v].y += (trans[1][0] * originalVerts[v].x +
trans[1][1] * originalVerts[v].y +
trans[1][2] * originalVerts[v].z +
trans[1][3])
* weight;
newVerts[v].z += (trans[2][0] * originalVerts[v].x +
trans[2][1] * originalVerts[v].y +
trans[2][2] * originalVerts[v].z +
trans[2][3])
* weight;
++it;
}
}
mMinMaxOutOfDate = true;
mParent.MarkExtentsOutOfDate();
}
void SubMesh::Render(const RenderPass& pass, RenderTarget& renderTarget)
{
if(!mVertices)
return;
renderTarget.SetVertexSource(&(*mVertices)[0]);
if(mNormals)
{
if(mNormals->size() >= mVertices->size())
{
renderTarget.SetNormalSource(&(*mNormals)[0]);
}
}
if(pass.GetVertexColouringEnabled() && mColours)
{
if(mColours->size() >= mVertices->size())
{
renderTarget.SetColourSource(&(*mColours)[0]);
}
}
u32 numActiveTextureUnits = 0;
if(mTextureCoordinates)
{
size_t numTexSets = mTextureCoordinates->size();
for(size_t i = 0; i < pass.GetNumTextureUnits(); ++i)
{
const TextureUnit* textureUnit = pass.GetTextureUnit(i);
size_t setToUse = textureUnit->GetTextureUnitSetToUse();
if(setToUse < numTexSets)
{
shared_ptr< std::vector<TextureUV> >& textureUnitSetPtr = (*mTextureCoordinates)[setToUse];
if(textureUnitSetPtr->size() >= mVertices->size())
{
renderTarget.SetTextureCoordinateSource(&(*textureUnitSetPtr)[0],numActiveTextureUnits);
renderTarget.SetTexture2DEnabled(true);
++numActiveTextureUnits;
}
}
}
}
if(mIndices)
{
if(pass.mProgram)
{
pass.mProgram->SetVector3AttributeStream("position", &(*mVertices)[0]);
pass.mProgram->SetActive();
}
switch(mType)
{
case MeshTypes::TRIANGLES:
renderTarget.DrawTriangles(*mIndices);
break;
case MeshTypes::TRIANGLE_STRIP:
renderTarget.DrawTriangleStrip(*mIndices);
break;
case MeshTypes::POINTS:
renderTarget.DrawPoints(*mIndices,mPointAndLineSize);
break;
case MeshTypes::LINES:
renderTarget.DrawLines(*mIndices,mPointAndLineSize);
break;
case MeshTypes::LINE_STRIP:
renderTarget.DrawLineStrip(*mIndices,mPointAndLineSize);
break;
}
if(pass.mProgram)
{
pass.mProgram->SetInactive();
}
}
if(mTextureCoordinates)
{
for(size_t i = 0; i < numActiveTextureUnits; ++i)
{
renderTarget.SetTextureCoordinateSource(0,numActiveTextureUnits-i-1);
renderTarget.SetTexture2DEnabled(false);
}
}
if(pass.GetVertexColouringEnabled())
{
renderTarget.SetColourSource(static_cast<VertexColour*>(0));
}
if(mNormals)
{
renderTarget.SetNormalSource(0);
}
renderTarget.SetVertexSource(static_cast<Vector3*>(0));
}
}

File Metadata

Mime Type
text/x-c++
Expires
Wed, Jan 15, 8:43 PM (2 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
72050
Default Alt Text
SubMesh.cpp (11 KB)

Event Timeline