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