Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/gameengine/Rasterizer/RAS_MeshObject.cpp')
-rw-r--r--source/gameengine/Rasterizer/RAS_MeshObject.cpp282
1 files changed, 155 insertions, 127 deletions
diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp
index e4b654343e7..af5228e4c35 100644
--- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp
+++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp
@@ -35,6 +35,8 @@
#include "MT_MinMax.h"
#include "MT_Point3.h"
+#include <algorithm>
+
STR_String RAS_MeshObject::s_emptyname = "";
@@ -63,11 +65,12 @@ KX_ArrayOptimizer::~KX_ArrayOptimizer()
-RAS_MeshObject::RAS_MeshObject(int lightlayer)
+RAS_MeshObject::RAS_MeshObject(Mesh* mesh, int lightlayer)
: m_bModified(true),
m_lightlayer(lightlayer),
m_zsort(false),
m_MeshMod(true),
+ m_mesh(mesh),
m_class(0)
{
}
@@ -200,28 +203,35 @@ void RAS_MeshObject::DebugColor(unsigned int abgr)
m_debugcolor = abgr;
}
-
+void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba)
+{
+ const vecVertexArray & vertexvec = GetVertexCache(mat);
+
+ for (vector<KX_VertexArray*>::const_iterator it = vertexvec.begin(); it != vertexvec.end(); ++it)
+ {
+ KX_VertexArray::iterator vit;
+ for (vit=(*it)->begin(); vit != (*it)->end(); vit++)
+ {
+ vit->SetRGBA(rgba);
+ }
+ }
+}
void RAS_MeshObject::SchedulePoly(const KX_VertexIndex& idx,
int numverts,
RAS_IPolyMaterial* mat)
{
- //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;
+
+ if (!mat->UsesTriangles())
ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[3]);
- }
}
-
void RAS_MeshObject::ScheduleWireframePoly(const KX_VertexIndex& idx,
int numverts,
int edgecode,
@@ -256,27 +266,30 @@ int RAS_MeshObject::FindOrAddVertex(int vtxarray,
const MT_Vector4& tangent,
const unsigned int rgbacolor,
const MT_Vector3& normal,
+ bool flat,
RAS_IPolyMaterial* mat,
- int orgindex)
+ int origindex)
{
- KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]);
+ KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);
int numverts = ao->m_VertexArrayCache1[vtxarray]->size();//m_VertexArrayCount[vtxarray];
- RAS_TexVert newvert(xyz,uv,uv2,tangent,rgbacolor,normal, 0);
+ RAS_TexVert newvert(xyz,uv,uv2,tangent,rgbacolor,normal, flat? TV_CALCFACENORMAL: 0,origindex);
+
#define KX_FIND_SHARED_VERTICES
#ifdef KX_FIND_SHARED_VERTICES
-
- 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)
- )
+ if(!flat) {
+ for (std::vector<RAS_MatArrayIndex>::iterator it = m_xyz_index_to_vertex_index_mapping[origindex].begin();
+ it != m_xyz_index_to_vertex_index_mapping[origindex].end();
+ it++)
{
- return (*it).m_index;
+ if ((*it).m_arrayindex1 == ao->m_index1 &&
+ (*it).m_array == vtxarray &&
+ *(*it).m_matid == *mat &&
+ (*ao->m_VertexArrayCache1[vtxarray])[(*it).m_index].closeTo(&newvert)
+ )
+ {
+ return (*it).m_index;
+ }
}
}
#endif // KX_FIND_SHARED_VERTICES
@@ -289,22 +302,18 @@ int RAS_MeshObject::FindOrAddVertex(int vtxarray,
idx.m_array = vtxarray;
idx.m_index = numverts;
idx.m_matid = mat;
- m_xyz_index_to_vertex_index_mapping[orgindex].push_back(idx);
+ m_xyz_index_to_vertex_index_mapping[origindex].push_back(idx);
return numverts;
}
-
-
-const vecVertexArray& RAS_MeshObject::GetVertexCache (RAS_IPolyMaterial* mat)
+vecVertexArray& RAS_MeshObject::GetVertexCache (RAS_IPolyMaterial* mat)
{
- KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]);
+ KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);
return ao->m_VertexArrayCache1;
}
-
-
int RAS_MeshObject::GetVertexArrayLength(RAS_IPolyMaterial* mat)
{
int len = 0;
@@ -358,7 +367,7 @@ RAS_TexVert* RAS_MeshObject::GetVertex(unsigned int matid,
const vecIndexArrays& RAS_MeshObject::GetIndexCache (RAS_IPolyMaterial* mat)
{
- KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);//*(m_matVertexArrays[*mat]);
+ KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);
return ao->m_IndexArrayCache1;
}
@@ -367,16 +376,27 @@ const vecIndexArrays& RAS_MeshObject::GetIndexCache (RAS_IPolyMaterial* mat)
KX_ArrayOptimizer* RAS_MeshObject::GetArrayOptimizer(RAS_IPolyMaterial* polymat)
{
- KX_ArrayOptimizer** aop = (m_matVertexArrayS[*polymat]);
+ KX_ArrayOptimizer** aop = m_matVertexArrayS[polymat];
- if (aop)
+ if(aop)
return *aop;
+ // didn't find array, but an array might already exist
+ // for a material equal to this one
+ for(int i=0;i<m_matVertexArrayS.size();i++) {
+ RAS_IPolyMaterial *mat = (RAS_IPolyMaterial*)(m_matVertexArrayS.getKey(i)->getValue());
+ if(*mat == *polymat) {
+ m_matVertexArrayS.insert(polymat, *m_matVertexArrayS.at(i));
+ return *m_matVertexArrayS.at(i);
+ }
+ }
+
+ // create new array
int numelements = m_matVertexArrayS.size();
m_sortedMaterials.push_back(polymat);
-
+
KX_ArrayOptimizer* ao = new KX_ArrayOptimizer(numelements);
- m_matVertexArrayS.insert(*polymat,ao);
+ m_matVertexArrayS.insert(polymat, ao);
return ao;
}
@@ -398,7 +418,6 @@ void RAS_MeshObject::Bucketize(double* oglmatrix,
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);
}
@@ -423,7 +442,6 @@ void RAS_MeshObject::MarkVisible(double* oglmatrix,
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);
}
@@ -442,7 +460,6 @@ void RAS_MeshObject::RemoveFromBuckets(double* oglmatrix,
{
RAS_MaterialBucket* bucket = *it;
// RAS_IPolyMaterial* polymat = bucket->GetPolyMaterial();
- bucket->SchedulePolygons(0);
//KX_ArrayOptimizer* oa = GetArrayOptimizer(polymat);
bucket->RemoveMeshSlot(ms);
}
@@ -459,7 +476,7 @@ RAS_TexVert* RAS_MeshObject::GetVertex(short array,
unsigned int index,
RAS_IPolyMaterial* polymat)
{
- KX_ArrayOptimizer* ao = GetArrayOptimizer(polymat);//*(m_matVertexArrays[*polymat]);
+ KX_ArrayOptimizer* ao = GetArrayOptimizer(polymat);
return &((*(ao->m_VertexArrayCache1)[array])[index]);
}
@@ -467,13 +484,19 @@ RAS_TexVert* RAS_MeshObject::GetVertex(short array,
void RAS_MeshObject::ClearArrayData()
{
- for (int i=0;i<m_matVertexArrayS.size();i++)
- {
+ for (int i=0;i<m_matVertexArrayS.size();i++) {
KX_ArrayOptimizer** ao = m_matVertexArrayS.at(i);
+
+ // we have duplicate entries, only free once
+ for(int j=i+1;j<m_matVertexArrayS.size();j++) {
+ if(ao == m_matVertexArrayS.at(j)) {
+ ao = NULL;
+ break;
+ }
+ }
+
if (ao)
- {
delete *ao;
- }
}
}
@@ -555,31 +578,36 @@ void RAS_MeshObject::UpdateMaterialList()
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)
+ float m_z;
+ int m_index[4];
+
+ polygonSlot() {}
+
+ /* pnorm is the normal from the plane equation that the distance from is
+ * used to sort again. */
+ void get(const KX_VertexArray& vertexarray, const KX_IndexArray& indexarray,
+ int offset, int nvert, const MT_Vector3& pnorm)
{
- 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;
+ 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]].getLocalXYZ();
}
- m_z /= m_poly->VertexCount();
+
+ /* 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(KX_IndexArray& indexarray, int offset, int nvert)
+ {
+ int i;
+
+ for(i=0; i<nvert; i++)
+ indexarray[offset+i] = m_index[i];
}
};
@@ -599,100 +627,100 @@ struct RAS_MeshObject::fronttoback
}
};
-
void RAS_MeshObject::SortPolygons(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.
+
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.
+ // unneeded: const MT_Scalar pval = transform.getOrigin()[2];
+
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();
- }
+ if(!(*it)->IsZSort())
+ continue;
- 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());
+ RAS_IPolyMaterial *mat = (*it)->GetPolyMaterial();
+ KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);
+
+ vecIndexArrays& indexarrays = ao->m_IndexArrayCache1;
+ vecVertexArray& vertexarrays = ao->m_VertexArrayCache1;
+ unsigned int i, j, nvert = (mat->UsesTriangles())? 3: 4;
+
+ for(i=0; i<indexarrays.size(); i++) {
+ KX_IndexArray& indexarray = *indexarrays[i];
+ KX_VertexArray& vertexarray = *vertexarrays[i];
+
+ unsigned int totpoly = indexarray.size()/nvert;
+ vector<polygonSlot> slots(totpoly);
+
+ /* get indices and z into temporary array */
+ for(j=0; j<totpoly; j++)
+ slots[j].get(vertexarray, indexarray, 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(indexarray, j*nvert, nvert);
+ }
+ }
}
-void RAS_MeshObject::SchedulePolygons(const MT_Transform &transform, int drawingmode)
+void RAS_MeshObject::SchedulePolygons(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;
+ int i, numpolys = m_Polygons.size();
- bucket->SchedulePolygons(drawingmode);
- if (bucket->GetPolyMaterial()->IsZSort())
+ for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it)
+ if ((*it)->IsZSort())
m_zsort = true;
- }
-
- int numpolys = m_Polygons.size();
- if ((drawingmode > RAS_IRasterizer::KX_BOUNDINGBOX) &&
- (drawingmode < RAS_IRasterizer::KX_SOLID))
+ if (drawingmode == RAS_IRasterizer::KX_WIREFRAME)
{
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());
+ ScheduleWireframePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetEdgeCode(),
+ poly->GetMaterial()->GetPolyMaterial());
}
m_zsort = false;
}
else
{
- if (!m_zsort)
+ for (i=0;i<numpolys;i++)
{
- for (i=0;i<numpolys;i++)
- {
- RAS_Polygon* poly = m_Polygons[i];
- if (poly->IsVisible())
- {
- SchedulePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetMaterial()->GetPolyMaterial());
- }
- }
+ RAS_Polygon* poly = m_Polygons[i];
+ if (poly->IsVisible())
+ SchedulePoly(poly->GetVertexIndexBase(),poly->VertexCount(),
+ poly->GetMaterial()->GetPolyMaterial());
}
}
m_bModified = false;
-
m_MeshMod = true;
}
}
+