926 lines
23 KiB
C++
926 lines
23 KiB
C++
|
/*
|
||
|
* Copyright (C) 2012 Open Source Robotics Foundation
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*
|
||
|
*/
|
||
|
#include <float.h>
|
||
|
#include <string.h>
|
||
|
#include <algorithm>
|
||
|
|
||
|
#include "gazebo/math/Helpers.hh"
|
||
|
|
||
|
#include "gazebo/common/Material.hh"
|
||
|
#include "gazebo/common/Exception.hh"
|
||
|
#include "gazebo/common/Console.hh"
|
||
|
#include "gazebo/common/Mesh.hh"
|
||
|
#include "gazebo/common/Skeleton.hh"
|
||
|
#include "gazebo/gazebo_config.h"
|
||
|
|
||
|
using namespace gazebo;
|
||
|
using namespace common;
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
Mesh::Mesh()
|
||
|
{
|
||
|
this->name = "unknown";
|
||
|
this->skeleton = NULL;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
Mesh::~Mesh()
|
||
|
{
|
||
|
for (std::vector<SubMesh*>::iterator iter = this->submeshes.begin();
|
||
|
iter != this->submeshes.end(); ++iter)
|
||
|
{
|
||
|
delete *iter;
|
||
|
}
|
||
|
this->submeshes.clear();
|
||
|
|
||
|
for (std::vector<Material*>::iterator iter = this->materials.begin();
|
||
|
iter != this->materials.end(); ++iter)
|
||
|
{
|
||
|
delete *iter;
|
||
|
}
|
||
|
this->materials.clear();
|
||
|
|
||
|
delete this->skeleton;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void Mesh::SetPath(const std::string &_path)
|
||
|
{
|
||
|
this->path = _path;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
std::string Mesh::GetPath() const
|
||
|
{
|
||
|
return this->path;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void Mesh::SetName(const std::string &_n)
|
||
|
{
|
||
|
this->name = _n;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
std::string Mesh::GetName() const
|
||
|
{
|
||
|
return this->name;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
ignition::math::Vector3d Mesh::Max() const
|
||
|
{
|
||
|
ignition::math::Vector3d max;
|
||
|
std::vector<SubMesh*>::const_iterator iter;
|
||
|
|
||
|
max.X(-FLT_MAX);
|
||
|
max.Y(-FLT_MAX);
|
||
|
max.Z(-FLT_MAX);
|
||
|
|
||
|
for (iter = this->submeshes.begin(); iter != this->submeshes.end(); ++iter)
|
||
|
{
|
||
|
if ((*iter)->GetVertexCount() <= 2)
|
||
|
continue;
|
||
|
|
||
|
ignition::math::Vector3d smax = (*iter)->Max();
|
||
|
max.X(std::max(max.X(), smax.X()));
|
||
|
max.Y(std::max(max.Y(), smax.Y()));
|
||
|
max.Z(std::max(max.Z(), smax.Z()));
|
||
|
}
|
||
|
|
||
|
return max;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
ignition::math::Vector3d Mesh::Min() const
|
||
|
{
|
||
|
ignition::math::Vector3d min;
|
||
|
std::vector<SubMesh *>::const_iterator iter;
|
||
|
|
||
|
min.X(FLT_MAX);
|
||
|
min.Y(FLT_MAX);
|
||
|
min.Z(FLT_MAX);
|
||
|
|
||
|
for (iter = this->submeshes.begin(); iter != this->submeshes.end(); ++iter)
|
||
|
{
|
||
|
if ((*iter)->GetVertexCount() <= 2)
|
||
|
continue;
|
||
|
|
||
|
ignition::math::Vector3d smin = (*iter)->Min();
|
||
|
min.X(std::min(min.X(), smin.X()));
|
||
|
min.Y(std::min(min.Y(), smin.Y()));
|
||
|
min.Z(std::min(min.Z(), smin.Z()));
|
||
|
}
|
||
|
|
||
|
return min;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
unsigned int Mesh::GetVertexCount() const
|
||
|
{
|
||
|
unsigned int sum = 0;
|
||
|
std::vector<SubMesh *>::const_iterator iter;
|
||
|
|
||
|
for (iter = this->submeshes.begin(); iter != this->submeshes.end(); ++iter)
|
||
|
{
|
||
|
if ((*iter)->GetVertexCount() <= 2)
|
||
|
continue;
|
||
|
sum += (*iter)->GetVertexCount();
|
||
|
}
|
||
|
|
||
|
return sum;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
unsigned int Mesh::GetNormalCount() const
|
||
|
{
|
||
|
unsigned int sum = 0;
|
||
|
std::vector<SubMesh *>::const_iterator iter;
|
||
|
|
||
|
for (iter = this->submeshes.begin(); iter != this->submeshes.end(); ++iter)
|
||
|
{
|
||
|
if ((*iter)->GetVertexCount() <= 2)
|
||
|
continue;
|
||
|
sum += (*iter)->GetNormalCount();
|
||
|
}
|
||
|
|
||
|
return sum;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
unsigned int Mesh::GetIndexCount() const
|
||
|
{
|
||
|
unsigned int sum = 0;
|
||
|
std::vector<SubMesh *>::const_iterator iter;
|
||
|
|
||
|
for (iter = this->submeshes.begin(); iter != this->submeshes.end(); ++iter)
|
||
|
{
|
||
|
if ((*iter)->GetVertexCount() <= 2)
|
||
|
continue;
|
||
|
sum += (*iter)->GetIndexCount();
|
||
|
}
|
||
|
|
||
|
return sum;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
unsigned int Mesh::GetTexCoordCount() const
|
||
|
{
|
||
|
unsigned int sum = 0;
|
||
|
std::vector<SubMesh *>::const_iterator iter;
|
||
|
|
||
|
for (iter = this->submeshes.begin(); iter != this->submeshes.end(); ++iter)
|
||
|
{
|
||
|
if ((*iter)->GetVertexCount() <= 2)
|
||
|
continue;
|
||
|
sum += (*iter)->GetTexCoordCount();
|
||
|
}
|
||
|
|
||
|
return sum;
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void Mesh::AddSubMesh(SubMesh *_sub)
|
||
|
{
|
||
|
this->submeshes.push_back(_sub);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
unsigned int Mesh::GetSubMeshCount() const
|
||
|
{
|
||
|
return this->submeshes.size();
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
const SubMesh *Mesh::GetSubMesh(unsigned int i) const
|
||
|
{
|
||
|
if (i < this->submeshes.size())
|
||
|
return this->submeshes[i];
|
||
|
else
|
||
|
gzthrow("Invalid index: " << i << " >= " << this->submeshes.size() << "\n");
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
const SubMesh *Mesh::GetSubMesh(const std::string &_name) const
|
||
|
{
|
||
|
// Find the submesh with the provided name.
|
||
|
for (std::vector<SubMesh *>::const_iterator iter = this->submeshes.begin();
|
||
|
iter != this->submeshes.end(); ++iter)
|
||
|
{
|
||
|
if ((*iter)->GetName() == _name)
|
||
|
return *iter;
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
int Mesh::AddMaterial(Material *_mat)
|
||
|
{
|
||
|
int result = -1;
|
||
|
|
||
|
if (_mat)
|
||
|
{
|
||
|
this->materials.push_back(_mat);
|
||
|
result = this->materials.size()-1;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
unsigned int Mesh::GetMaterialCount() const
|
||
|
{
|
||
|
return this->materials.size();
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
const Material *Mesh::GetMaterial(int index) const
|
||
|
{
|
||
|
if (index >= 0 && index < static_cast<int>(this->materials.size()))
|
||
|
return this->materials[index];
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
int Mesh::GetMaterialIndex(const Material *_mat) const
|
||
|
{
|
||
|
for (unsigned int i = 0; i < this->materials.size(); ++i)
|
||
|
{
|
||
|
if (this->materials[i] == _mat)
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void Mesh::FillArrays(float **_vertArr, int **_indArr) const
|
||
|
{
|
||
|
std::vector<SubMesh *>::const_iterator iter;
|
||
|
|
||
|
unsigned int vertCount = 0;
|
||
|
unsigned int indCount = 0;
|
||
|
|
||
|
for (iter = this->submeshes.begin(); iter != this->submeshes.end(); ++iter)
|
||
|
{
|
||
|
if ((*iter)->GetVertexCount() <= 2)
|
||
|
continue;
|
||
|
vertCount += (*iter)->GetVertexCount();
|
||
|
indCount += (*iter)->GetIndexCount();
|
||
|
}
|
||
|
|
||
|
if (*_vertArr)
|
||
|
delete [] *_vertArr;
|
||
|
|
||
|
if (*_indArr)
|
||
|
delete [] *_indArr;
|
||
|
|
||
|
*_vertArr = new float[vertCount * 3];
|
||
|
*_indArr = new int[indCount];
|
||
|
|
||
|
float *vPtr = *_vertArr;
|
||
|
unsigned int index = 0;
|
||
|
unsigned int offset = 0;
|
||
|
|
||
|
for (iter = this->submeshes.begin(); iter != this->submeshes.end(); ++iter)
|
||
|
{
|
||
|
if ((*iter)->GetVertexCount() <= 2)
|
||
|
continue;
|
||
|
|
||
|
float *vertTmp = NULL;
|
||
|
int *indTmp = NULL;
|
||
|
(*iter)->FillArrays(&vertTmp, &indTmp);
|
||
|
|
||
|
memcpy(vPtr, vertTmp, sizeof(vertTmp[0])*(*iter)->GetVertexCount()*3);
|
||
|
|
||
|
for (unsigned int i = 0; i < (*iter)->GetIndexCount(); ++i)
|
||
|
{
|
||
|
(*_indArr)[index++] = (*iter)->GetIndex(i) + offset;
|
||
|
}
|
||
|
|
||
|
offset = offset + (*iter)->GetMaxIndex() + 1;
|
||
|
|
||
|
vPtr += (*iter)->GetVertexCount()*3;
|
||
|
|
||
|
delete [] vertTmp;
|
||
|
delete [] indTmp;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void Mesh::RecalculateNormals()
|
||
|
{
|
||
|
std::vector<SubMesh*>::iterator iter;
|
||
|
for (iter = this->submeshes.begin(); iter != this->submeshes.end(); ++iter)
|
||
|
(*iter)->RecalculateNormals();
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void Mesh::SetSkeleton(Skeleton* _skel)
|
||
|
{
|
||
|
this->skeleton = _skel;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
Skeleton* Mesh::GetSkeleton() const
|
||
|
{
|
||
|
return this->skeleton;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
bool Mesh::HasSkeleton() const
|
||
|
{
|
||
|
if (this->skeleton)
|
||
|
return true;
|
||
|
else
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void Mesh::Scale(double _factor)
|
||
|
{
|
||
|
std::vector<SubMesh*>::iterator iter;
|
||
|
for (iter = this->submeshes.begin(); iter != this->submeshes.end(); ++iter)
|
||
|
(*iter)->Scale(_factor);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void Mesh::SetScale(const ignition::math::Vector3d &_factor)
|
||
|
{
|
||
|
std::vector<SubMesh*>::iterator iter;
|
||
|
for (iter = this->submeshes.begin(); iter != this->submeshes.end(); ++iter)
|
||
|
(*iter)->SetScale(_factor);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void Mesh::GenSphericalTexCoord(const ignition::math::Vector3d &_center)
|
||
|
{
|
||
|
std::vector<SubMesh*>::iterator siter;
|
||
|
for (siter = this->submeshes.begin(); siter != this->submeshes.end(); ++siter)
|
||
|
(*siter)->GenSphericalTexCoord(_center);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void Mesh::Center(const ignition::math::Vector3d &_center)
|
||
|
{
|
||
|
ignition::math::Vector3d min, max, half;
|
||
|
min = this->Min();
|
||
|
max = this->Max();
|
||
|
half = (max - min) * 0.5;
|
||
|
|
||
|
this->Translate(_center - (min + half));
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void Mesh::Translate(const ignition::math::Vector3d &_vec)
|
||
|
{
|
||
|
std::vector<SubMesh*>::iterator iter;
|
||
|
|
||
|
for (iter = this->submeshes.begin(); iter != this->submeshes.end(); ++iter)
|
||
|
{
|
||
|
if ((*iter)->GetVertexCount() <= 2)
|
||
|
continue;
|
||
|
|
||
|
(*iter)->Translate(_vec);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
//////////////////////////////////////////////////
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
SubMesh::SubMesh()
|
||
|
{
|
||
|
this->materialIndex = -1;
|
||
|
this->primitiveType = TRIANGLES;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
SubMesh::SubMesh(const SubMesh *_mesh)
|
||
|
{
|
||
|
if (!_mesh)
|
||
|
{
|
||
|
gzerr << "Submesh is NULL." << std::endl;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
this->name = _mesh->name;
|
||
|
this->materialIndex = _mesh->materialIndex;
|
||
|
this->primitiveType = _mesh->primitiveType;
|
||
|
|
||
|
std::copy(_mesh->nodeAssignments.begin(), _mesh->nodeAssignments.end(),
|
||
|
std::back_inserter(this->nodeAssignments));
|
||
|
|
||
|
std::copy(_mesh->indices.begin(), _mesh->indices.end(),
|
||
|
std::back_inserter(this->indices));
|
||
|
std::copy(_mesh->normals.begin(), _mesh->normals.end(),
|
||
|
std::back_inserter(this->normals));
|
||
|
std::copy(_mesh->texCoords.begin(), _mesh->texCoords.end(),
|
||
|
std::back_inserter(this->texCoords));
|
||
|
std::copy(_mesh->vertices.begin(), _mesh->vertices.end(),
|
||
|
std::back_inserter(this->vertices));
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
SubMesh::~SubMesh()
|
||
|
{
|
||
|
this->vertices.clear();
|
||
|
this->indices.clear();
|
||
|
this->nodeAssignments.clear();
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::SetPrimitiveType(PrimitiveType _type)
|
||
|
{
|
||
|
this->primitiveType = _type;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
SubMesh::PrimitiveType SubMesh::GetPrimitiveType() const
|
||
|
{
|
||
|
return this->primitiveType;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::CopyVertices(const std::vector<ignition::math::Vector3d> &_verts)
|
||
|
{
|
||
|
this->vertices.clear();
|
||
|
this->vertices.resize(_verts.size());
|
||
|
std::copy(_verts.begin(), _verts.end(), this->vertices.begin());
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::CopyNormals(const std::vector<ignition::math::Vector3d> &_norms)
|
||
|
{
|
||
|
this->normals.clear();
|
||
|
this->normals.resize(_norms.size());
|
||
|
for (unsigned int i = 0; i < _norms.size(); ++i)
|
||
|
{
|
||
|
this->normals[i] = _norms[i];
|
||
|
this->normals[i].Normalize();
|
||
|
if (ignition::math::equal(this->normals[i].Length(), 0.0))
|
||
|
{
|
||
|
this->normals[i].Set(0, 0, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::SetVertexCount(unsigned int _count)
|
||
|
{
|
||
|
this->vertices.resize(_count);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::SetIndexCount(unsigned int _count)
|
||
|
{
|
||
|
this->indices.resize(_count);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::SetNormalCount(unsigned int _count)
|
||
|
{
|
||
|
this->normals.resize(_count);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::SetTexCoordCount(unsigned int _count)
|
||
|
{
|
||
|
this->texCoords.resize(_count);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::AddIndex(unsigned int _i)
|
||
|
{
|
||
|
this->indices.push_back(_i);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::AddVertex(const ignition::math::Vector3d &_v)
|
||
|
{
|
||
|
this->vertices.push_back(_v);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::AddVertex(double _x, double _y, double _z)
|
||
|
{
|
||
|
this->AddVertex(ignition::math::Vector3d(_x, _y, _z));
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::AddNormal(const ignition::math::Vector3d &_n)
|
||
|
{
|
||
|
this->normals.push_back(_n);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::AddNormal(double _x, double _y, double _z)
|
||
|
{
|
||
|
this->AddNormal(ignition::math::Vector3d(_x, _y, _z));
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::AddTexCoord(double _u, double _v)
|
||
|
{
|
||
|
this->texCoords.push_back(ignition::math::Vector2d(_u, _v));
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::AddNodeAssignment(unsigned int _vertex, unsigned int _node,
|
||
|
float _weight)
|
||
|
{
|
||
|
NodeAssignment na;
|
||
|
na.vertexIndex = _vertex;
|
||
|
na.nodeIndex = _node;
|
||
|
na.weight = _weight;
|
||
|
|
||
|
this->nodeAssignments.push_back(na);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
ignition::math::Vector3d SubMesh::Vertex(unsigned int _i) const
|
||
|
{
|
||
|
if (_i >= this->vertices.size())
|
||
|
gzthrow("Index too large");
|
||
|
|
||
|
return this->vertices[_i];
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::SetVertex(unsigned int _i, const ignition::math::Vector3d &_v)
|
||
|
{
|
||
|
if (_i >= this->vertices.size())
|
||
|
gzthrow("Index too large");
|
||
|
|
||
|
this->vertices[_i] = _v;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
ignition::math::Vector3d SubMesh::Normal(unsigned int _i) const
|
||
|
{
|
||
|
if (_i >= this->normals.size())
|
||
|
gzthrow("Index too large");
|
||
|
|
||
|
return this->normals[_i];
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::SetNormal(unsigned int _i, const ignition::math::Vector3d &_n)
|
||
|
{
|
||
|
if (_i >= this->normals.size())
|
||
|
gzthrow("Index too large");
|
||
|
|
||
|
this->normals[_i] = _n;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
ignition::math::Vector2d SubMesh::TexCoord(unsigned int _i) const
|
||
|
{
|
||
|
if (_i >= this->texCoords.size())
|
||
|
gzthrow("Index too large");
|
||
|
|
||
|
return this->texCoords[_i];
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
NodeAssignment SubMesh::GetNodeAssignment(unsigned int _i) const
|
||
|
{
|
||
|
if (_i >= this->nodeAssignments.size())
|
||
|
gzthrow("Index too large");
|
||
|
|
||
|
return this->nodeAssignments[_i];
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::SetTexCoord(unsigned int _i, const ignition::math::Vector2d &_t)
|
||
|
{
|
||
|
if (_i >= this->texCoords.size())
|
||
|
gzthrow("Index too large");
|
||
|
|
||
|
this->texCoords[_i] = _t;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
unsigned int SubMesh::GetIndex(unsigned int _i) const
|
||
|
{
|
||
|
if (_i > this->indices.size())
|
||
|
gzthrow("Index too large");
|
||
|
|
||
|
return this->indices[_i];
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
ignition::math::Vector3d SubMesh::Max() const
|
||
|
{
|
||
|
ignition::math::Vector3d max;
|
||
|
std::vector<ignition::math::Vector3d>::const_iterator iter;
|
||
|
|
||
|
max.X(-FLT_MAX);
|
||
|
max.Y(-FLT_MAX);
|
||
|
max.Z(-FLT_MAX);
|
||
|
|
||
|
for (iter = this->vertices.begin(); iter != this->vertices.end(); ++iter)
|
||
|
{
|
||
|
max.X(std::max(max.X(), (*iter).X()));
|
||
|
max.Y(std::max(max.Y(), (*iter).Y()));
|
||
|
max.Z(std::max(max.Z(), (*iter).Z()));
|
||
|
}
|
||
|
|
||
|
return max;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
ignition::math::Vector3d SubMesh::Min() const
|
||
|
{
|
||
|
ignition::math::Vector3d min;
|
||
|
std::vector<ignition::math::Vector3d>::const_iterator iter;
|
||
|
|
||
|
min.X(FLT_MAX);
|
||
|
min.Y(FLT_MAX);
|
||
|
min.Z(FLT_MAX);
|
||
|
|
||
|
for (iter = this->vertices.begin(); iter != this->vertices.end(); ++iter)
|
||
|
{
|
||
|
min.X(std::min(min.X(), (*iter).X()));
|
||
|
min.Y(std::min(min.Y(), (*iter).Y()));
|
||
|
min.Z(std::min(min.Z(), (*iter).Z()));
|
||
|
}
|
||
|
|
||
|
return min;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
unsigned int SubMesh::GetVertexCount() const
|
||
|
{
|
||
|
return this->vertices.size();
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
unsigned int SubMesh::GetNormalCount() const
|
||
|
{
|
||
|
return this->normals.size();
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
unsigned int SubMesh::GetIndexCount() const
|
||
|
{
|
||
|
return this->indices.size();
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
unsigned int SubMesh::GetTexCoordCount() const
|
||
|
{
|
||
|
return this->texCoords.size();
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
unsigned int SubMesh::GetNodeAssignmentsCount() const
|
||
|
{
|
||
|
return this->nodeAssignments.size();
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
unsigned int SubMesh::GetMaxIndex() const
|
||
|
{
|
||
|
std::vector<unsigned int>::const_iterator maxIter;
|
||
|
maxIter = std::max_element(this->indices.begin(), this->indices.end());
|
||
|
|
||
|
if (maxIter != this->indices.end())
|
||
|
return *maxIter;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::SetMaterialIndex(unsigned int _index)
|
||
|
{
|
||
|
this->materialIndex = _index;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
unsigned int SubMesh::GetMaterialIndex() const
|
||
|
{
|
||
|
return this->materialIndex;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
bool SubMesh::HasVertex(const ignition::math::Vector3d &_v) const
|
||
|
{
|
||
|
std::vector< ignition::math::Vector3d >::const_iterator iter;
|
||
|
|
||
|
for (iter = this->vertices.begin(); iter != this->vertices.end(); ++iter)
|
||
|
if (_v.Equal(*iter))
|
||
|
return true;
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
unsigned int SubMesh::GetVertexIndex(const ignition::math::Vector3d &_v) const
|
||
|
{
|
||
|
std::vector< ignition::math::Vector3d >::const_iterator iter;
|
||
|
|
||
|
for (iter = this->vertices.begin(); iter != this->vertices.end(); ++iter)
|
||
|
if (_v.Equal(*iter))
|
||
|
return iter - this->vertices.begin();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::FillArrays(float **_vertArr, int **_indArr) const
|
||
|
{
|
||
|
if (this->vertices.empty() || this->indices.empty())
|
||
|
gzerr << "No vertices or indices\n";
|
||
|
|
||
|
std::vector<ignition::math::Vector3d>::const_iterator viter;
|
||
|
std::vector<unsigned int>::const_iterator iiter;
|
||
|
unsigned int i;
|
||
|
|
||
|
if (*_vertArr)
|
||
|
delete [] *_vertArr;
|
||
|
|
||
|
if (*_indArr)
|
||
|
delete [] *_indArr;
|
||
|
|
||
|
*_vertArr = new float[this->vertices.size() * 3];
|
||
|
*_indArr = new int[this->indices.size()];
|
||
|
|
||
|
for (viter = this->vertices.begin(), i = 0; viter != this->vertices.end();
|
||
|
++viter)
|
||
|
{
|
||
|
(*_vertArr)[i++] = static_cast<float>((*viter).X());
|
||
|
(*_vertArr)[i++] = static_cast<float>((*viter).Y());
|
||
|
(*_vertArr)[i++] = static_cast<float>((*viter).Z());
|
||
|
}
|
||
|
|
||
|
for (iiter = this->indices.begin(), i = 0;
|
||
|
iiter != this->indices.end(); ++iiter)
|
||
|
{
|
||
|
(*_indArr)[i++] = (*iiter);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::RecalculateNormals()
|
||
|
{
|
||
|
unsigned int i;
|
||
|
if (normals.size() < 3)
|
||
|
return;
|
||
|
|
||
|
// Reset all the normals
|
||
|
for (i = 0; i < this->normals.size(); ++i)
|
||
|
this->normals[i].Set(0, 0, 0);
|
||
|
|
||
|
if (this->normals.size() != this->vertices.size())
|
||
|
this->normals.resize(this->vertices.size());
|
||
|
|
||
|
// For each face, which is defined by three indices, calculate the normals
|
||
|
for (i = 0; i < this->indices.size(); i+= 3)
|
||
|
{
|
||
|
ignition::math::Vector3d v1 = this->vertices[this->indices[i]];
|
||
|
ignition::math::Vector3d v2 = this->vertices[this->indices[i+1]];
|
||
|
ignition::math::Vector3d v3 = this->vertices[this->indices[i+2]];
|
||
|
ignition::math::Vector3d n = ignition::math::Vector3d::Normal(v1, v2, v3);
|
||
|
|
||
|
for (unsigned int j = 0; j< this->vertices.size(); ++j)
|
||
|
{
|
||
|
if (this->vertices[j] == v1 ||
|
||
|
this->vertices[j] == v2 ||
|
||
|
this->vertices[j] == v3)
|
||
|
{
|
||
|
this->normals[j] += n;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Normalize the results
|
||
|
for (i = 0; i < this->normals.size(); ++i)
|
||
|
{
|
||
|
this->normals[i].Normalize();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void Mesh::GetAABB(ignition::math::Vector3d &_center,
|
||
|
ignition::math::Vector3d &_minXYZ,
|
||
|
ignition::math::Vector3d &_maxXYZ) const
|
||
|
{
|
||
|
// find aabb center
|
||
|
_minXYZ.X(1e15);
|
||
|
_maxXYZ.X(-1e15);
|
||
|
_minXYZ.Y(1e15);
|
||
|
_maxXYZ.Y(-1e15);
|
||
|
_minXYZ.Z(1e15);
|
||
|
_maxXYZ.Z(-1e15);
|
||
|
_center.X(0);
|
||
|
_center.Y(0);
|
||
|
_center.Z(0);
|
||
|
|
||
|
std::vector<SubMesh*>::const_iterator siter;
|
||
|
for (siter = this->submeshes.begin(); siter != this->submeshes.end(); ++siter)
|
||
|
{
|
||
|
ignition::math::Vector3d max = (*siter)->Max();
|
||
|
ignition::math::Vector3d min = (*siter)->Min();
|
||
|
|
||
|
_minXYZ.X(std::min(_minXYZ.X(), min.X()));
|
||
|
_maxXYZ.X(std::max(_maxXYZ.X(), max.X()));
|
||
|
_minXYZ.Y(std::min(_minXYZ.Y(), min.Y()));
|
||
|
_maxXYZ.Y(std::max(_maxXYZ.Y(), max.Y()));
|
||
|
_minXYZ.Z(std::min(_minXYZ.Z(), min.Z()));
|
||
|
_maxXYZ.Z(std::max(_maxXYZ.Z(), max.Z()));
|
||
|
}
|
||
|
_center.X(0.5 * (_minXYZ.X() + _maxXYZ.X()));
|
||
|
_center.Y(0.5 * (_minXYZ.Y() + _maxXYZ.Y()));
|
||
|
_center.Z(0.5 * (_minXYZ.Z() + _maxXYZ.Z()));
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::GenSphericalTexCoord(const ignition::math::Vector3d &_center)
|
||
|
{
|
||
|
std::vector<ignition::math::Vector3d>::const_iterator viter;
|
||
|
for (viter = this->vertices.begin(); viter != this->vertices.end(); ++viter)
|
||
|
{
|
||
|
// generate projected texture coordinates, projected from center
|
||
|
// get x, y, z for computing texture coordinate projections
|
||
|
double x = (*viter).X() - _center.X();
|
||
|
double y = (*viter).Y() - _center.Y();
|
||
|
double z = (*viter).Z() - _center.Z();
|
||
|
|
||
|
double r = std::max(0.000001, sqrt(x*x+y*y+z*z));
|
||
|
double s = std::min(1.0, std::max(-1.0, z/r));
|
||
|
double t = std::min(1.0, std::max(-1.0, y/r));
|
||
|
double u = acos(s) / M_PI;
|
||
|
double v = acos(t) / M_PI;
|
||
|
this->AddTexCoord(u, v);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::Scale(double _factor)
|
||
|
{
|
||
|
for (auto &vert : this->vertices)
|
||
|
vert *= _factor;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::SetScale(const ignition::math::Vector3d &_factor)
|
||
|
{
|
||
|
for (auto &vert : this->vertices)
|
||
|
vert *= _factor;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::Center(const ignition::math::Vector3d &_center)
|
||
|
{
|
||
|
ignition::math::Vector3d min, max, half;
|
||
|
min = this->Min();
|
||
|
max = this->Max();
|
||
|
half = (max - min) * 0.5;
|
||
|
|
||
|
this->Translate(_center - (min + half));
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::Translate(const ignition::math::Vector3d &_vec)
|
||
|
{
|
||
|
for (auto &vert : this->vertices)
|
||
|
vert += _vec;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
void SubMesh::SetName(const std::string &_n)
|
||
|
{
|
||
|
this->name = _n;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
std::string SubMesh::GetName() const
|
||
|
{
|
||
|
return this->name;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
NodeAssignment::NodeAssignment()
|
||
|
: vertexIndex(0), nodeIndex(0), weight(0.0)
|
||
|
{
|
||
|
}
|