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

Generated on Tue Sep 4 23:22:18 2007 for The Fluxus Renderer (libfluxus) by  doxygen 1.5.1