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.Resize(0);
00054 }
00055
00056 PolyPrimitive *ShadowVolumeGen::GetVolume()
00057 {
00058 return &m_ShadowVolume;
00059 }
00060
00061 void ShadowVolumeGen::PolyGen(PolyPrimitive *src)
00062 {
00063 TypedPData<dVector> *points = dynamic_cast<TypedPData<dVector>* >(src->GetDataRaw("p"));
00064
00069 const vector<dVector> &normals = src->GetGeometricNormals();
00070 const vector<vector<int> > &connected=src->GetConnectedVerts();
00071
00072 dMatrix &transform = src->GetState()->Transform;
00073
00074 int stride=0;
00075 if (src->GetType()==PolyPrimitive::TRISTRIP) stride=2;
00076 if (src->GetType()==PolyPrimitive::QUADS) stride=4;
00077 if (src->GetType()==PolyPrimitive::TRILIST) stride=3;
00078 if (stride>0)
00079 {
00080 SharedEdgeContainer edges = src->GetUniqueEdges();
00081 vector<pair<dVector,dVector> > silhouette;
00082
00083 if (src->IsIndexed())
00084 {
00085 vector<unsigned int> index = src->GetIndex();
00086
00087 for (SharedEdgeContainer::iterator i=edges.begin(); i!=edges.end(); ++i)
00088 {
00089 EdgeContainer sharededges = *i;
00090
00091 dVector lightdir = transform.transform(points->m_Data[index[sharededges.begin()->first]])-m_LightPosition;
00092 lightdir.normalise();
00093
00094 if (sharededges.size()==2)
00095 {
00096 bool backface=false;
00097 bool frontface=false;
00098
00099 EdgeContainer::iterator frontedge;
00100
00101
00102 for (EdgeContainer::iterator edge=sharededges.begin(); edge!=sharededges.end(); ++edge)
00103 {
00104
00105
00106 if (lightdir.dot(transform.transform_no_trans(normals[edge->first]))>0)
00107 {
00108 frontedge=edge;
00109 frontface=true;
00110 }
00111 else backface=true;
00112 }
00113
00114
00115 if (backface && frontface)
00116 {
00117 silhouette.push_back(pair<dVector,dVector>(transform.transform(points->m_Data[index[frontedge->first]]),
00118 transform.transform(points->m_Data[index[frontedge->second]])));
00119 }
00120 }
00121 }
00122 }
00123 else
00124 {
00125
00126 for (SharedEdgeContainer::iterator i=edges.begin(); i!=edges.end(); ++i)
00127 {
00128 EdgeContainer sharededges = *i;
00129
00130 dVector lightdir = transform.transform(points->m_Data[sharededges.begin()->first])-m_LightPosition;
00131 lightdir.normalise();
00132
00133
00134 if (sharededges.size()==2)
00135 {
00136 bool backface=false;
00137 bool frontface=false;
00138
00139 EdgeContainer::iterator frontedge;
00140
00141
00142 for (EdgeContainer::iterator edge=sharededges.begin(); edge!=sharededges.end(); ++edge)
00143 {
00144
00145
00146 if (lightdir.dot(transform.transform_no_trans(normals[edge->first]))>0)
00147 {
00148 frontedge=edge;
00149 frontface=true;
00150 }
00151 else backface=true;
00152 }
00153
00154
00155 if (backface && frontface)
00156 {
00157 silhouette.push_back(pair<dVector,dVector>(transform.transform(points->m_Data[frontedge->first]),
00158 transform.transform(points->m_Data[frontedge->second])));
00159 }
00160 }
00161 }
00162 }
00163
00164 for (vector<pair<dVector,dVector> >::iterator i=silhouette.begin();
00165 i!=silhouette.end(); i++)
00166 {
00167 AddEdge(i->first,i->second);
00168 }
00169 }
00170 }
00171
00172 void ShadowVolumeGen::AddEdge(dVector start, dVector end)
00173 {
00174 if (m_Debug)
00175 {
00176 glDisable(GL_LIGHTING);
00177 glLineWidth(3);
00178 glBegin(GL_LINES);
00179 glColor3f(1,0,0);
00180 glVertex3fv(start.arr());
00181 glColor3f(0,0,1);
00182 glVertex3fv(end.arr());
00183 glEnd();
00184 glEnable(GL_LIGHTING);
00185 }
00186
00187 m_ShadowVolume.AddVertex(dVertex(start,dVector(0,0,0),0,0));
00188 m_ShadowVolume.AddVertex(dVertex(end,dVector(0,0,0),0,0));
00189
00190 dVector proj = end-m_LightPosition;
00191 m_ShadowVolume.AddVertex(dVertex(end+proj*m_Length,dVector(0,0,0),0,0));
00192
00193 proj = start-m_LightPosition;
00194 m_ShadowVolume.AddVertex(dVertex(start+proj*m_Length,dVector(0,0,0),0,0));
00195 }
00196
00198 void ShadowVolumeGen::NURBSGen(NURBSPrimitive *src)
00199 {
00200 TypedPData<dVector> *points = dynamic_cast<TypedPData<dVector>* >(src->GetDataRaw("p"));
00201 TypedPData<dVector> *normals = dynamic_cast<TypedPData<dVector>* >(src->GetDataRaw("n"));
00202
00203 dMatrix &transform = src->GetState()->Transform;
00204
00205 int stride=4;
00206
00207
00208 for (unsigned int vert=0; vert<points->Size(); vert+=stride)
00209 {
00210
00211 vector<int> edgeverts;
00212
00213 for (int facevert=0; facevert<stride; facevert++)
00214 {
00215 dVector lightdir = transform.transform(points->m_Data[vert+facevert])-m_LightPosition;
00216 lightdir.normalise();
00217
00218 bool backface=false;
00219 bool frontface=false;
00220
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 if (backface && frontface)
00233 {
00234 edgeverts.push_back(vert+facevert);
00235 }
00236 }
00237
00238 if (edgeverts.size()>=2)
00239 {
00240 for (unsigned int i=0; i<edgeverts.size()-1; i++)
00241 {
00242 dVector worldpoint1 = transform.transform(points->m_Data[edgeverts[i]]);
00243 dVector worldpoint2 = transform.transform(points->m_Data[edgeverts[i+1]]);
00244
00245 glPushMatrix();
00246 glDisable(GL_LIGHTING);
00247 glBegin(GL_LINES);
00248 glColor3f(1,0,0);
00249 glVertex3fv(worldpoint1.arr());
00250 glColor3f(0,0,1);
00251 glVertex3fv(worldpoint2.arr());
00252 glEnd();
00253 glEnable(GL_LIGHTING);
00254 glPopMatrix();
00255
00256 m_ShadowVolume.AddVertex(dVertex(worldpoint1,dVector(0,0,0),0,0));
00257 m_ShadowVolume.AddVertex(dVertex(worldpoint2,dVector(0,0,0),0,0));
00258
00259 dVector proj = worldpoint2-m_LightPosition;
00260 m_ShadowVolume.AddVertex(dVertex(worldpoint1+proj*100,dVector(0,0,0),0,0));
00261
00262 proj = worldpoint1-m_LightPosition;
00263 m_ShadowVolume.AddVertex(dVertex(worldpoint2+proj*100,dVector(0,0,0),0,0));
00264 }
00265 }
00266 }
00267 }
00268
00269