diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2008-11-13 00:16:53 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2008-11-13 00:16:53 +0300 |
commit | bdfe7d89e2f1292644577972c716931b4ce3c6c3 (patch) | |
tree | d00eb50b749cb001e2b08272c91791e66740b05d /source/gameengine/Rasterizer/RAS_MeshObject.cpp | |
parent | 78a1c27c4a6abe0ed31ca93ad21910f3df04da56 (diff) | |
parent | 7e4db234cee71ead34ee81a12e27da4bd548eb4b (diff) |
Merge of trunk into blender 2.5:
svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r12987:17416
Issues:
* GHOST/X11 had conflicting changes. Some code was added in 2.5, which was
later added in trunk also, but reverted partially, specifically revision
16683. I have left out this reversion in the 2.5 branch since I think it is
needed there.
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16683
* Scons had various conflicting changes, I decided to go with trunk version
for everything except priorities and some library renaming.
* In creator.c, there were various fixes and fixes for fixes related to the -w
-W and -p options. In 2.5 -w and -W is not coded yet, and -p is done
differently. Since this is changed so much, and I don't think those fixes
would be needed in 2.5, I've left them out.
* Also in creator.c: there was code for a python bugfix where the screen was not
initialized when running with -P. The code that initializes the screen there
I had to disable, that can't work in 2.5 anymore but left it commented as a
reminder.
Further I had to disable some new function calls. using src/ and python/, as
was done already in this branch, disabled function calls:
* bpath.c: error reporting
* BME_conversions.c: editmesh conversion functions.
* SHD_dynamic: disabled almost completely, there is no python/.
* KX_PythonInit.cpp and Ketsji/ build files: Mathutils is not there, disabled.
* text.c: clipboard copy call.
* object.c: OB_SUPPORT_MATERIAL.
* DerivedMesh.c and subsurf_ccg, stipple_quarttone.
Still to be done:
* Go over files and functions that were moved to a different location but could
still use changes that were done in trunk.
Diffstat (limited to 'source/gameengine/Rasterizer/RAS_MeshObject.cpp')
-rw-r--r-- | source/gameengine/Rasterizer/RAS_MeshObject.cpp | 761 |
1 files changed, 287 insertions, 474 deletions
diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index e441908532f..a907994bf57 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -26,70 +26,91 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - #include "RAS_MeshObject.h" #include "RAS_IRasterizer.h" #include "MT_MinMax.h" #include "MT_Point3.h" +#include <algorithm> -STR_String RAS_MeshObject::s_emptyname = ""; - - +/* polygon sorting */ -KX_ArrayOptimizer::~KX_ArrayOptimizer() +struct RAS_MeshObject::polygonSlot { - for (vector<KX_VertexArray*>::iterator itv = m_VertexArrayCache1.begin(); - !(itv == m_VertexArrayCache1.end());++itv) - { - delete (*itv); - } + float m_z; + int m_index[4]; + + polygonSlot() {} - for (vector<KX_IndexArray*>::iterator iti = m_IndexArrayCache1.begin(); - !(iti == m_IndexArrayCache1.end());++iti) + /* pnorm is the normal from the plane equation that the distance from is + * used to sort again. */ + void get(const RAS_TexVert *vertexarray, const unsigned short *indexarray, + int offset, int nvert, const MT_Vector3& pnorm) { - delete (*iti); - } - - m_TriangleArrayCount.clear(); - m_VertexArrayCache1.clear(); - m_IndexArrayCache1.clear(); + MT_Vector3 center(0, 0, 0); + int i; + for(i=0; i<nvert; i++) { + m_index[i] = indexarray[offset+i]; + center += vertexarray[m_index[i]].getXYZ(); + } -} + /* note we don't divide center by the number of vertices, since all + * polygons have the same number of vertices, and that we leave out + * the 4-th component of the plane equation since it is constant. */ + m_z = MT_dot(pnorm, center); + } + void set(unsigned short *indexarray, int offset, int nvert) + { + int i; + for(i=0; i<nvert; i++) + indexarray[offset+i] = m_index[i]; + } +}; + +struct RAS_MeshObject::backtofront +{ + bool operator()(const polygonSlot &a, const polygonSlot &b) const + { + return a.m_z < b.m_z; + } +}; -RAS_MeshObject::RAS_MeshObject(int lightlayer) - : m_bModified(true), - m_lightlayer(lightlayer), - m_zsort(false), - m_MeshMod(true), - m_class(0) +struct RAS_MeshObject::fronttoback { -} + bool operator()(const polygonSlot &a, const polygonSlot &b) const + { + return a.m_z > b.m_z; + } +}; +/* mesh object */ -bool RAS_MeshObject::MeshModified() +STR_String RAS_MeshObject::s_emptyname = ""; + +RAS_MeshObject::RAS_MeshObject(Mesh* mesh, int lightlayer) + : m_lightlayer(lightlayer), + m_bModified(true), + m_bMeshModified(true), + m_mesh(mesh), + m_bDeformed(false) { - return m_MeshMod; } - RAS_MeshObject::~RAS_MeshObject() { - for (vector<RAS_Polygon*>::iterator it=m_Polygons.begin();!(it==m_Polygons.end());it++) - { - delete (*it); - } + vector<RAS_Polygon*>::iterator it; - ClearArrayData(); + for(it=m_Polygons.begin(); it!=m_Polygons.end(); it++) + delete (*it); } - +bool RAS_MeshObject::MeshModified() +{ + return m_bMeshModified; +} unsigned int RAS_MeshObject::GetLightLayer() { @@ -105,18 +126,21 @@ int RAS_MeshObject::NumMaterials() const STR_String& RAS_MeshObject::GetMaterialName(unsigned int matid) { - RAS_MaterialBucket* bucket = GetMaterialBucket(matid); + RAS_MeshMaterial* mmat = GetMeshMaterial(matid); + + if(mmat) + return mmat->m_bucket->GetPolyMaterial()->GetMaterialName(); - return bucket?bucket->GetPolyMaterial()->GetMaterialName():s_emptyname; + return s_emptyname; } -RAS_MaterialBucket* RAS_MeshObject::GetMaterialBucket(unsigned int matid) +RAS_MeshMaterial* RAS_MeshObject::GetMeshMaterial(unsigned int matid) { if (m_materials.size() > 0 && (matid < m_materials.size())) { - RAS_MaterialBucket::Set::const_iterator it = m_materials.begin(); + list<RAS_MeshMaterial>::iterator it = m_materials.begin(); while (matid--) ++it; - return *it; + return &*it; } return NULL; @@ -131,21 +155,24 @@ int RAS_MeshObject::NumPolygons() -RAS_Polygon* RAS_MeshObject::GetPolygon(int num) +RAS_Polygon* RAS_MeshObject::GetPolygon(int num) const { return m_Polygons[num]; } -RAS_MaterialBucket::Set::iterator RAS_MeshObject::GetFirstMaterial() + + list<RAS_MeshMaterial>::iterator GetFirstMaterial(); + list<RAS_MeshMaterial>::iterator GetLastMaterial(); +list<RAS_MeshMaterial>::iterator RAS_MeshObject::GetFirstMaterial() { return m_materials.begin(); } -RAS_MaterialBucket::Set::iterator RAS_MeshObject::GetLastMaterial() +list<RAS_MeshMaterial>::iterator RAS_MeshObject::GetLastMaterial() { return m_materials.end(); } @@ -168,355 +195,238 @@ const STR_String& RAS_MeshObject::GetName() const STR_String& RAS_MeshObject::GetTextureName(unsigned int matid) { - RAS_MaterialBucket* bucket = GetMaterialBucket(matid); + RAS_MeshMaterial* mmat = GetMeshMaterial(matid); - return bucket?bucket->GetPolyMaterial()->GetTextureName():s_emptyname; + if(mmat) + return mmat->m_bucket->GetPolyMaterial()->GetTextureName(); + + return s_emptyname; } +RAS_MeshMaterial *RAS_MeshObject::GetMeshMaterial(RAS_IPolyMaterial *mat) +{ + list<RAS_MeshMaterial>::iterator mit; + /* find a mesh material */ + for(mit = m_materials.begin(); mit != m_materials.end(); mit++) + if(mit->m_bucket->GetPolyMaterial() == mat) + return &*mit; -void RAS_MeshObject::AddPolygon(RAS_Polygon* poly) -{ - m_Polygons.push_back(poly); + return NULL; } +RAS_Polygon* RAS_MeshObject::AddPolygon(RAS_MaterialBucket *bucket, int numverts) +{ + RAS_MeshMaterial *mmat; + RAS_Polygon *poly; + RAS_MeshSlot *slot; + + /* find a mesh material */ + mmat = GetMeshMaterial(bucket->GetPolyMaterial()); + /* none found, create a new one */ + if(!mmat) { + RAS_MeshMaterial meshmat; + meshmat.m_bucket = bucket; + meshmat.m_baseslot = meshmat.m_bucket->AddMesh(numverts); + m_materials.push_back(meshmat); + mmat = &m_materials.back(); + } + + /* add it to the bucket, this also adds new display arrays */ + slot = mmat->m_baseslot; + slot->AddPolygon(numverts); + + /* create a new polygon */ + RAS_DisplayArray *darray = slot->CurrentDisplayArray(); + poly = new RAS_Polygon(bucket, darray, numverts); + m_Polygons.push_back(poly); + + return poly; +} void RAS_MeshObject::DebugColor(unsigned int abgr) { -/* - int numpolys = NumPolygons(); - for (int i=0;i<numpolys;i++) - { + /*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); - } + RAS_TexVert* vtx = poly->GetVertex(v)->setDebugRGBA(abgr); } */ - m_debugcolor = abgr; + /* m_debugcolor = abgr; */ } - - -void RAS_MeshObject::SchedulePoly(const KX_VertexIndex& idx, - int numverts, - RAS_IPolyMaterial* mat) +void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba) { - //int indexpos = m_IndexArrayCount[idx.m_vtxarray]; - //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]); - } -} - + RAS_MeshMaterial *mmat = GetMeshMaterial(mat); + RAS_MeshSlot *slot = mmat->m_baseslot; + RAS_MeshSlot::iterator it; + size_t i; - -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; + for(slot->begin(it); !slot->end(it); slot->next(it)) + for(i=it.startvertex; i<it.endvertex; i++) + it.vertex[i].SetRGBA(rgba); } -int RAS_MeshObject::FindOrAddVertex(int vtxarray, - const MT_Point3& xyz, - const MT_Point2& uv, - const MT_Point2& uv2, - const MT_Vector4& tangent, - const unsigned int rgbacolor, - const MT_Vector3& normal, - RAS_IPolyMaterial* mat, - int orgindex) +void RAS_MeshObject::AddVertex(RAS_Polygon *poly, int i, + const MT_Point3& xyz, + const MT_Point2& uv, + const MT_Point2& uv2, + const MT_Vector4& tangent, + const unsigned int rgba, + const MT_Vector3& normal, + bool flat, + int origindex) { - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]); - - int numverts = ao->m_VertexArrayCache1[vtxarray]->size();//m_VertexArrayCount[vtxarray]; - RAS_TexVert newvert(xyz,uv,uv2,tangent,rgbacolor,normal, 0); -#define KX_FIND_SHARED_VERTICES -#ifdef KX_FIND_SHARED_VERTICES + RAS_TexVert texvert(xyz, uv, uv2, tangent, rgba, normal, flat, origindex); + RAS_MeshMaterial *mmat; + RAS_DisplayArray *darray; + RAS_MeshSlot *slot; + int offset; - for (std::vector<RAS_MatArrayIndex>::iterator it = m_xyz_index_to_vertex_index_mapping[orgindex].begin(); - it != m_xyz_index_to_vertex_index_mapping[orgindex].end(); - it++) - { - if ((*it).m_arrayindex1 == ao->m_index1 && - (*it).m_array == vtxarray && - *(*it).m_matid == *mat && - (*ao->m_VertexArrayCache1[vtxarray])[(*it).m_index].closeTo(&newvert) - ) + mmat = GetMeshMaterial(poly->GetMaterial()->GetPolyMaterial()); + slot = mmat->m_baseslot; + darray = slot->CurrentDisplayArray(); + + if(!flat) { + /* find vertices shared between faces, with the restriction + * that they exist in the same display array, and have the + * same uv coordinate etc */ + vector<SharedVertex>& sharedmap = m_sharedvertex_map[origindex]; + vector<SharedVertex>::iterator it; + + for(it = sharedmap.begin(); it != sharedmap.end(); it++) { - return (*it).m_index; + if(it->m_darray != darray) + continue; + if(!it->m_darray->m_vertex[it->m_offset].closeTo(&texvert)) + continue; + + /* found one, add it and we're done */ + if(poly->IsVisible()) + slot->AddPolygonVertex(it->m_offset); + poly->SetVertexOffset(i, it->m_offset); + return; } } -#endif // KX_FIND_SHARED_VERTICES - - // no vertex found, add one - ao->m_VertexArrayCache1[vtxarray]->push_back(newvert); - // 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 = 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; + /* no shared vertex found, add a new one */ + offset = slot->AddVertex(texvert); + if(poly->IsVisible()) + slot->AddPolygonVertex(offset); + poly->SetVertexOffset(i, offset); + + if(!flat) { + SharedVertex shared; + shared.m_darray = darray; + shared.m_offset = offset; + m_sharedvertex_map[origindex].push_back(shared); + } } - - -int RAS_MeshObject::GetVertexArrayLength(RAS_IPolyMaterial* mat) +int RAS_MeshObject::NumVertices(RAS_IPolyMaterial* mat) { - int len = 0; + RAS_MeshMaterial *mmat; + RAS_MeshSlot *slot; + RAS_MeshSlot::iterator it; + size_t len = 0; - const vecVertexArray & vertexvec = GetVertexCache(mat); - vector<KX_VertexArray*>::const_iterator it = vertexvec.begin(); + mmat = GetMeshMaterial(mat); + slot = mmat->m_baseslot; + for(slot->begin(it); !slot->end(it); slot->next(it)) + len += it.endvertex - it.startvertex; - for (; it != vertexvec.end(); ++it) - { - len += (*it)->size(); - } - return len; } - RAS_TexVert* RAS_MeshObject::GetVertex(unsigned int matid, unsigned 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 (unsigned int len = 0; it != vertexvec.end(); ++it) - { - if (index < len + (*it)->size()) - { - vertex = &(*(*it))[index-len]; - break; - } - else - { - len += (*it)->size(); - } - } - } - } - - return vertex; -} - - + RAS_MeshMaterial *mmat; + RAS_MeshSlot *slot; + RAS_MeshSlot::iterator it; + size_t len; -const vecIndexArrays& RAS_MeshObject::GetIndexCache (RAS_IPolyMaterial* mat) -{ - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]); - - return ao->m_IndexArrayCache1; -} + mmat = GetMeshMaterial(matid); - - -KX_ArrayOptimizer* RAS_MeshObject::GetArrayOptimizer(RAS_IPolyMaterial* polymat) -{ - KX_ArrayOptimizer** aop = (m_matVertexArrayS[*polymat]); - - if (aop) - return *aop; + if(!mmat) + return NULL; - int numelements = m_matVertexArrayS.size(); - m_sortedMaterials.push_back(polymat); - - KX_ArrayOptimizer* ao = new KX_ArrayOptimizer(numelements); - m_matVertexArrayS.insert(*polymat,ao); + slot = mmat->m_baseslot; + len = 0; + for(slot->begin(it); !slot->end(it); slot->next(it)) { + if(index >= len + it.endvertex - it.startvertex) + len += it.endvertex - it.startvertex; + else + return &it.vertex[index - len]; + } - return ao; + return NULL; } - - -void RAS_MeshObject::Bucketize(double* oglmatrix, - void* clientobj, - bool useObjectColor, - const MT_Vector4& rgbavec) +void RAS_MeshObject::AddMeshUser(void *clientobj) { - KX_MeshSlot ms; - ms.m_clientObj = clientobj; - ms.m_mesh = this; - ms.m_OpenGLMatrix = oglmatrix; - ms.m_bObjectColor = useObjectColor; - ms.m_RGBAcolor = rgbavec; - - for (RAS_MaterialBucket::Set::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); - } + list<RAS_MeshMaterial>::iterator it; -} - - - -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 (RAS_MaterialBucket::Set::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); + for(it = m_materials.begin();it!=m_materials.end();++it) { + /* always copy from the base slot, which is never removed + * since new objects can be created with the same mesh data */ + RAS_MeshSlot *ms = it->m_bucket->CopyMesh(it->m_baseslot); + ms->m_clientObj = clientobj; + it->m_slots.insert(clientobj, ms); } } - -void RAS_MeshObject::RemoveFromBuckets(double* oglmatrix, - void* clientobj) +void RAS_MeshObject::UpdateBuckets(void* clientobj, + double* oglmatrix, + bool useObjectColor, + const MT_Vector4& rgbavec, + bool visible, + bool culled) { - KX_MeshSlot ms; - ms.m_clientObj = clientobj; - ms.m_mesh = this; - ms.m_OpenGLMatrix = oglmatrix; - - for (RAS_MaterialBucket::Set::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); - } - -} + list<RAS_MeshMaterial>::iterator it; + for(it = m_materials.begin();it!=m_materials.end();++it) { + RAS_MeshSlot **msp = it->m_slots[clientobj]; + if(!msp) + continue; -/* - * 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, - unsigned int index, - RAS_IPolyMaterial* polymat) -{ - KX_ArrayOptimizer* ao = GetArrayOptimizer(polymat);//*(m_matVertexArrays[*polymat]); - return &((*(ao->m_VertexArrayCache1)[array])[index]); -} + RAS_MeshSlot *ms = *msp; + ms->m_mesh = this; + ms->m_OpenGLMatrix = oglmatrix; + ms->m_bObjectColor = useObjectColor; + ms->m_RGBAcolor = rgbavec; + ms->m_bVisible = visible; + ms->m_bCulled = culled || !visible; - -void RAS_MeshObject::ClearArrayData() -{ - for (int i=0;i<m_matVertexArrayS.size();i++) - { - KX_ArrayOptimizer** ao = m_matVertexArrayS.at(i); - if (ao) - delete *ao; + /* split if necessary */ + ms->Split(); } } - - -/** - * RAS_MeshObject::CreateNewVertices creates vertices within sorted pools of vertices that share same material -*/ -int RAS_MeshObject::FindVertexArray(int numverts, - RAS_IPolyMaterial* polymat) +void RAS_MeshObject::RemoveFromBuckets(void *clientobj) { -// bool found=false; - int array=-1; + list<RAS_MeshMaterial>::iterator it; - KX_ArrayOptimizer* ao = GetArrayOptimizer(polymat); + for(it = m_materials.begin();it!=m_materials.end();++it) { + RAS_MeshSlot **msp = it->m_slots[clientobj]; - for (unsigned 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; - } - } - } + if(!msp) + continue; - 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); - } + RAS_MeshSlot *ms = *msp; - return array; + it->m_bucket->RemoveMesh(ms); + it->m_slots.remove(clientobj); + } } - - - //void RAS_MeshObject::Transform(const MT_Transform& trans) //{ //m_trans.translate(MT_Vector3(0,0,1));//.operator *=(trans); @@ -538,159 +448,62 @@ void RAS_MeshObject::RelativeTransform(const MT_Vector3& vec) } */ - - -void RAS_MeshObject::UpdateMaterialList() -{ - m_materials.clear(); - unsigned int numpolys = m_Polygons.size(); - // for all polygons, find out which material they use, and add it to the set of materials - for (unsigned int i=0;i<numpolys;i++) - { - m_materials.insert(m_Polygons[i]->GetMaterial()); +void RAS_MeshObject::SortPolygons(RAS_MeshSlot& ms, const MT_Transform &transform) +{ + // Limitations: sorting is quite simple, and handles many + // cases wrong, partially due to polygons being sorted per + // bucket. + // + // a) mixed triangles/quads are sorted wrong + // b) mixed materials are sorted wrong + // c) more than 65k faces are sorted wrong + // d) intersecting objects are sorted wrong + // e) intersecting polygons are sorted wrong + // + // a) can be solved by making all faces either triangles or quads + // if they need to be z-sorted. c) could be solved by allowing + // larger buckets, b) and d) cannot be solved easily if we want + // to avoid excessive state changes while drawing. e) would + // require splitting polygons. + + RAS_MeshSlot::iterator it; + size_t j; + + for(ms.begin(it); !ms.end(it); ms.next(it)) { + unsigned int nvert = (int)it.array->m_type; + unsigned int totpoly = it.totindex/nvert; + + if(totpoly <= 1) + continue; + if(it.array->m_type == RAS_DisplayArray::LINE) + continue; + + // Extract camera Z plane... + const MT_Vector3 pnorm(transform.getBasis()[2]); + // unneeded: const MT_Scalar pval = transform.getOrigin()[2]; + + vector<polygonSlot> slots(totpoly); + + /* get indices and z into temporary array */ + for(j=0; j<totpoly; j++) + slots[j].get(it.vertex, it.index, j*nvert, nvert, pnorm); + + /* sort (stable_sort might be better, if flickering happens?) */ + std::sort(slots.begin(), slots.end(), backtofront()); + + /* get indices from temporary array again */ + for(j=0; j<totpoly; j++) + slots[j].set(it.index, j*nvert, nvert); } } -struct RAS_MeshObject::polygonSlot -{ - float m_z; - RAS_Polygon *m_poly; - - polygonSlot(float z, RAS_Polygon* poly) : - m_z(z), - m_poly(poly) - {} - /** - * pnorm and pval form the plane equation that the distance from is used to - * sort against. - */ - polygonSlot(const MT_Vector3 &pnorm, const MT_Scalar &pval, RAS_MeshObject *mesh, RAS_Polygon* poly) : - m_poly(poly) - { - const KX_VertexIndex &base = m_poly->GetIndexBase(); - RAS_TexVert *vert = mesh->GetVertex(base.m_vtxarray, base.m_indexarray[0], poly->GetMaterial()->GetPolyMaterial()); - m_z = MT_dot(pnorm, vert->getLocalXYZ()) + pval; - - for(int i = 1; i < m_poly->VertexCount(); i++) - { - vert = mesh->GetVertex(base.m_vtxarray, base.m_indexarray[i], poly->GetMaterial()->GetPolyMaterial()); - float z = MT_dot(pnorm, vert->getLocalXYZ()) + pval; - m_z += z; - } - m_z /= m_poly->VertexCount(); - } -}; - -struct RAS_MeshObject::backtofront -{ - bool operator()(const polygonSlot &a, const polygonSlot &b) const - { - return a.m_z < b.m_z; - } -}; -struct RAS_MeshObject::fronttoback +void RAS_MeshObject::SchedulePolygons(int drawingmode) { - bool operator()(const polygonSlot &a, const polygonSlot &b) const - { - return a.m_z > b.m_z; - } -}; - - -void RAS_MeshObject::SortPolygons(const MT_Transform &transform) -{ - if (!m_zsort) - return; - - // Extract camera Z plane... - const MT_Vector3 pnorm(transform.getBasis()[2]); - const MT_Scalar pval = transform.getOrigin()[2]; - - unsigned int numpolys = m_Polygons.size(); - std::multiset<polygonSlot, backtofront> alphapolyset; - std::multiset<polygonSlot, fronttoback> solidpolyset; - - for (unsigned int p = 0; p < numpolys; p++) - { - RAS_Polygon* poly = m_Polygons[p]; - if (poly->IsVisible()) - { - if (poly->GetMaterial()->GetPolyMaterial()->IsTransparant()) - { - alphapolyset.insert(polygonSlot(pnorm, pval, this, poly)); - } else { - solidpolyset.insert(polygonSlot(pnorm, pval, this, poly)); - } - } - } - - // Clear current array data. - for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) - { - vector<KX_IndexArray*> *indexcache = &GetArrayOptimizer((*it)->GetPolyMaterial())->m_IndexArrayCache1; - for (vector<KX_IndexArray*>::iterator iit = indexcache->begin(); iit != indexcache->end(); ++iit) - (*iit)->clear(); - } - - std::multiset<polygonSlot, fronttoback>::iterator sit = solidpolyset.begin(); - for (; sit != solidpolyset.end(); ++sit) - SchedulePoly((*sit).m_poly->GetVertexIndexBase(), (*sit).m_poly->VertexCount(), (*sit).m_poly->GetMaterial()->GetPolyMaterial()); - - std::multiset<polygonSlot, backtofront>::iterator ait = alphapolyset.begin(); - for (; ait != alphapolyset.end(); ++ait) - SchedulePoly((*ait).m_poly->GetVertexIndexBase(), (*ait).m_poly->VertexCount(), (*ait).m_poly->GetMaterial()->GetPolyMaterial()); -} - - -void RAS_MeshObject::SchedulePolygons(const MT_Transform &transform, int drawingmode) -{ -// int nummaterials = m_materials.size(); - int i; - if (m_bModified) { - for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) - { - RAS_MaterialBucket* bucket = *it; - - bucket->SchedulePolygons(drawingmode); - if (bucket->GetPolyMaterial()->IsZSort()) - m_zsort = true; - } - - int numpolys = m_Polygons.size(); - - if ((drawingmode > RAS_IRasterizer::KX_BOUNDINGBOX) && - (drawingmode < 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()); - - } - m_zsort = false; - } - else - { - if (!m_zsort) - { - 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; - - m_MeshMod = true; + m_bMeshModified = true; } } + |