00001 /* 00002 File: SceneObjects.cc 00003 00004 Function: See header file 00005 00006 Author: Andrew Willmott 00007 00008 Notes: 00009 */ 00010 00011 #include "gcl/SceneObjects.h" 00012 #include "gcl/VecUtil.h" 00013 #include "gcl/GCLConfig.h" 00014 00015 // --- Polygon methods -------------------------------------------------------- 00016 00017 StrConst scPoly::Label() const 00018 { 00019 return("mesh"); 00020 } 00021 00022 IndexList *gIdentityList = 0; 00023 00024 00025 /* 00026 Current defaults: 00027 00028 point indexes = [0, 1, 2, 3...] 00029 normal, texture indexes: point indexes 00030 colour indexes: normal indexes 00031 */ 00032 00033 Void scPoly::Draw(Renderer &r, SLContext *context) 00034 // draw one or more polygons 00035 { 00036 Int i, j; 00037 Int f, faces, faceS, faceE; 00038 Vector normal; 00039 Colour polyClr; 00040 PointList *points; 00041 NormalList *normals; 00042 ColourList *colours; 00043 CoordList *coords; 00044 Texture *texture; 00045 IndexList *indexes; 00046 IndexList *clrIndexes; 00047 IndexList *normIndexes; 00048 IndexList *coordIndexes; 00049 IndexList *faceIndexes; 00050 scMeshType *meshType; 00051 RenderStyle meshStyle; 00052 00053 points = SC_GET(Points); 00054 colours = SC_GET(Colours); 00055 normals = SC_GET(Normals); 00056 texture = SC_GET(Texture); 00057 00058 if (!gIdentityList) 00059 { 00060 gIdentityList = new IndexList(256); 00061 for (i = 0; i < gIdentityList->NumItems(); i++) 00062 gIdentityList->Item(i) = i; 00063 } 00064 00065 indexes = SC_GET(PointIndexes); 00066 faceIndexes = SC_GET(FaceIndexes); 00067 if (meshType = SC_GET(MeshType)) 00068 meshStyle = meshType->itsType; 00069 else 00070 meshStyle = sRenderStyle; 00071 00072 if (!indexes) 00073 { 00074 indexes = gIdentityList; 00075 Assert(points->NumItems() <= 256, "polygon too large"); 00076 // note: we are relying on Array not changing the current items 00077 // array when we resize down and then back up again. 00078 // (This is currently safe: the items array only changes if the array 00079 // size is increased.) 00080 indexes->SetSize(points->NumItems()); 00081 } 00082 00083 normIndexes = SC_GET(NormalIndexes); 00084 if (!normIndexes) 00085 normIndexes = indexes; 00086 00087 if (colours) 00088 { 00089 clrIndexes = SC_GET(ColourIndexes); 00090 if (!clrIndexes) 00091 clrIndexes = normIndexes; 00092 } 00093 else 00094 { 00095 if (SC_GET(Colour)) 00096 polyClr = *(SC_GET(Colour)); 00097 else if (SC_GET(Emittance)) 00098 polyClr = *(SC_GET(Emittance)); 00099 else 00100 polyClr[0] = -1.0; 00101 } 00102 00103 if (texture) 00104 { 00105 // texture map 00106 coords = SC_GET(Coords); 00107 if (coords) 00108 { 00109 r.SetTexture(texture->image); 00110 coordIndexes = SC_GET(CoordIndexes); 00111 if (!coordIndexes) 00112 coordIndexes = gIdentityList; 00113 } 00114 } 00115 else 00116 coords = 0; 00117 00118 if (faceIndexes) 00119 { 00120 00121 if (faceIndexes->NumItems() < 2) 00122 { 00123 // XXX empty face index list 00124 // should modify face begin & end routines to cull 00125 // such empty lists; requires object->Remove() method? 00126 // _Warning("Empty face index list"); 00127 return; 00128 } 00129 00130 faceS = faceIndexes->Item(0); 00131 faceE = faceIndexes->Item(1); 00132 faces = faceIndexes->NumItems() - 1; 00133 f = 2; 00134 } 00135 else 00136 { 00137 faceS = 0; 00138 faceE = indexes->NumItems(); 00139 faces = 1; 00140 } 00141 00142 while (true) 00143 { 00144 r.Begin(meshStyle); 00145 00146 if (!normals) 00147 { 00148 CalcTriAreaNormal((*points)[(*indexes)[faceS]], 00149 (*points)[(*indexes)[faceS + 1]], 00150 (*points)[(*indexes)[faceS + 2]], 00151 normal 00152 ); 00153 r.N(normal); 00154 } 00155 00156 if (!colours && polyClr[0] >= 0.0) 00157 r.SetColour(polyClr); 00158 00159 for (i = faceS; i < faceE; i++) 00160 { 00161 if (colours) 00162 { 00163 j = (*clrIndexes)[i]; 00164 r.SetColour((*colours)[j]); 00165 } 00166 if (coords) 00167 { 00168 j = (*coordIndexes)[i]; 00169 r.SetTexCoord((*coords)[j]); 00170 } 00171 if (normals) 00172 { 00173 j = (*normIndexes)[i]; 00174 r.SetNormal((*normals)[j]); 00175 } 00176 00177 j = (*indexes)[i]; 00178 r.SetPoint((*points)[j]); 00179 } 00180 r.End(); 00181 00182 if (faces <= 1) break; 00183 faces--; 00184 faceS = faceE; 00185 faceE = faceIndexes->Item(f++); 00186 } 00187 00188 if (coords) 00189 r.SetTexture(0); 00190 } 00191 00192 Void scPoly::DecimateSelf(Decimator &dec) 00193 { 00194 Int i, j, n, idx[32], changed; 00195 Int fi, fStart, fEnd, fLen; 00196 SLContext *context = dec.context; 00197 PointList *points = SC_GET(Points); 00198 IndexList *indexes = SC_GET(PointIndexes); 00199 IndexList *faces = SC_GET(FaceIndexes); 00200 00201 if (!points) 00202 return; 00203 00204 if (!indexes) 00205 { 00206 if (!gIdentityList) 00207 { 00208 gIdentityList = new IndexList(256); 00209 for (i = 0; i < gIdentityList->NumItems(); i++) 00210 gIdentityList->Item(i) = i; 00211 } 00212 indexes = gIdentityList; 00213 Assert(points->NumItems() <= 256, "polygon too large"); 00214 // note: we are relying on Array not changing the current items 00215 // array when we resize down and then back up again. 00216 // (This is currently safe: the items array only changes if the array 00217 // size is increased.) 00218 indexes->SetSize(points->NumItems()); 00219 } 00220 00221 changed = 1; 00222 if (faces) 00223 { 00224 fStart = (*faces)[0]; 00225 fEnd = (*faces)[1]; 00226 fLen = fEnd - fStart; 00227 fi = 2; 00228 } 00229 else 00230 { 00231 fStart = 0; 00232 fLen = fEnd = indexes->NumItems(); 00233 } 00234 00235 while (true) 00236 { 00237 if (!(dec.flags & DecTris)) 00238 n = fLen; 00239 else if (fLen == 4 && (dec.flags & DecQuads)) 00240 { 00241 // XXX : not stable as height of pgram goes to zero. 00242 00243 Int *ip = &(*indexes)[fStart]; 00244 Vector ab = (*points)[ip[1]] - (*points)[ip[0]]; 00245 Vector cd = (*points)[ip[2]] - (*points)[ip[3]]; 00246 00247 // ab == cd : |ab - cd| / |ab + cd| < eps? 00248 00249 if (sqrlen(ab - cd) / sqrlen(ab + cd) < 1e-6) 00250 n = 4; 00251 else 00252 n = 3; 00253 } 00254 else 00255 n = 3; 00256 00257 for (j = 0; j < n; j++) 00258 idx[j] = (*indexes)[j + fStart] + dec.pointsAccNum; 00259 00260 dec.HandlePoly(n, idx, changed); 00261 dec.decNum++; 00262 changed = 0; 00263 00264 if (n == 3) 00265 for (j = fStart + 2; j < fEnd - 1; j++) 00266 { 00267 idx[1] = (*indexes)[j] + dec.pointsAccNum; 00268 idx[2] = (*indexes)[j + 1] + dec.pointsAccNum; 00269 dec.HandlePoly(n, idx, 0); 00270 dec.decNum++; 00271 } 00272 00273 if (faces && fi < faces->NumItems()) 00274 { 00275 fStart = fEnd; 00276 fEnd = (*faces)[fi++]; 00277 fLen = fEnd - fStart; 00278 } 00279 else 00280 break; 00281 } 00282 } 00283 00284 Void scPoly::Parse(istream &s) 00285 { 00286 } 00287 00288 00289 // --- Attributes ------------------------------------------------------------- 00290 00291 Void scPoints::Apply(const Transform &m) 00292 { 00293 Int i; 00294 00295 for (i = 0; i < NumItems(); i++) 00296 SELF[i] = proj(xform(m, Vector4(SELF[i], 1.0))); 00297 } 00298 00299 Void scCoords::Apply(const Transform &m) 00300 { 00301 } 00302 00303 Void scTransform::ApplyActionSelf(scSceneAction &a) 00304 { 00305 scObject::ApplyActionSelf(a); 00306 a.transAcc = xform(a.transAcc, SELF); 00307 } 00308 00309 Void scCamera::Parse(istream &s) 00310 { 00311 String str; 00312 Vector p; 00313 Char c; 00314 Int model = 1; 00315 00316 ChompWhiteSpace(s); 00317 while (s.peek() == '+') // extension? 00318 { 00319 s.get(c); 00320 str.ReadWord(s); 00321 00322 if (str == "eye") 00323 s >> position; 00324 else if (str == "dir") 00325 s >> viewDir; 00326 else if (str == "lookAt") 00327 { 00328 s >> lookAt; 00329 model = 2; 00330 } 00331 else if (str == "vup") 00332 s >> up; 00333 else if (str == "scale") 00334 s >> scale; 00335 else if (str == "fov") 00336 s >> fov; 00337 else if (str == "clipNear") 00338 s >> clipNear; 00339 else if (str == "clipFar") 00340 s >> clipFar; 00341 else 00342 cerr << "unknown camera option: '" << str << "'" << endl; 00343 00344 ChompWhiteSpace(s); 00345 } 00346 00347 SetupFromParams(); 00348 } 00349 00350 Void scCamera::Print(ostream &s) const 00351 { 00352 // GetViewDirParams(); XXX can't do this 'cause of const 00353 00354 s << "camera"; 00355 00356 if (scale != 1.0) 00357 s << " +scale " << scale; 00358 00359 s << " +eye " << position; 00360 s << " +dir " << viewDir; 00361 s << " +vup " << up; 00362 s << " +fov " << fov; 00363 } 00364 00365 Void scIndexes::Print(ostream &s) const 00366 { 00367 switch (AttrID()) 00368 { 00369 case aPointIndexes: 00370 s << "indexes "; 00371 break; 00372 case aNormalIndexes: 00373 s << "n_indexes "; 00374 break; 00375 case aCoordIndexes: 00376 s << "t_indexes "; 00377 break; 00378 case aColourIndexes: 00379 s << "c_indexes "; 00380 break; 00381 case aFaceIndexes: 00382 s << "faces "; 00383 break; 00384 } 00385 00386 s << (IndexList&) SELF << endl; 00387 } 00388 00389 Void scTexture::Parse(istream &s) 00390 { 00391 String str; 00392 00393 ChompWhiteSpace(s); 00394 s >> str; 00395 Load(str); 00396 } 00397 00398 Void scTexture::Print(ostream &s) const 00399 { 00400 s << "texture \"" << textureFile.GetPath() << '"'; 00401 } 00402 00403 Void scMeshType::Parse(istream &s) 00404 { 00405 String str; 00406 00407 ChompWhiteSpace(s); 00408 // s >> itsType; 00409 } 00410 00411 Void scMeshType::Print(ostream &s) const 00412 { 00413 s << "meshtype \"" << itsType << '"'; 00414 } 00415