00001 #include <esg/parser/RhinoParser.h>
00002 #include <esg/Material.h>
00003 #include <esg/geometry/NurbsSurface.h>
00004 #include <esg/SpotLight.h>
00005 #include <esg/DirLight.h>
00006 #include <esg/PointLight.h>
00007 #include <esg/LightSource.h>
00008
00009 using namespace esg;
00010
00011
00012
00013
00014
00015
00016
00017
00018 const int RhinoParser::_objectFilter = ON::mesh_object;
00019
00020
00021 bool RhinoParser::_read_bitmap_table(ON_BinaryFile& file)
00022 {
00023 BOOL rc;
00024
00025 if (file.BeginRead3dmBitmapTable()) {
00026
00027 ON_Bitmap* pBitmap = NULL;
00028 for(;;) {
00029 pBitmap = NULL;
00030 rc = file.Read3dmBitmap(&pBitmap);
00031 if (rc == 0) break;
00032 if (rc < 0) {
00033 fprintf(stderr,"RhinoParser WARNING: Corrupt bitmap found. Skipping rest of bitmap table.\n");
00034 break;
00035 }
00036 bitmapTable.Append(pBitmap);
00037 }
00038
00039
00040
00041 if (!file.EndRead3dmBitmapTable()) {
00042 fprintf(stderr, "RhinoParser Error: FAILURE in EndRead3dmBitmapTable().\n");
00043 return false;
00044 }
00045 } else {
00046 fprintf(stderr, "RhinoParser WARNING: Missing or corrupt bitmap table - attempting to continue.\n");
00047 }
00048
00049 return true;
00050 }
00051
00052 bool RhinoParser::_read_material_table(ON_BinaryFile& file)
00053 {
00054 BOOL rc;
00055 ON_ClassArray<ON_Material> materialTable;
00056
00057 if (file.BeginRead3dmMaterialTable()) {
00058 ON_Material* pMaterial = NULL;
00059 for(;;) {
00060 rc = file.Read3dmMaterial(&pMaterial);
00061 if (rc == 0) break;
00062 if (rc < 0) {
00063 fprintf(stderr, "RhinoParser WARNING: Corrupt render material found. Skipping to material table.\n");
00064 break;
00065 }
00066 materialTable.Append(*pMaterial);
00067 delete pMaterial;
00068 pMaterial = NULL;
00069 }
00070
00071
00072
00073 if (!file.EndRead3dmMaterialTable()) {
00074 fprintf(stderr, "RhinoParser Error: FAILURE in EndRead3dmMaterialTable().\n");
00075 return false;
00076 }
00077 } else
00078 fprintf(stderr, "RhinoParser WARNING: Missing or corrupt render material table - attempting to continue.\n");
00079
00080
00081 _matTableSize = materialTable.Count();
00082 _specularMatTable = new AutoPtr<Material>* [_matTableSize];
00083 _diffuseMatTable = new AutoPtr<Material>* [_matTableSize];
00084 _ambientMatTable = new AutoPtr<Material>* [_matTableSize];
00085
00086 _roughnessMatTable = new AutoPtr<Material>* [_matTableSize];
00087 for (int i = 0; i < _matTableSize; i++) {
00088 Color3f specular(materialTable[i].Specular().FractionRed(),
00089 materialTable[i].Specular().FractionGreen(),
00090 materialTable[i].Specular().FractionBlue());
00091 Color3f diffuse (materialTable[i].Diffuse().FractionRed(),
00092 materialTable[i].Diffuse().FractionGreen(),
00093 materialTable[i].Diffuse().FractionBlue());
00094 Color3f ambient (materialTable[i].Ambient().FractionRed(),
00095 materialTable[i].Ambient().FractionGreen(),
00096 materialTable[i].Ambient().FractionBlue());
00097
00098
00099
00100 float sh = materialTable[i].Shine();
00101
00102
00103
00104 sh /= materialTable[i].MaxShine();
00105
00106
00107
00108 _specularMatTable[i] =new AutoPtr<Material>(new Specular(specular));
00109 _diffuseMatTable[i] =new AutoPtr<Material>(new Diffuse(diffuse));
00110 _ambientMatTable[i] =new AutoPtr<Material>(new Ambient(ambient));
00111
00112 _roughnessMatTable[i]=new AutoPtr<Material>(new Roughness(sh));
00113
00114 _specularMatTable[i]->registerReferer(this);
00115 _diffuseMatTable[i]->registerReferer(this);
00116 _ambientMatTable[i]->registerReferer(this);
00117
00118 _roughnessMatTable[i]->registerReferer(this);
00119 }
00120
00121 return true;
00122 }
00123
00124 bool RhinoParser::_read_layer_table(ON_BinaryFile& file)
00125 {
00126 BOOL rc;
00127
00128 if (file.BeginRead3dmLayerTable()) {
00129 ON_Layer* pLayer = NULL;
00130 for(;;) {
00131 pLayer = NULL;
00132 rc = file.Read3dmLayer(&pLayer);
00133 if (rc == 0) break;
00134 if (rc < 0) {
00135 fprintf(stderr, "RhinoParser WARNING: Corrupt layer found. Skipping rest of layer table.\n");
00136 break;
00137 }
00138 layerTable.Append(*pLayer);
00139 delete pLayer;
00140 pLayer = NULL;
00141 }
00142
00143
00144
00145 if (!file.EndRead3dmLayerTable()) {
00146 fprintf(stderr, "RhinoParser Error: FAILURE in EndRead3dmLayerTable().\n");
00147 return false;
00148 }
00149 } else {
00150 fprintf(stderr, "RhinoParser WARNING: Missing or corrupt layer table - attempting to continue.\n");
00151 }
00152
00153 return true;
00154 }
00155
00156 bool RhinoParser::_read_group_table(ON_BinaryFile& file)
00157 {
00158 BOOL rc;
00159
00160 if (file.BeginRead3dmGroupTable()) {
00161 ON_Group* pGroup = NULL;
00162 for(;;) {
00163 pGroup = NULL;
00164 rc = file.Read3dmGroup(&pGroup);
00165 if (rc == 0) break;
00166 if (rc < 0) {
00167 fprintf(stderr, "RhinoParser WARNING: Corrupt group found. Skipping rest of group table.\n");
00168 break;
00169 }
00170 groupTable.Append(*pGroup);
00171 delete pGroup;
00172 pGroup = NULL;
00173 }
00174
00175
00176
00177 if (!file.EndRead3dmGroupTable()) {
00178 fprintf(stderr, "RhinoParser Error: FAILURE in EndRead3dmGroupTable().\n");
00179 return false;
00180 }
00181 } else {
00182 fprintf(stderr, "RhinoParser WARNING: Missing or corrupt group table - attempting to continue.\n");
00183 }
00184
00185 return true;
00186 }
00187
00188 bool RhinoParser::_read_lights_table(ON_BinaryFile& file)
00189 {
00190 BOOL rc;
00191 ON_3dmObjectAttributes object_attributes;
00192 Color3f diffuse;
00193 bool isOn;
00194 Vector3 location;
00195 Vector3 direction;
00196 LightSource* pNewLight = NULL;
00197
00198 if (file.BeginRead3dmLightTable()) {
00199 ON_Light* pLight = NULL;
00200 for(;;) {
00201 object_attributes.Default();
00202 rc = file.Read3dmLight(&pLight,&object_attributes);
00203 if (rc == 0) break;
00204 if (rc < 0) {
00205 fprintf(stderr, "RhinoParser WARNING: Corrupt render light found. Skipping rest of light table.\n");
00206 break;
00207 }
00208
00209 isOn = pLight->IsEnabled();
00210 diffuse.set(pLight->Diffuse().FractionRed(),
00211 pLight->Diffuse().FractionGreen(),
00212 pLight->Diffuse().FractionBlue());
00213 location.set(pLight->Location().x,
00214 pLight->Location().y,
00215 pLight->Location().z);
00216 direction.set(pLight->Direction().x,
00217 pLight->Direction().y,
00218 pLight->Direction().z);
00219
00220 switch (pLight->Style()) {
00221
00222 case ON::camera_directional_light:
00223 case ON::world_directional_light:
00224 pNewLight = new DirLight(location, direction, diffuse, _oid++);
00225 break;
00226
00227 case ON::camera_point_light:
00228 case ON::world_point_light:
00229 pNewLight = new PointLight(location, diffuse, .0, .0, _oid++);
00230 break;
00231
00232 case ON::camera_spot_light:
00233 case ON::world_spot_light:
00234 pNewLight = new SpotLight(location, direction, diffuse,
00235 pLight->SpotAngleRadians(),
00236 (char) pLight->SpotExponent(),
00237 .0, .0,
00238 _oid++);
00239 break;
00240 case ON::ambient_light:
00241
00242 break;
00243 default:
00244
00245 break;
00246 }
00247
00248 if (pNewLight) {
00249 _lights.append(pNewLight);
00250 pNewLight = NULL;
00251 }
00252 delete pLight;
00253 pLight = NULL;
00254 }
00255
00256
00257
00258 if (!file.EndRead3dmLightTable()) {
00259 fprintf(stderr, "RhinoParser Error: FAILURE in EndRead3dmLightTable().\n");
00260 return false;
00261 }
00262 } else {
00263 fprintf(stderr, "RhinoParser WARNING: Missing or corrupt light table - attempting to continue.\n");
00264 }
00265
00266 return true;
00267 }
00268
00269 Vertex3* RhinoParser::_get_vertices(const ON_Mesh& mesh)
00270 {
00271 Vertex3* vertArray = new Vertex3 [mesh.m_V.Count()];
00272 for (register int i = 0; i < mesh.m_V.Count(); i++)
00273 vertArray[i].set(mesh.m_V[i].x, mesh.m_V[i].y, mesh.m_V[i].z);
00274 return vertArray;
00275 }
00276
00277 Vector3* RhinoParser::_get_normals(const ON_Mesh& mesh)
00278 {
00279 if (mesh.HasVertexNormals()) {
00280 Vector3* normArray = new Vector3 [mesh.m_N.Count()];
00281 for (register int i = 0; i < mesh.m_N.Count(); i++)
00282 normArray[i].set(mesh.m_N[i].x, mesh.m_N[i].y, mesh.m_N[i].z);
00283 return normArray;
00284 }
00285 return NULL;
00286 }
00287
00288 Vector2* RhinoParser::_get_texture_coords(const ON_Mesh& mesh)
00289 {
00290 if (mesh.HasTextureCoordinates()) {
00291 Vector2* textureArray = new Vector2 [mesh.m_T.Count()];
00292 for (register int i = 0; i < mesh.m_T.Count(); i++)
00293 textureArray[i].set(mesh.m_T[i].x, mesh.m_T[i].y);
00294 return textureArray;
00295 }
00296 return NULL;
00297 }
00298
00299 void RhinoParser::_set_material(SceneGraphObject& prim,
00300 const ON_3dmObjectAttributes& objAttr) const
00301 {
00302 int li = -1;
00303 int mi = -1;
00304
00305 switch (objAttr.MaterialSource()) {
00306 case ON::material_from_layer:
00307
00308 li = objAttr.m_layer_index;
00309 if (li >= 0 && li < layerTable.Count())
00310 mi = layerTable[li].RenderMaterialIndex();
00311 break;
00312 case ON::material_from_object:
00313
00314 mi = objAttr.m_material_index;
00315 break;
00316 default:
00317 mi = -1;
00318 }
00319
00320 if (mi < 0 || mi >= _matTableSize) {
00321 prim.appendSharedMaterial(_pDefSpecularMat);
00322 prim.appendSharedMaterial(_pDefDiffuseMat);
00323 prim.appendSharedMaterial(_pDefAmbientMat);
00324
00325 prim.appendSharedMaterial(_pDefRoughnessMat);
00326 } else {
00327 prim.appendSharedMaterial(_specularMatTable[mi]);
00328 prim.appendSharedMaterial(_diffuseMatTable[mi]);
00329 prim.appendSharedMaterial(_ambientMatTable[mi]);
00330
00331 prim.appendSharedMaterial(_roughnessMatTable[mi]);
00332 }
00333 }
00334
00335 Shape* RhinoParser::_parse_mesh(const ON_Mesh& mesh)
00336 {
00337 int fi;
00338 unsigned v1[3];
00339 unsigned v2[3];
00340
00341 const int face_count = mesh.FaceCount();
00342
00343 Surface* pSurface = new Surface(*_pSSProto,
00344 new AutoArray<Vertex3>(_get_vertices(mesh)),
00345 mesh.m_V.Count(),
00346 new AutoArray<Vector3>(_get_normals(mesh)),
00347 mesh.m_N.Count(),
00348 new AutoArray<Vector2>(_get_texture_coords(mesh)),
00349 mesh.m_T.Count(),
00350 Surface::TRIANGLES,
00351 new AutoPtr<Intersector>(new Intersector),
00352 true);
00353
00354 if (!pSurface) return NULL;
00355
00356 for (fi = 0; fi < face_count; fi++) {
00357 const ON_MeshFace& f = mesh.m_F[fi];
00358
00359 if (f.IsQuad()) {
00360
00361 if (mesh.m_V[f.vi[0]].DistanceTo(mesh.m_V[f.vi[2]]) <=
00362 mesh.m_V[f.vi[1]].DistanceTo(mesh.m_V[f.vi[3]])) {
00363 v1[0] = f.vi[0]; v1[1] = f.vi[1]; v1[2] = f.vi[2];
00364 v2[0] = f.vi[0]; v2[1] = f.vi[2]; v2[2] = f.vi[3];
00365 } else {
00366 v1[0] = f.vi[1]; v1[1] = f.vi[2]; v1[2] = f.vi[3];
00367 v2[0] = f.vi[1]; v2[1] = f.vi[3]; v2[2] = f.vi[0];
00368 }
00369 } else {
00370 v1[0] = f.vi[0]; v1[1] = f.vi[1]; v1[2] = f.vi[2];
00371 v2[0] = f.vi[0]; v2[1] = f.vi[0]; v2[2] = f.vi[0];
00372 }
00373
00374
00375 if (mesh.HasVertexNormals()) {
00376 (void) pSurface->vertex(v1[0],v1[0]);
00377 (void) pSurface->vertex(v1[1],v1[1]);
00378 (void) pSurface->vertex(v1[2],v1[2]);
00379 } else {
00380 (void) pSurface->vertex(v1[0]);
00381 (void) pSurface->vertex(v1[1]);
00382 (void) pSurface->vertex(v1[2]);
00383 }
00384
00385 if (_pStat) _pStat->primitives++;
00386
00387 if (v2[0] != v2[1]) {
00388 if (mesh.HasVertexNormals()) {
00389 (void) pSurface->vertex(v2[0],v2[0]);
00390 (void) pSurface->vertex(v2[1],v2[1]);
00391 (void) pSurface->vertex(v2[2],v2[2]);
00392 } else {
00393 (void) pSurface->vertex(v2[0]);
00394 (void) pSurface->vertex(v2[1]);
00395 (void) pSurface->vertex(v2[2]);
00396 }
00397 if (_pStat) _pStat->primitives++;
00398 }
00399 }
00400
00401 pSurface->done();
00402
00403 Shape * pPrim = new Shape(_oid++, "Polygonal Mesh");
00404 pPrim->setSharedGeometry(new AutoPtr<Geometry>(pSurface));
00405
00406 return pPrim;
00407 }
00408
00409 Shape* RhinoParser::_parse_brep(const ON_Brep& brep, int index)
00410 {
00411 if (index < 0 || index >= brep.m_F.Count()) {
00412 fprintf(stderr,"RhinoParser Error: Bad facet index in B-Rep\n");
00413 return NULL;
00414 }
00415
00416 const ON_BrepFace& face = brep.m_F[index];
00417
00418 if (face.m_si < 0 || face.m_si >= brep.m_S.Count()) {
00419 fprintf(stderr,"RhinoParser Error: Bad surface index in B-Rep\n");
00420 return NULL;
00421 } else {
00422 Shape* pPrim = new Shape(_oid++, "B-Rep");
00423 NurbsSurface* pSurface = new NurbsSurface(*_pSSProto,
00424 new AutoPtr<Intersector>(new Intersector),
00425 (ON_NurbsSurface&)*(brep.m_S[face.m_si]));
00426 pPrim->setSharedGeometry(new AutoPtr<Geometry>(pSurface));
00427 return pPrim;
00428 }
00429 }
00430
00431 void RhinoParser::_parse_object(const ON_Geometry& geom,
00432 const ON_3dmObjectAttributes& objAttr)
00433 {
00434 const ON_Point* point;
00435 const ON_PointCloud* cloud;
00436 const ON_Brep* brep;
00437 const ON_Mesh* mesh;
00438 const ON_Curve* curve;
00439 const ON_Surface* surface;
00440 const ON_NurbsSurface* nurbsSurface;
00441
00442 mesh = ON_Mesh::Cast(&geom);
00443 if (mesh) {
00444 _pParsedObject = _parse_mesh(*mesh);
00445 if (_pParsedObject)
00446 _set_material(*_pParsedObject, objAttr);
00447 return;
00448 }
00449
00450 curve = ON_Curve::Cast(&geom);
00451 if (curve) {
00452 fprintf(stderr, "RhinoParser Warning: skipping unsuported Curve\n");
00453
00454 return;
00455 }
00456
00457 nurbsSurface = ON_NurbsSurface::Cast(&geom);
00458 if (nurbsSurface) {
00459 NurbsSurface* pSurface = new NurbsSurface(*_pSSProto,
00460 new AutoPtr<Intersector>(new Intersector),
00461 *nurbsSurface);
00462 if (pSurface) {
00463 _pParsedObject = new Shape(_oid++, "NURBS Surface");
00464 _set_material(*_pParsedObject, objAttr);
00465 _pParsedObject->setSharedGeometry(new AutoPtr<Geometry>(pSurface));
00466 }
00467 return;
00468 }
00469
00470 surface = ON_Surface::Cast(&geom);
00471 if (surface) {
00472 fprintf(stderr, "RhinoParser Warning: skipping unsuported Surface\n");
00473
00474 return;
00475 }
00476
00477 brep = ON_Brep::Cast(&geom);
00478 if (brep) {
00479 #warning "TODO: Only the first surface of B-Rep is actually parsed"
00480 _pParsedObject = _parse_brep(*brep, 0);
00481 if (_pParsedObject)
00482 _set_material(*_pParsedObject, objAttr);
00483 return;
00484 }
00485
00486 point = ON_Point::Cast(&geom);
00487 if (point) {
00488 fprintf(stderr, "RhinoParser Warning: skipping unsuported Point\n");
00489
00490 return;
00491 }
00492
00493 cloud = ON_PointCloud::Cast(&geom);
00494 if (cloud) {
00495 fprintf(stderr, "RhinoParser Warning: skipping unsuported Cloud\n");
00496
00497 return;
00498 }
00499
00500 fprintf(stderr, "RhinoParser Warning: skipping unsuported unknown object\n");
00501 }
00502
00503 RhinoParser::RhinoParser(const char * path,
00504 const SDS & proto,
00505 SceneGraphObject::OID firstOID,
00506 Parser::Statistics * pStat)
00507 : Parser(path, proto, firstOID), _continueReading(false)
00508 {
00509 _pDefSpecularMat = new AutoPtr<Material>(new Specular());
00510 _pDefDiffuseMat = new AutoPtr<Material>(new Diffuse());
00511 _pDefAmbientMat = new AutoPtr<Material>(new Ambient());
00512
00513 _pDefRoughnessMat = new AutoPtr<Material>(new Roughness());
00514
00515 _pDefSpecularMat->registerReferer(this);
00516 _pDefDiffuseMat->registerReferer(this);
00517 _pDefAmbientMat->registerReferer(this);
00518
00519 _pDefRoughnessMat->registerReferer(this);
00520
00521 _pFile = new ON_BinaryFile(ON::read3dm, _workspace.OpenFile(path, "rb "));
00522
00523
00524 if (!_pFile->Read3dmStartSection(&version, startComments)) {
00525 fprintf(stderr, "RhinoParser Error: FAILURE in Read3dmStartSection().\n");
00526 return;
00527 }
00528
00529
00530 if (!_pFile->Read3dmProperties(properties)) {
00531 fprintf(stderr, "RhinoParser Error: FAILURE in Read3dmProperties().\n");
00532 return;
00533 }
00534
00535
00536 if (!_pFile->Read3dmSettings(settings)) {
00537 fprintf(stderr, "RhinoParser Error: FAILURE in Read3dmSettings().\n");
00538 return;
00539 }
00540
00541
00542 if (!_read_bitmap_table(*_pFile)) return;
00543
00544
00545 if (!_read_material_table(*_pFile)) return;
00546
00547
00548 if (!_read_layer_table(*_pFile)) return;
00549
00550
00551 if (!_read_group_table(*_pFile)) return;
00552
00553
00554 if (!_read_lights_table(*_pFile)) return;
00555
00556
00557 if (!_pFile->BeginRead3dmObjectTable()) {
00558 fprintf(stderr, "RhinoParser WARNING: Missing or corrupt object table.\n");
00559 return;
00560 }
00561
00562 _continueReading = true;
00563 }
00564
00565 RhinoParser::~RhinoParser()
00566 {
00567 AutoPtr<Material>::destroy(_pDefSpecularMat, this);
00568 AutoPtr<Material>::destroy(_pDefDiffuseMat, this);
00569 AutoPtr<Material>::destroy(_pDefAmbientMat, this);
00570
00571 AutoPtr<Material>::destroy(_pDefRoughnessMat, this);
00572
00573 for (int i = 0; i < _matTableSize; i++) {
00574 AutoPtr<Material>::destroy(_specularMatTable[i], this);
00575 AutoPtr<Material>::destroy(_diffuseMatTable[i], this);
00576 AutoPtr<Material>::destroy(_ambientMatTable[i], this);
00577
00578 AutoPtr<Material>::destroy(_roughnessMatTable[i], this);
00579 }
00580
00581 delete [] _specularMatTable;
00582 delete [] _diffuseMatTable;
00583 delete [] _ambientMatTable;
00584
00585 delete [] _roughnessMatTable;
00586 }
00587
00588 bool RhinoParser::parseObject(void)
00589 {
00590 BOOL rc;
00591 ON_3dmObjectAttributes attributes;
00592 ON_Geometry * pGeometry;
00593 ON_Object * pObject = NULL;
00594
00595 _pParsedObject = NULL;
00596
00597 if (!_continueReading) {
00598 fprintf(stderr, "RhinoParser Error: Can't continue with reading due to previous error or job finish\n");
00599 return false;
00600 }
00601
00602 while (_continueReading && !_pParsedObject) {
00603 rc = _pFile->Read3dmObject(&pObject, &attributes, _objectFilter);
00604
00605
00606 if (rc == 0) {
00607 if (!_pFile->EndRead3dmObjectTable())
00608 fprintf(stderr, "RhinoParser Error: FAILURE in EndRead3dmObjectTable().\n");
00609 _continueReading = false;
00610 continue;
00611 }
00612
00613
00614 if (rc < 0) {
00615 fprintf(stderr, "RhinoParser WARNING: Corrupt object found. Skipping rest of object table.\n");
00616 if (!_pFile->EndRead3dmObjectTable())
00617 fprintf(stderr, "RhinoParser Error: FAILURE in EndRead3dmObjectTable().\n");
00618 _continueReading = false;
00619 continue;
00620 }
00621
00622 if (pObject) {
00623
00624
00625 pGeometry = ON_Geometry::Cast(pObject);
00626 if (pGeometry) _parse_object(*pGeometry, attributes);
00627 delete pObject;
00628 pObject = NULL;
00629 } else {
00630 if (rc == 2)
00631 fprintf(stderr, "RhinoParser WARNING: Skipping object because it's filtered.\n");
00632 else if (rc == 3)
00633 fprintf(stderr, "RhinoParser WARNING: Skipping object because it's newer than this code. Update your OpenNURBS toolkit.\n");
00634 else
00635 fprintf(stderr, "RhinoParser WARNING: Skipping object for unknown reason.\n");
00636 }
00637 }
00638
00639 if (_pParsedObject) return true;
00640 else { _continueReading = false; return false; }
00641 }
00642