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) // accumulate
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         
00241         if (smooth)
00242         {
00243             // smooth the normals
00244             TypedPData<dVector> *newnorms = new TypedPData<dVector>;
00245             for (unsigned int i=0; i<m_VertData->size(); i++)
00246             {
00247                 float count=1;
00248                 dVector n = (*m_NormData)[i];
00249                 for (vector<int>::iterator b=m_ConnectedVerts[i].begin(); 
00250                         b!=m_ConnectedVerts[i].end(); b++)
00251                 {
00252                     n+=(*m_NormData)[*b];
00253                     count+=1;
00254                 }
00255                 newnorms->m_Data.push_back((n/count).normalise());
00256             }
00257             SetDataRaw("n", newnorms);
00258         }
00259     }
00260 }
00261 
00262 void PolyPrimitive::ConvertToIndexed()
00263 {
00264     if (m_IndexMode) return;
00265 
00266     if (m_ConnectedVerts.empty())
00267     {
00268         CalculateConnected();
00269     }
00270         
00271     TypedPData<dVector> *NewVerts = new TypedPData<dVector>;
00272     TypedPData<dVector> *NewNorms = new TypedPData<dVector>;
00273     TypedPData<dColour> *NewCols = new TypedPData<dColour>;
00274     TypedPData<dVector> *NewTex = new TypedPData<dVector>;
00275 
00276     m_IndexData.clear();
00277     int vert=0;
00278     int index=0;
00279     map<int,int> verttoindex;
00280     for (vector<vector<int> >::iterator i=m_ConnectedVerts.begin();
00281          i!=m_ConnectedVerts.end(); i++)
00282     {
00283         if (!i->empty() && verttoindex.find(vert)==verttoindex.end())
00284         {
00285             // take the first connected as our new point - will trash non-shared
00286             // normals, texture coords and colours
00287             NewVerts->m_Data.push_back((*m_VertData)[(*i)[0]]);
00288             NewNorms->m_Data.push_back((*m_NormData)[(*i)[0]]);
00289             NewCols->m_Data.push_back((*m_ColData)[(*i)[0]]);
00290             NewTex->m_Data.push_back((*m_TexData)[(*i)[0]]);
00291             m_IndexData.push_back(index);
00292             
00293             // record all the verts that can point to this index
00294             for (vector<int>::iterator v=i->begin(); v!=i->end(); v++)
00295             {
00296                 verttoindex[*v]=index;
00297             }
00298             
00299             index++;
00300         }
00301         else
00302         {
00303             m_IndexData.push_back(verttoindex[vert]);
00304         }
00305         
00306         vert++;
00307     }
00308     
00309     SetDataRaw("p", NewVerts);
00310     SetDataRaw("n", NewNorms);
00311     SetDataRaw("c", NewCols);
00312     SetDataRaw("t", NewTex);
00313         
00314     m_IndexMode=true;
00315 }
00316 
00317 void PolyPrimitive::GenerateTopology()
00318 {
00319     if (m_ConnectedVerts.empty())
00320     {
00321         CalculateConnected();
00322     }
00323     
00324     if (m_GeometricNormals.empty())
00325     {
00326         CalculateGeometricNormals();
00327     }
00328 }
00329 
00330 void PolyPrimitive::CalculateConnected()
00331 { 
00332     
00333     if (m_IndexMode)
00334     {       
00335         for (unsigned int i=0; i<m_IndexData.size(); i++)
00336         {
00337             vector<int> connected;
00338             for (unsigned int b=0; b<m_IndexData.size(); b++)
00339             {
00340                 // compare index value
00341                 if (i!=b && (m_IndexData[i]==m_IndexData[b] || 
00342                    // compare positions
00343                    ((*m_VertData)[m_IndexData[i]].feq((*m_VertData)[m_IndexData[b]]))))
00344                 {
00345                     connected.push_back(b);
00346                 }
00347             }
00348             
00349             m_ConnectedVerts.push_back(connected);
00350         }
00351     }
00352     else
00353     {
00354         // cache the connected verts 
00355         for (unsigned int i=0; i<m_VertData->size(); i++)
00356         {
00357             vector<int> connected;
00358             for (unsigned int b=0; b<m_VertData->size(); b++)
00359             {
00360                 // find all close verts
00361                 if (i!=b && (*m_VertData)[i].feq((*m_VertData)[b]))
00362                 {
00363                     connected.push_back(b);
00364                 }
00365             }   
00366 
00367             m_ConnectedVerts.push_back(connected);
00368         }
00369     }
00370 }
00371 
00372 
00373 void PolyPrimitive::CalculateGeometricNormals()
00374 {
00376     // one face 
00377     if (m_Type==POLYGON && m_VertData->size()>2) 
00378     {
00379         m_GeometricNormals.clear();
00380         dVector a((*m_VertData)[0]-(*m_VertData)[1]);
00381         dVector b((*m_VertData)[1]-(*m_VertData)[2]);
00382         dVector normal(a.cross(b));
00383         normal.normalise();
00384         
00385         for (unsigned int i=0; i<m_VertData->size(); i++)
00386         {
00387             m_GeometricNormals.push_back(normal);
00388         }
00389         
00390         return;
00391     }
00392     
00393     int stride=0;
00394     if (m_Type==TRISTRIP) stride=2;
00395     if (m_Type==QUADS) stride=4;
00396     if (m_Type==TRILIST) stride=3;
00397     if (stride>0)
00398     {
00399         m_GeometricNormals.clear();
00400         
00401         if (m_IndexMode)
00402         {
00403             for (unsigned int i=0; i<m_IndexData.size(); i+=stride)
00404             {
00405                 if (i+2<m_IndexData.size())
00406                 {
00407                     dVector a((*m_VertData)[m_IndexData[i]]-(*m_VertData)[m_IndexData[i+1]]);
00408                     dVector b((*m_VertData)[m_IndexData[i+1]]-(*m_VertData)[m_IndexData[i+2]]);
00409                     dVector normal(a.cross(b));
00410                     normal.normalise();
00411                     for (int n=0; n<stride; n++)
00412                     {
00413                         m_GeometricNormals.push_back(normal);
00414                     }
00415                 }
00416             }
00417         }
00418         else
00419         {
00420             for (unsigned int i=0; i<m_VertData->size(); i+=stride)
00421             {
00422                 if (i+2<m_VertData->size())
00423                 {
00424                     dVector a((*m_VertData)[i]-(*m_VertData)[i+1]);
00425                     dVector b((*m_VertData)[i+1]-(*m_VertData)[i+2]);
00426                     dVector normal(a.cross(b));
00427                     normal.normalise();
00428                     for (int n=0; n<stride; n++)
00429                     {
00430                         m_GeometricNormals.push_back(normal);
00431                     }
00432                 }
00433             }
00434         }
00435     }
00436 }
00437 
00438 void PolyPrimitive::CalculateUniqueEdges()
00439 {
00440     if (m_UniqueEdges.empty())
00441     {
00442         // todo - need different approach for TRIFAN
00443         int stride=0;
00444         if (m_Type==TRISTRIP) stride=2;
00445         if (m_Type==QUADS) stride=4;
00446         if (m_Type==TRILIST) stride=3;
00447         if (stride>0)
00448         {       
00449             set<pair<int,int> > firstpass;
00450             
00451             unsigned int vertcount=m_VertData->size();
00452             if (m_IndexMode) vertcount=m_IndexData.size();
00453             
00454             // first, record all valid edges from the topology type
00455             for (unsigned int i=0; i<vertcount; i+=stride)
00456             {
00457                 for (int n=0; n<stride-1; n++)
00458                 {
00459                     firstpass.insert(pair<int,int>(n+i,n+i+1));
00460                 }
00461                 firstpass.insert(pair<int,int>(i+stride-1,i));
00462             }
00463 
00464             set<pair<int,int> > stored;
00465             pair<int,int> key;
00466 
00467             // now find all edges which share points and group them together
00468             for (unsigned int i=0; i<vertcount; i+=stride)
00469             {
00470                 for (int n=0; n<stride-1; n++)
00471                 {   
00472                     UniqueEdgesFindShared(pair<int,int>(n+i,n+i+1), firstpass, stored);
00473                 }   
00474                 UniqueEdgesFindShared(pair<int,int>(i+stride-1,i), firstpass, stored);  
00475             }
00476         }
00477     }
00478 }
00479 
00480 void PolyPrimitive::UniqueEdgesFindShared(pair<int,int> edge, set<pair<int,int> > firstpass, set<pair<int,int> > &stored)
00481 {
00482     vector<pair<int,int> > edges;
00483     
00484     if (stored.find(edge)==stored.end() && stored.find(pair<int,int>(edge.second,edge.first))==stored.end())
00485     {
00486         // first, store the test edge
00487         edges.push_back(edge);
00488         stored.insert(edge);
00489         
00490         //Trace::Stream<<"edge:"<<edge.first<<" "<<edge.second<<endl;
00491         
00492         // make all combinations of verts connected to the edge verts
00493         for (vector<int>::iterator a=m_ConnectedVerts[edge.first].begin();
00494             a!=m_ConnectedVerts[edge.first].end(); a++)
00495         {
00496             for (vector<int>::iterator b=m_ConnectedVerts[edge.second].begin();
00497                     b!=m_ConnectedVerts[edge.second].end(); b++)
00498             {
00499                 //Trace::Stream<<*a<<" "<<*b<<endl;
00500                 pair<int, int> candidate(*a,*b);
00501                 if (firstpass.find(candidate)!=firstpass.end() && // if this is a real edge
00502                     stored.find(candidate)==stored.end() )        // and we've not stored it already
00503                 {
00504                     edges.push_back(candidate);
00505                     stored.insert(candidate);
00506                     //Trace::Stream<<"^ "<<candidate.first<<" "<<candidate.second<<endl;
00507                 }                       
00508 
00509                 pair<int, int> rcandidate(*b,*a);
00510                 if (firstpass.find(rcandidate)!=firstpass.end() && // if this is a real edge
00511                     stored.find(rcandidate)==stored.end() )        // and we've not stored it already
00512                 {
00513                     edges.push_back(rcandidate);
00514                     stored.insert(rcandidate);
00515                     //Trace::Stream<<"^ "<<rcandidate.first<<" "<<rcandidate.second<<endl;
00516                 }                       
00517             }
00518         }
00519 
00520         if (!edges.empty())
00521         {
00522             m_UniqueEdges.push_back(edges);
00523         }
00524     }
00525 }
00526 
00527 dBoundingBox PolyPrimitive::GetBoundingBox()
00528 {   
00529     dBoundingBox box;
00530     for (vector<dVector>::iterator i=m_VertData->begin(); i!=m_VertData->end(); ++i)
00531     {
00532         box.expand(*i);
00533     }
00534     return box;
00535 }
00536 
00537 void PolyPrimitive::ApplyTransform(bool ScaleRotOnly)
00538 {
00539     if (!ScaleRotOnly)
00540     {
00541         for (vector<dVector>::iterator i=m_VertData->begin(); i!=m_VertData->end(); ++i)
00542         {
00543             *i=GetState()->Transform.transform(*i);
00544             // why not normals?
00545         }
00546     }
00547     else
00548     {
00549         for (unsigned int i=0; i<m_VertData->size(); i++)
00550         {
00551             (*m_VertData)[i]=GetState()->Transform.transform_no_trans((*m_VertData)[i]);
00552             (*m_NormData)[i]=GetState()->Transform.transform_no_trans((*m_NormData)[i]).normalise();
00553         }
00554     }
00555     
00556     GetState()->Transform.init();
00557 }
00558 

Generated on Wed Sep 17 21:16:30 2008 for The Fluxus Renderer (libfluxus) by  doxygen 1.5.1