00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 #include <algorithm>
00018 #include "ShadowVolumeGen.h"
00019 
00020 using namespace Fluxus;
00021 
00022 ShadowVolumeGen::ShadowVolumeGen() :
00023 m_ShadowVolume(PolyPrimitive::QUADS),
00024 m_LightPosition(5,5,0),
00025 m_Length(10),
00026 m_Debug(false)
00027 {
00028 }
00029 
00030 ShadowVolumeGen::~ShadowVolumeGen() 
00031 {
00032 }
00033 
00034 void ShadowVolumeGen::Generate(Primitive *prim)
00035 {   
00036     PolyPrimitive *poly = dynamic_cast<PolyPrimitive*>(prim);
00037     if (poly)
00038     {
00039         PolyGen(poly);
00040     }
00041     else
00042     {       
00043         NURBSPrimitive *nurbs = dynamic_cast<NURBSPrimitive*>(prim);
00044         if (nurbs)
00045         {
00046             NURBSGen(nurbs);
00047         }
00048     }
00049 }
00050 
00051 void ShadowVolumeGen::Clear()
00052 { 
00053     m_ShadowVolume.Clear();
00054     
00055 }
00056 
00057 PolyPrimitive *ShadowVolumeGen::GetVolume() 
00058 { 
00059     return &m_ShadowVolume; 
00060 }
00061 
00062 void ShadowVolumeGen::PolyGen(PolyPrimitive *src)
00063 {   
00064     TypedPData<dVector> *points = dynamic_cast<TypedPData<dVector>* >(src->GetDataRaw("p"));
00065     
00070     const vector<dVector> &normals = src->GetGeometricNormals();
00071     const vector<vector<int> > &connected=src->GetConnectedVerts();
00072     
00073     dMatrix &transform = src->GetState()->Transform;
00074     
00075     int stride=0;
00076     if (src->GetType()==PolyPrimitive::TRISTRIP) stride=2;
00077     if (src->GetType()==PolyPrimitive::QUADS) stride=4;
00078     if (src->GetType()==PolyPrimitive::TRILIST) stride=3;
00079     if (stride>0)
00080     {
00081         SharedEdgeContainer edges = src->GetUniqueEdges();
00082         vector<pair<dVector,dVector> > silhouette;
00083             
00084         if (src->IsIndexed())
00085         {
00086             vector<unsigned int> index = src->GetIndex();
00087             
00088             for (SharedEdgeContainer::iterator i=edges.begin(); i!=edges.end(); ++i)
00089             {
00090                 EdgeContainer sharededges = *i;
00091 
00092                 dVector lightdir = transform.transform(points->m_Data[index[sharededges.begin()->first]])-m_LightPosition;
00093                 lightdir.normalise();
00094 
00095                 if (sharededges.size()==2)
00096                 {
00097                     bool backface=false;
00098                     bool frontface=false;
00099 
00100                     EdgeContainer::iterator frontedge;
00101 
00102                     
00103                     for (EdgeContainer::iterator edge=sharededges.begin(); edge!=sharededges.end(); ++edge)
00104                     {           
00105                         
00106                         
00107                         if (lightdir.dot(transform.transform_no_trans(normals[edge->first]))>0) 
00108                         {
00109                             frontedge=edge;
00110                             frontface=true;
00111                         }
00112                         else backface=true;
00113                     }
00114 
00115                     
00116                     if (backface && frontface) 
00117                     {           
00118                         silhouette.push_back(pair<dVector,dVector>(transform.transform(points->m_Data[index[frontedge->first]]),
00119                                                                    transform.transform(points->m_Data[index[frontedge->second]])));
00120                     }
00121                 }
00122             }
00123         }
00124         else
00125         {
00126             
00127             for (SharedEdgeContainer::iterator i=edges.begin(); i!=edges.end(); ++i)
00128             {
00129                 EdgeContainer sharededges = *i;
00130 
00131                 dVector lightdir = transform.transform(points->m_Data[sharededges.begin()->first])-m_LightPosition;
00132                 lightdir.normalise();
00133 
00134 
00135                 if (sharededges.size()==2)
00136                 {
00137                     bool backface=false;
00138                     bool frontface=false;
00139 
00140                     EdgeContainer::iterator frontedge;
00141 
00142                     
00143                     for (EdgeContainer::iterator edge=sharededges.begin(); edge!=sharededges.end(); ++edge)
00144                     {           
00145                         
00146                         
00147                         if (lightdir.dot(transform.transform_no_trans(normals[edge->first]))>0) 
00148                         {
00149                             frontedge=edge;
00150                             frontface=true;
00151                         }
00152                         else backface=true;
00153                     }
00154 
00155                     
00156                     if (backface && frontface) 
00157                     {           
00158                         silhouette.push_back(pair<dVector,dVector>(transform.transform(points->m_Data[frontedge->first]),
00159                                                                    transform.transform(points->m_Data[frontedge->second])));
00160                     }
00161                 }
00162             }
00163         }
00164         
00165         for (vector<pair<dVector,dVector> >::iterator i=silhouette.begin();
00166              i!=silhouette.end(); i++)
00167         {
00168             AddEdge(i->first,i->second);
00169         }
00170     }
00171 }
00172 
00173 void ShadowVolumeGen::AddEdge(dVector start, dVector end)
00174 {
00175     if (m_Debug)
00176     {
00177         glDisable(GL_LIGHTING);
00178         glLineWidth(3);
00179         glBegin(GL_LINES);                  
00180             glColor3f(1,0,0);
00181             glVertex3fv(start.arr());
00182             glColor3f(0,0,1);
00183             glVertex3fv(end.arr());
00184         glEnd();
00185         glEnable(GL_LIGHTING);
00186     }
00187 
00188     m_ShadowVolume.AddVertex(dVertex(start,dVector(0,0,0),0,0));
00189     m_ShadowVolume.AddVertex(dVertex(end,dVector(0,0,0),0,0));
00190 
00191     dVector proj = end-m_LightPosition;
00192     m_ShadowVolume.AddVertex(dVertex(end+proj*m_Length,dVector(0,0,0),0,0));
00193 
00194     proj = start-m_LightPosition;
00195     m_ShadowVolume.AddVertex(dVertex(start+proj*m_Length,dVector(0,0,0),0,0));
00196 }
00197 
00199 void ShadowVolumeGen::NURBSGen(NURBSPrimitive *src)
00200 {   
00201     TypedPData<dVector> *points = dynamic_cast<TypedPData<dVector>* >(src->GetDataRaw("p"));
00202     TypedPData<dVector> *normals = dynamic_cast<TypedPData<dVector>* >(src->GetDataRaw("n"));
00203     
00204     dMatrix &transform = src->GetState()->Transform;
00205     
00206     int stride=4;
00207     
00208     
00209     for (unsigned int vert=0; vert<points->Size(); vert+=stride)
00210     {
00211         
00212         vector<int> edgeverts;
00213 
00214         for (int facevert=0; facevert<stride; facevert++)
00215         {
00216             dVector lightdir = transform.transform(points->m_Data[vert+facevert])-m_LightPosition;
00217             lightdir.normalise();
00218 
00219             bool backface=false;
00220             bool frontface=false;
00221 
00223             
00224             
00225             
00226 
00227 
00228 
00229 
00230 
00231             
00232             
00233             if (backface && frontface) 
00234             {
00235                 edgeverts.push_back(vert+facevert);
00236             }
00237         }
00238 
00239         if (edgeverts.size()>=2)
00240         {
00241             for (unsigned int i=0; i<edgeverts.size()-1; i++)
00242             {   
00243                 dVector worldpoint1 = transform.transform(points->m_Data[edgeverts[i]]);
00244                 dVector worldpoint2 = transform.transform(points->m_Data[edgeverts[i+1]]);
00245 
00246                 glPushMatrix();
00247                 glDisable(GL_LIGHTING);
00248                 glBegin(GL_LINES);                  
00249                     glColor3f(1,0,0);
00250                     glVertex3fv(worldpoint1.arr());
00251                     glColor3f(0,0,1);
00252                     glVertex3fv(worldpoint2.arr());
00253                 glEnd();
00254                 glEnable(GL_LIGHTING);
00255                 glPopMatrix();
00256 
00257                 m_ShadowVolume.AddVertex(dVertex(worldpoint1,dVector(0,0,0),0,0));
00258                 m_ShadowVolume.AddVertex(dVertex(worldpoint2,dVector(0,0,0),0,0));
00259 
00260                 dVector proj = worldpoint2-m_LightPosition;
00261                 m_ShadowVolume.AddVertex(dVertex(worldpoint1+proj*100,dVector(0,0,0),0,0));
00262 
00263                 proj = worldpoint1-m_LightPosition;
00264                 m_ShadowVolume.AddVertex(dVertex(worldpoint2+proj*100,dVector(0,0,0),0,0));
00265             }
00266         }
00267     }
00268 }
00269 
00270