diff options
Diffstat (limited to 'source/gameengine/Rasterizer/RAS_MeshObject.cpp')
-rw-r--r-- | source/gameengine/Rasterizer/RAS_MeshObject.cpp | 635 |
1 files changed, 635 insertions, 0 deletions
diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp new file mode 100644 index 00000000000..3c78b7cf991 --- /dev/null +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -0,0 +1,635 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "RAS_MeshObject.h" + +#include "RAS_IRasterizer.h" +#include "MT_MinMax.h" + +STR_String RAS_MeshObject::s_emptyname = ""; + + + +KX_ArrayOptimizer::~KX_ArrayOptimizer() +{ + int i = 0; + + for (vector<KX_VertexArray*>::iterator itv = m_VertexArrayCache1.begin(); + !(itv == m_VertexArrayCache1.end());itv++) + { + delete (*itv); + } + + for (vector<KX_IndexArray*>::iterator iti = m_IndexArrayCache1.begin(); + !(iti == m_IndexArrayCache1.end());iti++) + { + delete (*iti); + } + + m_TriangleArrayCount.clear(); + m_VertexArrayCache1.clear(); + m_IndexArrayCache1.clear(); + + +} + + + +RAS_MeshObject::RAS_MeshObject(int lightlayer) + : m_bModified(true), + m_lightlayer(lightlayer) +{ +} + + + +RAS_MeshObject::~RAS_MeshObject() +{ + for (vector<RAS_Polygon*>::iterator it=m_Polygons.begin();!(it==m_Polygons.end());it++) + { + delete (*it); + } + + ClearArrayData(); +} + + + +int RAS_MeshObject::GetLightLayer() +{ + return m_lightlayer; +} + + + +int RAS_MeshObject::NumMaterials() +{ + return m_materials.size(); +} + + + +const STR_String& RAS_MeshObject::GetMaterialName(int matid) +{ + if (m_materials.size() > 0 && (matid < m_materials.size())) + { + BucketMaterialSet::iterator it = m_materials.begin(); + + for (int i = 1; i < m_materials.size(); i++) + { + it++; + } + return (*it)->GetPolyMaterial()->GetMaterialName(); + } + + return s_emptyname; +} + + + +RAS_MaterialBucket* RAS_MeshObject::GetMaterialBucket(int matid) +{ + RAS_MaterialBucket* bucket = NULL; + + if (m_materials.size() > 0 && (matid < m_materials.size())) + { + BucketMaterialSet::iterator it = m_materials.begin(); + int i = matid; + while (i > 0) + { + i--; + it++; + } + bucket = *it; + } + + return bucket; +} + + + +int RAS_MeshObject::NumPolygons() +{ + return m_Polygons.size(); +} + + + +RAS_Polygon* RAS_MeshObject::GetPolygon(int num) +{ + return m_Polygons[num]; +} + + + +set<RAS_MaterialBucket*>::iterator RAS_MeshObject::GetFirstMaterial() +{ + return m_materials.begin(); +} + + + +set<RAS_MaterialBucket*>::iterator RAS_MeshObject::GetLastMaterial() +{ + return m_materials.end(); +} + + + +void RAS_MeshObject::SetName(STR_String name) +{ + m_name = name; +} + + + +const STR_String& RAS_MeshObject::GetName() +{ + return m_name; +} + + + +const STR_String& RAS_MeshObject::GetTextureName(int matid) +{ + if (m_materials.size() > 0 && (matid < m_materials.size())) + { + BucketMaterialSet::iterator it = m_materials.begin(); + for (int i = 1; i < m_materials.size(); i++) + { + it++; + } + + return (*it)->GetPolyMaterial()->GetTextureName(); + } + + return s_emptyname; +} + + + +void RAS_MeshObject::AddPolygon(RAS_Polygon* poly) +{ + m_Polygons.push_back(poly); +} + + + +void RAS_MeshObject::DebugColor(unsigned int abgr) +{ +/* + int numpolys = NumPolygons(); + for (int i=0;i<numpolys;i++) + { + RAS_Polygon* poly = m_polygons[i]; + for (int v=0;v<poly->VertexCount();v++) + { + RAS_TexVert* vtx = poly->GetVertex(v); + vtx->setDebugRGBA(abgr); + } + } + */ + + m_debugcolor = abgr; +} + + + +void RAS_MeshObject::SchedulePoly(const KX_VertexIndex& idx, + int numverts, + RAS_IPolyMaterial* mat) +{ + //int indexpos = m_IndexArrayCount[idx.m_vtxarray]; + int indexidx = 0; + //m_IndexArrayCount[idx.m_vtxarray] = indexpos + 3; + + KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); + ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[0]); + ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[1]); + ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[2]); + if (!mat->UsesTriangles()) //if (!m_bUseTriangles) + { + //m_IndexArrayCount[idx.m_vtxarray] = indexpos+4; + ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[3]); + } +} + + + +void RAS_MeshObject::ScheduleWireframePoly(const KX_VertexIndex& idx, + int numverts, + int edgecode, + RAS_IPolyMaterial* mat) +{ + //int indexpos = m_IndexArrayCount[idx.m_vtxarray]; + int edgetrace = 1<<(numverts-1); + bool drawedge = (edgecode & edgetrace)!=0; + edgetrace = 1; + int prevvert = idx.m_indexarray[numverts-1]; + KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); + + for (int v = 0; v < numverts; v++) + { + unsigned int curvert = idx.m_indexarray[v]; + if (drawedge) + { + ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(prevvert); + ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(curvert); + } + prevvert = curvert; + drawedge = (edgecode & edgetrace)!=0; + edgetrace*=2; + } + //m_IndexArrayCount[idx.m_vtxarray] = indexpos; +} + +int RAS_MeshObject::FindOrAddVertex(int vtxarray, + const MT_Point3& xyz, + const MT_Point2& uv, + const unsigned int rgbacolor, + const MT_Vector3& normal, + RAS_IPolyMaterial* mat, + int orgindex) +{ + short newnormal[3]; + + newnormal[0]=(short)((normal[0])*32767.0); + newnormal[1]=(short)((normal[1])*32767.0); + newnormal[2]=(short)((normal[2])*32767.0); + + KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]); + + int numverts = ao->m_VertexArrayCache1[vtxarray]->size();//m_VertexArrayCount[vtxarray]; + +#define KX_FIND_SHARED_VERTICES +#ifdef KX_FIND_SHARED_VERTICES + + std::vector<RAS_MatArrayIndex>::iterator it = m_xyz_index_to_vertex_index_mapping[orgindex].begin(); + int index=-1; + while (index < 0 && !(it == m_xyz_index_to_vertex_index_mapping[orgindex].end())) + { + if ((*it).m_arrayindex1 == ao->m_index1 && + ((*it).m_array == vtxarray) && + (RAS_IPolyMaterial*) (*it).m_matid == mat + ) + { + return (*it).m_index; + } + it++; + } + + if (index >= 0) + return index; +#endif // KX_FIND_SHARED_VERTICES + + // no vertex found, add one + ao->m_VertexArrayCache1[vtxarray]->push_back(RAS_TexVert (xyz,uv,rgbacolor,newnormal, 0)); + // printf("(%f,%f,%f) ",xyz[0],xyz[1],xyz[2]); + RAS_MatArrayIndex idx; + idx.m_arrayindex1 = ao->m_index1; + idx.m_array = vtxarray; + idx.m_index = numverts; + idx.m_matid = (int) mat; + m_xyz_index_to_vertex_index_mapping[orgindex].push_back(idx); + + return numverts; +} + + + +const vecVertexArray& RAS_MeshObject::GetVertexCache (RAS_IPolyMaterial* mat) +{ + KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]); + + return ao->m_VertexArrayCache1; +} + + + +int RAS_MeshObject::GetVertexArrayLength(RAS_IPolyMaterial* mat) +{ + int len = 0; + + const vecVertexArray & vertexvec = GetVertexCache(mat); + vector<KX_VertexArray*>::const_iterator it = vertexvec.begin(); + + for (; it != vertexvec.end(); it++) + { + len += (*it)->size(); + } + + return len; +} + + + +RAS_TexVert* RAS_MeshObject::GetVertex(int matid, + int index) +{ + RAS_TexVert* vertex = NULL; + + RAS_MaterialBucket* bucket = GetMaterialBucket(matid); + if (bucket) + { + RAS_IPolyMaterial* mat = bucket->GetPolyMaterial(); + if (mat) + { + const vecVertexArray & vertexvec = GetVertexCache(mat); + vector<KX_VertexArray*>::const_iterator it = vertexvec.begin(); + + for (int len = 0; it != vertexvec.end(); it++) + { + if (index < len + (*it)->size()) + { + vertex = &(*(*it))[index-len]; + break; + } + else + { + len += (*it)->size(); + } + } + } + } + + return vertex; +} + + + +const vecIndexArrays& RAS_MeshObject::GetIndexCache (RAS_IPolyMaterial* mat) +{ + KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]); + + return ao->m_IndexArrayCache1; +} + + + +KX_ArrayOptimizer* RAS_MeshObject::GetArrayOptimizer(RAS_IPolyMaterial* polymat) +{ + KX_ArrayOptimizer** aop = (m_matVertexArrayS[*polymat]); + + if (aop) + return *aop; + + int numelements = m_matVertexArrayS.size(); + m_sortedMaterials.push_back(polymat); + + KX_ArrayOptimizer* ao = new KX_ArrayOptimizer(numelements); + m_matVertexArrayS.insert(*polymat,ao); + + return ao; +} + + + +void RAS_MeshObject::Bucketize(double* oglmatrix, + void* clientobj, + bool useObjectColor, + const MT_Vector4& rgbavec) +{ + KX_MeshSlot ms; + ms.m_clientObj = clientobj; + ms.m_mesh = this; + ms.m_OpenGLMatrix = oglmatrix; + ms.m_bObjectColor = useObjectColor; + ms.m_RGBAcolor = rgbavec; + + int i=0; + for (BucketMaterialSet::iterator it = m_materials.begin();it!=m_materials.end();it++) + { + RAS_MaterialBucket* bucket = *it; + bucket->SchedulePolygons(0); + KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial()); + bucket->SetMeshSlot(ms); + } + +} + + + +void RAS_MeshObject::MarkVisible(double* oglmatrix, + void* clientobj, + bool visible, + bool useObjectColor, + const MT_Vector4& rgbavec) +{ + KX_MeshSlot ms; + ms.m_clientObj = clientobj; + ms.m_mesh = this; + ms.m_OpenGLMatrix = oglmatrix; + ms.m_RGBAcolor = rgbavec; + ms.m_bObjectColor= useObjectColor; + + for (BucketMaterialSet::iterator it = m_materials.begin();it!=m_materials.end();it++) + { + RAS_MaterialBucket* bucket = *it; + bucket->SchedulePolygons(0); + KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial()); + bucket->MarkVisibleMeshSlot(ms,visible,useObjectColor,rgbavec); + } +} + + + +void RAS_MeshObject::RemoveFromBuckets(double* oglmatrix, + void* clientobj) +{ + KX_MeshSlot ms; + ms.m_clientObj = clientobj; + ms.m_mesh = this; + ms.m_OpenGLMatrix = oglmatrix; + + for (BucketMaterialSet::iterator it = m_materials.begin();it!=m_materials.end();it++) + { + RAS_MaterialBucket* bucket = *it; + RAS_IPolyMaterial* polymat = bucket->GetPolyMaterial(); + bucket->SchedulePolygons(0); + //KX_ArrayOptimizer* oa = GetArrayOptimizer(polymat); + bucket->RemoveMeshSlot(ms); + } + +} + + + +/* + * RAS_MeshObject::GetVertex returns the vertex located somewhere in the vertexpool + * it is the clients responsibility to make sure the array and index are valid + */ +RAS_TexVert* RAS_MeshObject::GetVertex(short array, + short index, + RAS_IPolyMaterial* polymat) +{ + KX_ArrayOptimizer* ao = GetArrayOptimizer(polymat);//*(m_matVertexArrays[*polymat]); + return &((*(ao->m_VertexArrayCache1)[array])[index]); +} + + + +void RAS_MeshObject::ClearArrayData() +{ + for (int i=0;i<m_matVertexArrayS.size();i++) + { KX_ArrayOptimizer** ao = m_matVertexArrayS.at(i); + if (ao) + delete *ao; + } +} + + + +/** + * RAS_MeshObject::CreateNewVertices creates vertices within sorted pools of vertices that share same material +*/ +int RAS_MeshObject::FindVertexArray(int numverts, + RAS_IPolyMaterial* polymat) +{ + bool found=false; + int array=-1; + + KX_ArrayOptimizer* ao = GetArrayOptimizer(polymat); + + for (int i=0;i<ao->m_VertexArrayCache1.size();i++) + { + if ( (ao->m_TriangleArrayCount[i] + (numverts-2)) < BUCKET_MAX_TRIANGLES) + { + if((ao->m_VertexArrayCache1[i]->size()+numverts < BUCKET_MAX_INDICES)) + { + array = i; + ao->m_TriangleArrayCount[array]+=numverts-2; + break; + } + } + else + { + int i=0; + } + } + + if (array == -1) + { + array = ao->m_VertexArrayCache1.size(); + vector<RAS_TexVert>* va = new vector<RAS_TexVert>; + ao->m_VertexArrayCache1.push_back(va); + KX_IndexArray *ia = new KX_IndexArray(); + ao->m_IndexArrayCache1.push_back(ia); + ao->m_TriangleArrayCount.push_back(numverts-2); + } + + return array; +} + + + + +//void RAS_MeshObject::Transform(const MT_Transform& trans) +//{ + //m_trans.translate(MT_Vector3(0,0,1));//.operator *=(trans); + +// for (int i=0;i<m_Polygons.size();i++) +// { +// m_Polygons[i]->Transform(trans); +// } +//} + + +/* +void RAS_MeshObject::RelativeTransform(const MT_Vector3& vec) +{ + for (int i=0;i<m_Polygons.size();i++) + { + m_Polygons[i]->RelativeTransform(vec); + } +} +*/ + + + +void RAS_MeshObject::UpdateMaterialList() +{ + m_materials.clear(); + int numpolys = m_Polygons.size(); + // for all polygons, find out which material they use, and add it to the set of materials + for (int i=0;i<numpolys;i++) + { + m_materials.insert(m_Polygons[i]->GetMaterial()); + } + int nummaterials = m_materials.size(); + +} + + + +void RAS_MeshObject::SchedulePolygons(int drawingmode,RAS_IRasterizer* rasty) +{ + int nummaterials = m_materials.size(); + int i; + + if (m_bModified) + { + for (BucketMaterialSet::iterator it = m_materials.begin();it!=m_materials.end();it++) + { + RAS_MaterialBucket* bucket = *it; + + bucket->SchedulePolygons(drawingmode); + } + + int numpolys = m_Polygons.size(); + + if ((rasty->GetDrawingMode() > RAS_IRasterizer::KX_BOUNDINGBOX) && + (rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID)) + { + for (i=0;i<numpolys;i++) + { + RAS_Polygon* poly = m_Polygons[i]; + if (poly->IsVisible()) + ScheduleWireframePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetEdgeCode() + ,poly->GetMaterial()->GetPolyMaterial()); + + } + } + else + { + for (i=0;i<numpolys;i++) + { + RAS_Polygon* poly = m_Polygons[i]; + if (poly->IsVisible()) + { + SchedulePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetMaterial()->GetPolyMaterial()); + } + } + } + + m_bModified = false; + } + // } +} |