PolyPrimitive.cpp

Go to the documentation of this file.
00001 // Copyright (C) 2005 Dave Griffiths
00002 //
00003 // This program is free software; you can redistribute it and/or modify
00004 // it under the terms of the GNU General Public License as published by
00005 // the Free Software Foundation; either version 2 of the License, or
00006 // (at your option) any later version.
00007 //
00008 // This program is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 // GNU General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this program; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00016 
00017 #include "Renderer.h"
00018 #include "PolyPrimitive.h"
00019 #include "State.h"
00020 
00021 //#define RENDER_NORMALS
00022 //#define RENDER_BBOX
00023 
00024 using namespace Fluxus;
00025     
00026 PolyPrimitive::PolyPrimitive(Type t) :
00027 m_IndexMode(false),
00028 m_Type(t)
00029 {
00030     AddData("p",new TypedPData<dVector>);
00031     AddData("n",new TypedPData<dVector>);
00032     AddData("c",new TypedPData<dColour>);
00033     AddData("t",new TypedPData<dVector>);
00034     
00035     // setup the direct access for speed
00036     PDataDirty();
00037 }
00038 
00039 PolyPrimitive::PolyPrimitive(const PolyPrimitive &other) :
00040 Primitive(other),
00041 m_IndexMode(other.m_IndexMode),
00042 m_IndexData(other.m_IndexData),
00043 m_Type(other.m_Type)
00044 {
00045     PDataDirty();
00046 }
00047 
00048 PolyPrimitive::~PolyPrimitive()
00049 {
00050 }
00051 
00052 PolyPrimitive *PolyPrimitive::Clone() const
00053 {
00054     return new PolyPrimitive(*this);
00055 }
00056 
00057 void PolyPrimitive::Clear()
00058 {
00059     Resize(0);
00060     m_ConnectedVerts.clear();
00061     m_GeometricNormals.clear();
00062     m_UniqueEdges.clear();
00063 }
00064 
00065 void PolyPrimitive::PDataDirty()
00066 {
00067     // reset pointers
00068     m_VertData=GetDataVec<dVector>("p");
00069     m_NormData=GetDataVec<dVector>("n");
00070     m_ColData=GetDataVec<dColour>("c");
00071     m_TexData=GetDataVec<dVector>("t");
00072 }
00073 
00074 void PolyPrimitive::AddVertex(const dVertex &Vert) 
00075 { 
00076     m_VertData->push_back(Vert.point); 
00077     m_NormData->push_back(Vert.normal); 
00078     m_ColData->push_back(Vert.col);     
00079     m_TexData->push_back(dVector(Vert.s, Vert.t, 0));
00080     
00081     m_ConnectedVerts.clear();
00082     m_GeometricNormals.clear();
00083     m_UniqueEdges.clear();
00084 }   
00085 
00086 void PolyPrimitive::Render()
00087 {
00088     // some drivers crash if they don't get enough data for a primitive...
00089     if (m_VertData->size()<3) return; 
00090     if (m_IndexMode && m_IndexData.size()<3) return;
00091     
00092     int type=0;
00093     switch (m_Type)
00094     {
00095         case TRISTRIP : type=GL_TRIANGLE_STRIP; break;
00096         case QUADS : 
00097             // some drivers crash if they don't get enough data for a primitive...
00098             if (m_IndexMode)
00099             {
00100                 if (m_IndexData.size()<4) return; 
00101             }
00102             else
00103             {
00104                 if (m_VertData->size()<4) return; 
00105             }
00106             type=GL_QUADS;  
00107         break;
00108         case TRILIST : type=GL_TRIANGLES; break;
00109         case TRIFAN : type=GL_TRIANGLE_FAN; break;
00110         case POLYGON : type=GL_POLYGON; break;
00111     }
00112     
00113     if (m_State.Hints & HINT_AALIAS) glEnable(GL_LINE_SMOOTH);      
00114     else glDisable(GL_LINE_SMOOTH);     
00115 
00116     if (m_State.Hints & HINT_NORMAL)
00117     {
00118         glColor3f(1,0,0);
00119         glDisable(GL_LIGHTING);
00120         glBegin(GL_LINES);
00121         for (unsigned int i=0; i<m_VertData->size(); i++)
00122         {
00123             glVertex3fv((*m_VertData)[i].arr());
00124             glVertex3fv(((*m_VertData)[i]+(*m_NormData)[i]).arr());
00125         }
00126         glEnd();
00127         glEnable(GL_LIGHTING);
00128     }
00129     if (m_State.Hints & HINT_UNLIT) glDisable(GL_LIGHTING);
00130         
00131     glVertexPointer(3,GL_FLOAT,sizeof(dVector),(void*)m_VertData->begin()->arr());
00132     glNormalPointer(GL_FLOAT,sizeof(dVector),(void*)m_NormData->begin()->arr());
00133     glTexCoordPointer(3,GL_FLOAT,sizeof(dVector),(void*)m_TexData->begin()->arr());
00134     
00135     if (m_State.Hints & HINT_MULTITEX)
00136     {
00137         for (int n=1; n<MAX_TEXTURES; n++)
00138         {
00139             char name[3]; 
00140             snprintf(name,3,"t%d",n);
00141             TypedPData<dVector> *tex = dynamic_cast<TypedPData<dVector>*>(GetDataRaw(name));
00142             if (tex!=NULL)
00143             {   
00144                 #ifdef ENABLE_MULTITEXTURE
00145                 glClientActiveTexture(GL_TEXTURE0+n);
00146                 #endif
00147                 glTexCoordPointer(3,GL_FLOAT,sizeof(dVector),(void*)tex->m_Data.begin()->arr());
00148             }
00149         }
00150         #ifdef ENABLE_MULTITEXTURE
00151         glClientActiveTexture(GL_TEXTURE0);
00152         #endif
00153     }
00154     
00155     if (m_State.Hints & HINT_VERTCOLS)
00156     {
00157         glEnableClientState(GL_COLOR_ARRAY);
00158         glColorPointer(3,GL_FLOAT,sizeof(dVector),(void*)m_ColData->begin()->arr());
00159     }
00160     else
00161     {
00162         glDisableClientState(GL_COLOR_ARRAY);
00163     }
00164     
00165     if (m_State.Hints & HINT_SOLID)
00166     {
00167         if (m_IndexMode) glDrawElements(type,m_IndexData.size(),GL_UNSIGNED_INT,&(m_IndexData[0]));
00168         else glDrawArrays(type,0,m_VertData->size());
00169     }
00170 
00171     if (m_State.Hints & HINT_WIRE)
00172     {
00173         glDisable(GL_TEXTURE_2D);
00174         glPolygonOffset(1,1);
00175         glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
00176         glColor4fv(m_State.WireColour.arr());
00177         glDisable(GL_LIGHTING);
00178         if (m_IndexMode) glDrawElements(type,m_IndexData.size(),GL_UNSIGNED_INT,&(m_IndexData[0]));
00179         else glDrawArrays(type,0,m_VertData->size());
00180         glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
00181         glEnable(GL_LIGHTING);
00182         glEnable(GL_TEXTURE_2D);
00183     }
00184 
00185     if (m_State.Hints & HINT_POINTS)
00186     {
00187         glDisable(GL_TEXTURE_2D);
00188         glPolygonMode(GL_FRONT_AND_BACK,GL_POINT);
00189         glColor4fv(m_State.WireColour.arr());
00190         glDisable(GL_LIGHTING);
00191         if (m_IndexMode) glDrawElements(type,m_IndexData.size(),GL_UNSIGNED_INT,&(m_IndexData[0]));
00192         else glDrawArrays(type,0,m_VertData->size());
00193         glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
00194         glEnable(GL_LIGHTING);
00195         glEnable(GL_TEXTURE_2D);
00196     }
00197 
00198 
00199     if (m_State.Hints & HINT_UNLIT) glEnable(GL_LIGHTING);
00200 }
00201 
00202 void PolyPrimitive::RecalculateNormals(bool smooth)
00203 {
00204     GenerateTopology();
00205     CalculateGeometricNormals();
00206 
00207     if (!m_GeometricNormals.empty()) 
00208     {
00209         if (m_IndexMode) // smooth mode only for indexed polys
00210         {
00211             vector<int> count(m_VertData->size());
00212             
00213             // clear the normals
00214             for (unsigned int i=0; i<m_NormData->size(); i++)
00215             {
00216                 (*m_NormData)[i]=dVector(0,0,0);
00217                 count[i]=0;
00218             }
00219             
00220             // add all the contributing normals
00221             for (unsigned int i=0; i<m_IndexData.size(); i++)
00222             {
00223                 (*m_NormData)[m_IndexData[i]]+=m_GeometricNormals[i];
00224                 count[m_IndexData[i]]++;
00225             }
00226 
00227             // scale back
00228             for (unsigned int i=0; i<m_NormData->size(); i++)
00229             {
00230                 (*m_NormData)[i]/=(float)count[i];
00231             }
00232         }
00233         else
00234         {
00235             for (unsigned int i=0; i<m_VertData->size(); i++)
00236             {
00237                 (*m_NormData)[i]=m_GeometricNormals[i];
00238             }
00239 
00240             if (smooth)
00241             {
00242                 // smooth the normals
00243                 TypedPData<dVector> *newnorms = new TypedPData<dVector>;
00244                 for (unsigned int i=0; i<m_VertData->size(); i++)
00245                 {
00246                     float count=1;
00247                     dVector n = (*m_NormData)[i];
00248                     for (vector<int>::iterator b=m_ConnectedVerts[i].begin(); 
00249                             b!=m_ConnectedVerts[i].end(); b++)
00250                     {
00251                         n+=(*m_NormData)[*b];
00252                         count+=1;
00253                     }
00254                     newnorms->m_Data.push_back((n/count).normalise());
00255                 }
00256                 SetDataRaw("n", newnorms);
00257             }
00258         }
00259     }
00260 }
00261 
00262 void PolyPrimitive::ConvertToIndexed()
00263 {
00264     if (m_ConnectedVerts.empty())
00265     {
00266         CalculateConnected();
00267     }
00268         
00269     TypedPData<dVector> *NewVerts = new TypedPData<dVector>;
00270     TypedPData<dVector> *NewNorms = new TypedPData<dVector>;
00271     TypedPData<dColour> *NewCols = new TypedPData<dColour>;
00272     TypedPData<dVector> *NewTex = new TypedPData<dVector>;
00273 
00274     m_IndexData.clear();
00275     int vert=0;
00276     int index=0;
00277     map<int,int> verttoindex;
00278     for (vector<vector<int> >::iterator i=m_ConnectedVerts.begin();
00279          i!=m_ConnectedVerts.end(); i++)
00280     {
00281         if (!i->empty() && verttoindex.find(vert)==verttoindex.end())
00282         {
00283             // take the first connected as our new point - will trash non-shared
00284             // normals, texture coords and colours
00285             NewVerts->m_Data.push_back((*m_VertData)[(*i)[0]]);
00286             NewNorms->m_Data.push_back((*m_NormData)[(*i)[0]]);
00287             NewCols->m_Data.push_back((*m_ColData)[(*i)[0]]);
00288             NewTex->m_Data.push_back((*m_TexData)[(*i)[0]]);
00289             m_IndexData.push_back(index);
00290             
00291             // record all the verts that can point to this index
00292             for (vector<int>::iterator v=i->begin(); v!=i->end(); v++)
00293             {
00294                 verttoindex[*v]=index;
00295             }
00296             
00297             index++;
00298         }
00299         else
00300         {
00301             m_IndexData.push_back(verttoindex[vert]);
00302         }
00303         
00304         vert++;
00305     }
00306     
00307     SetDataRaw("p", NewVerts);
00308     SetDataRaw("n", NewNorms);
00309     SetDataRaw("c", NewCols);
00310     SetDataRaw("t", NewTex);
00311         
00312     m_IndexMode=true;
00313 }
00314 
00315 void PolyPrimitive::GenerateTopology()
00316 {
00317     if (m_ConnectedVerts.empty())
00318     {
00319         CalculateConnected();
00320     }
00321     
00322     if (m_GeometricNormals.empty())
00323     {
00324         CalculateGeometricNormals();
00325     }
00326 }
00327 
00328 void PolyPrimitive::CalculateConnected()
00329 { 
00330     // cache the connected verts 
00331     if (m_IndexMode)
00332     {       
00333         for (unsigned int i=0; i<m_IndexData.size(); i++)
00334         {
00335             vector<int> connected;
00336             for (unsigned int b=0; b<m_IndexData.size(); b++)
00337             {
00338                 // compare index value
00339                 if (i!=b && m_IndexData[i]==m_IndexData[b])
00340                 {
00341                     connected.push_back(b);
00342                 }
00343             }
00344             m_ConnectedVerts.push_back(connected);
00345         }
00346     }
00347     else
00348     {
00349         for (unsigned int i=0; i<m_VertData->size(); i++)
00350         {
00351             vector<int> connected;
00352             for (unsigned int b=0; b<m_VertData->size(); b++)
00353             {
00354                 // find all close verts
00355                 if (i!=b && (*m_VertData)[i].feq((*m_VertData)[b]))
00356                 {
00357                     connected.push_back(b);
00358                 }
00359             }
00360             m_ConnectedVerts.push_back(connected);
00361         }
00362     }
00363 }
00364 
00365 
00366 void PolyPrimitive::CalculateGeometricNormals()
00367 {
00369     // one face 
00370     if (m_Type==POLYGON && m_VertData->size()>2) 
00371     {
00372         m_GeometricNormals.clear();
00373         dVector a((*m_VertData)[0]-(*m_VertData)[1]);
00374         dVector b((*m_VertData)[1]-(*m_VertData)[2]);
00375         dVector normal(a.cross(b));
00376         normal.normalise();
00377         
00378         for (unsigned int i=0; i<m_VertData->size(); i++)
00379         {
00380             m_GeometricNormals.push_back(normal);
00381         }
00382         
00383         return;
00384     }
00385     
00386     int stride=0;
00387     if (m_Type==TRISTRIP) stride=2;
00388     if (m_Type==QUADS) stride=4;
00389     if (m_Type==TRILIST) stride=3;
00390     if (stride>0)
00391     {
00392         m_GeometricNormals.clear();
00393         
00394         if (m_IndexMode)
00395         {
00396             for (unsigned int i=0; i<m_IndexData.size(); i+=stride)
00397             {
00398                 if (i+2<m_IndexData.size())
00399                 {
00400                     dVector a((*m_VertData)[m_IndexData[i]]-(*m_VertData)[m_IndexData[i+1]]);
00401                     dVector b((*m_VertData)[m_IndexData[i+1]]-(*m_VertData)[m_IndexData[i+2]]);
00402                     dVector normal(a.cross(b));
00403                     normal.normalise();
00404                     for (int n=0; n<stride; n++)
00405                     {
00406                         m_GeometricNormals.push_back(normal);
00407                     }
00408                 }
00409             }
00410         }
00411         else
00412         {
00413             for (unsigned int i=0; i<m_VertData->size(); i+=stride)
00414             {
00415                 if (i+2<m_VertData->size())
00416                 {
00417                     dVector a((*m_VertData)[i]-(*m_VertData)[i+1]);
00418                     dVector b((*m_VertData)[i+1]-(*m_VertData)[i+2]);
00419                     dVector normal(a.cross(b));
00420                     normal.normalise();
00421                     for (int n=0; n<stride; n++)
00422                     {
00423                         m_GeometricNormals.push_back(normal);
00424                     }
00425                 }
00426             }
00427         }
00428     }
00429 }
00430 
00431 void PolyPrimitive::CalculateUniqueEdges()
00432 {
00433     if (m_UniqueEdges.empty())
00434     {
00435         // todo - need different approach for TRIFAN
00436         int stride=0;
00437         if (m_Type==TRISTRIP) stride=2;
00438         if (m_Type==QUADS) stride=4;
00439         if (m_Type==TRILIST) stride=3;
00440         if (stride>0)
00441         {       
00442             set<pair<int,int> > firstpass;
00443             
00444             unsigned int vertcount=m_VertData->size();
00445             if (m_IndexMode) vertcount=m_IndexData.size();
00446             
00447             // first, record all valid edges from the topology type
00448             for (unsigned int i=0; i<vertcount; i+=stride)
00449             {
00450                 for (int n=0; n<stride-1; n++)
00451                 {
00452                     firstpass.insert(pair<int,int>(n+i,n+i+1));
00453                 }
00454                 firstpass.insert(pair<int,int>(i+stride-1,i));
00455             }
00456 
00457             set<pair<int,int> > stored;
00458             pair<int,int> key;
00459 
00460             // now find all edges which share points and group them together
00461             for (unsigned int i=0; i<vertcount; i+=stride)
00462             {
00463                 for (int n=0; n<stride-1; n++)
00464                 {   
00465                     UniqueEdgesFindShared(pair<int,int>(n+i,n+i+1), firstpass, stored);
00466                 }   
00467                 UniqueEdgesFindShared(pair<int,int>(i+stride-1,i), firstpass, stored);  
00468             }
00469         }
00470     }
00471 }
00472 
00473 void PolyPrimitive::UniqueEdgesFindShared(pair<int,int> edge, set<pair<int,int> > firstpass, set<pair<int,int> > &stored)
00474 {
00475     vector<pair<int,int> > edges;
00476     
00477     if (stored.find(edge)==stored.end() && stored.find(pair<int,int>(edge.second,edge.first))==stored.end())
00478     {
00479         // first, store the test edge
00480         edges.push_back(edge);
00481         stored.insert(edge);
00482         
00483         //Trace::Stream<<"edge:"<<edge.first<<" "<<edge.second<<endl;
00484         
00485         // make all combinations of verts connected to the edge verts
00486         for (vector<int>::iterator a=m_ConnectedVerts[edge.first].begin();
00487             a!=m_ConnectedVerts[edge.first].end(); a++)
00488         {
00489             for (vector<int>::iterator b=m_ConnectedVerts[edge.second].begin();
00490                     b!=m_ConnectedVerts[edge.second].end(); b++)
00491             {
00492                 //Trace::Stream<<*a<<" "<<*b<<endl;
00493                 pair<int, int> candidate(*a,*b);
00494                 if (firstpass.find(candidate)!=firstpass.end() && // if this is a real edge
00495                     stored.find(candidate)==stored.end() )        // and we've not stored it already
00496                 {
00497                     edges.push_back(candidate);
00498                     stored.insert(candidate);
00499                     //Trace::Stream<<"^ "<<candidate.first<<" "<<candidate.second<<endl;
00500                 }                       
00501 
00502                 pair<int, int> rcandidate(*b,*a);
00503                 if (firstpass.find(rcandidate)!=firstpass.end() && // if this is a real edge
00504                     stored.find(rcandidate)==stored.end() )        // and we've not stored it already
00505                 {
00506                     edges.push_back(rcandidate);
00507                     stored.insert(rcandidate);
00508                     //Trace::Stream<<"^ "<<rcandidate.first<<" "<<rcandidate.second<<endl;
00509                 }                       
00510             }
00511         }
00512 
00513         if (!edges.empty())
00514         {
00515             m_UniqueEdges.push_back(edges);
00516         }
00517     }
00518 }
00519 
00520 dBoundingBox PolyPrimitive::GetBoundingBox()
00521 {   
00522     dBoundingBox box;
00523     for (vector<dVector>::iterator i=m_VertData->begin(); i!=m_VertData->end(); ++i)
00524     {
00525         box.expand(*i);
00526     }
00527     return box;
00528 }
00529 
00530 void PolyPrimitive::ApplyTransform(bool ScaleRotOnly)
00531 {
00532     if (!ScaleRotOnly)
00533     {
00534         for (vector<dVector>::iterator i=m_VertData->begin(); i!=m_VertData->end(); ++i)
00535         {
00536             *i=GetState()->Transform.transform(*i);
00537             // why not normals?
00538         }
00539     }
00540     else
00541     {
00542         for (unsigned int i=0; i<m_VertData->size(); i++)
00543         {
00544             (*m_VertData)[i]=GetState()->Transform.transform_no_trans((*m_VertData)[i]);
00545             (*m_NormData)[i]=GetState()->Transform.transform_no_trans((*m_NormData)[i]).normalise();
00546         }
00547     }
00548     
00549     GetState()->Transform.init();
00550 }
00551 

Generated on Mon Feb 11 06:54:25 2008 for The Fluxus Renderer (libfluxus) by  doxygen 1.5.1