1 /*---------------------------------------------------------------------------*\
2 * OpenSG openNURBS loader *
5 * Copyright (C) 2007-2008 by Seac02 S.r.l. http://www.seac02.it *
6 * Copyright (C) 2008 by Patrik Mueller muellerptr@users.sourceforge.net *
7 * Copyright (C) 2008 by Akos Balazs edhellon@cs.uni-bonn.de *
9 \*---------------------------------------------------------------------------*/
10 /*---------------------------------------------------------------------------*\
13 * This library is free software; you can redistribute it and/or modify it *
14 * under the terms of the GNU Library General Public License as published *
15 * by the Free Software Foundation, version 2. *
17 * This library is distributed in the hope that it will be useful, but *
18 * WITHOUT ANY WARRANTY; without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
20 * Library General Public License for more details. *
22 * You should have received a copy of the GNU Library General Public *
23 * License along with this library; if not, write to the Free Software *
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
26 \*---------------------------------------------------------------------------*/
28 // Some portions are based on example_gl.cpp in the openNURBS distribution:
30 // Copyright (c) 1993-2007 Robert McNeel & Associates. All rights reserved.
31 // Rhinoceros is a registered trademark of Robert McNeel & Assoicates.
33 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
34 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
35 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
37 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
39 ////////////////////////////////////////////////////////////////
42 #if __GNUC__ >= 4 || __GNUC_MINOR__ >=3
43 #pragma GCC diagnostic warning "-Wold-style-cast"
44 #pragma GCC diagnostic warning "-Wignored-qualifiers"
48 #include "OSGrhino2osb.h"
49 #include <opennurbs/opennurbs.h>
50 #include <OSGSurface.h>
51 #include <OSGSwitch.h>
52 #include <OSGCoredNodePtr.h>
53 #include <OSGBaseFunctions.h>
54 //#include <OSGSimpleAttachments.h>
55 #include <OSGNameAttachment.h>
56 #include <OSGTypedGeoVectorProperty.h>
57 #include <OSGTypedGeoIntegralProperty.h>
58 #include <OSGConceptPropertyChecks.h>
60 rhino2osb::rhino2osb(int curveInterpolationSteps
,
63 bool importRenderMeshes
):
66 m_actMaterial (NULL
),
67 m_cCurrentSurface (NULL
),
68 m_bNewTrimLoop (false ),
69 m_curveInterpolationSteps(curveInterpolationSteps
),
70 m_tessellationError (tessError
),
71 m_bDoTessellation (doTessellation
),
72 m_bImportRenderMeshes (importRenderMeshes
),
75 // OpenNURBS init can be run multiple times so it should be safe here
80 rhino2osb::~rhino2osb(void)
82 // OpenNURBS deinit can be run multiple times so it should be safe here
86 // create knot vectors from the ON knot vectors for surfaces and curves
87 OSG::NodeTransitPtr
rhino2osb::convert_knots(
88 const int order
, // ON_NurbsCurve order
89 const int cv_count
, // ON_NurbsCurve cv count
90 const double *knot
, // ON_NurbsCurve knot vector
91 GLfloat
*glknot
, // GL knot vector
92 int bPermitScaling
, // TRUE if knot scaling is allowed
93 double *scale
// If not NULL and knot scaling is
94 // allowed, then the scaling
95 // parameters are returned here.
96 // glknot = (knot - scale[0])*scale[1]
99 // Because GL uses floats instead of doubles for knot vectors and
100 // because some GLs are intolerant of closely spaced knots,
101 // the returned glknots[] may be re-scaled when bPermitScaling
102 // is TRUE. When the knots belong to a trimmed surface, any rescaling
103 // done to the surface's knots must be applied to the trimming geometry.
105 const int knot_count
= order
+ cv_count
- 2;
106 const int nknots
= knot_count
+2;
108 // GL knot vectors have old-fashioned extra knot at start and end
109 const double k0
= ON_SuperfluousKnot(order
, cv_count
, knot
, 0);
110 const double k1
= ON_SuperfluousKnot(order
, cv_count
, knot
, 1);
122 double d0
= knot
[order
-2];
131 for(i
= 1; i
< knot_count
; i
++)
133 d
= knot
[i
] - knot
[i
-1];
136 continue; // multiple knot
143 if(dmin
> 0.0 && dmax
>= dmin
)
149 else if(dmax
> 1.0e4
)
151 if(1.0e4
* dmin
>= 1.0e-2 * dmax
)
163 glknot
[0] = GLfloat((k0
- d0
) * dk
);
165 for(i
= 1, j
= 0; j
< knot_count
; i
++, j
++)
166 glknot
[i
] = GLfloat((knot
[j
] - d0
) * dk
);
168 glknot
[nknots
- 1] = GLfloat((k1
- d0
) * dk
);
172 glknot
[0] = GLfloat(k0
);
174 for(i
= 1, j
= 0; j
< knot_count
; i
++, j
++)
175 glknot
[i
] = GLfloat(knot
[j
]);
177 glknot
[nknots
- 1] = GLfloat(k1
);
180 return OSG::NodeTransitPtr(NULL
);
183 static void GetGLCV( const int dim
,
191 const double x
= cv
[0];
192 const double y
= cv
[1];
193 const double z
= (dim
== 3) ? cv
[2] : 0.0;
194 const double w
= (is_rat
) ? cv
[dim
] : 1.0;
196 glcv
[0] = GLfloat(xform
[0][0] * x
+
201 glcv
[1] = GLfloat(xform
[1][0] * x
+
208 glcv
[2] = GLfloat(xform
[2][0] * x
+
216 glcv
[dim
] = GLfloat(xform
[3][0] * x
+
224 glcv
[0] = GLfloat(cv
[0]);
225 glcv
[1] = GLfloat(cv
[1]);
228 glcv
[2] = GLfloat(cv
[2]);
231 glcv
[dim
] = GLfloat(cv
[dim
]);
235 OSG::NodeTransitPtr
rhino2osb::process_curve(const ON_Curve
&curve
,
238 const ON_PolyCurve
*poly_curve
= ON_PolyCurve::Cast(&curve
);
240 if(poly_curve
!= NULL
)
242 ON_Curve
*pSegmentCurve
= 0;
243 int segment_count
= poly_curve
->Count();
246 for(i
= 0; i
< segment_count
; i
++)
248 pSegmentCurve
= poly_curve
->SegmentCurve(i
);
250 if(pSegmentCurve
!= NULL
)
251 process_curve(*pSegmentCurve
, xform
);
254 return OSG::NodeTransitPtr(NULL
);
257 const ON_CurveProxy
*curve_proxy
= ON_CurveProxy::Cast(&curve
);
259 if(curve_proxy
!= NULL
&& !curve_proxy
->ProxyCurveIsReversed())
261 const ON_Curve
*real_curve
= curve_proxy
->ProxyCurve();
264 return OSG::NodeTransitPtr(NULL
);
266 if(curve_proxy
== real_curve
)
267 return OSG::NodeTransitPtr(NULL
);
269 if(curve_proxy
->ProxyCurveDomain() == real_curve
->Domain())
271 // printf("found proxy curve\n");
272 return process_curve(*real_curve
, xform
);
277 const ON_NurbsCurve
*nurbs_curve
= ON_NurbsCurve::Cast(&curve
);
281 if(curve
.GetNurbForm(tmp
))
287 printf("Failed to get nurbs form of curve\n");
288 return OSG::NodeTransitPtr(NULL
);
293 return process_trimcurve(nurbs_curve
->Dimension (),
294 nurbs_curve
->IsRational(),
295 nurbs_curve
->Order (),
296 nurbs_curve
->CVCount (),
297 nurbs_curve
->Knot (),
298 nurbs_curve
->m_cv_stride
,
306 OSG::NodeTransitPtr
rhino2osb::process_trimcurve(
311 const double *knot_vector
,
314 int bPermitKnotScaling
,
318 std::vector
<OSG::Real64
> knotv
;
319 std::vector
<OSG::Pnt3f
> cps
;
323 // GL knot count = TL knot count + 2
324 GLint nknots
= nurb_order
+ cv_count
;
325 GLfloat
*knot
= static_cast<GLfloat
*>(onmalloc(nknots
* sizeof(*knot
)));
327 convert_knots(nurb_order
,
332 dbg_ks
);//knot_scale );
335 GLint stride
= cv_stride
;
337 static_cast<GLfloat
*>(onmalloc(stride
* cv_count
* sizeof(*ctlarray
)));
339 // printf("trim dim: %d is_rat: %d stride: %d order: %d\n", dim, is_rat,
340 // stride, nurb_order);
342 for(i
= 0; i
< cv_count
; i
++)
344 GetGLCV(dim
, is_rat
, cv
+ i
* cv_stride
, xform
, ctlarray
+ stride
* i
);
347 // fill OpenSG structure
348 for(i
= 0; i
< cv_count
; i
++)
354 actcp
[0] = *(ctlarray
+ i
* stride
+ 0);
355 actcp
[1] = *(ctlarray
+ i
* stride
+ 1);
356 actcp
[2] = *(ctlarray
+ i
* stride
+ 2);
360 actcp
[0] = *(ctlarray
+ i
* stride
+ 0);
361 actcp
[1] = *(ctlarray
+ i
* stride
+ 1);
365 cps
.push_back(actcp
);
367 // printf( "trim ctrl %f %f %f\n", actcp[0], actcp[1], actcp[2] );
370 for(i
= 0; i
< nknots
; ++i
)
372 // fill OpenSG structure
373 knotv
.push_back(knot
[i
]);
374 // printf( "trim knot %f\n", knot[i] );
377 if(m_cCurrentSurface
!= NULL
)
379 // printf( "dimension: %d order: %d\n", dim, nurb_order );
380 OSG_ASSERT(knotv
.size() == cps
.size() + nurb_order
);
383 m_cCurrentSurface
->addCurve(nurb_order
-1, knotv
, cps
, m_bNewTrimLoop
);
385 m_bNewTrimLoop
= false; // next curve will be in the same curveloop,
386 // if not the caller will set it to true
393 return OSG::NodeTransitPtr(NULL
);
396 /* Here's the essence! */
397 OSG::NodeTransitPtr
rhino2osb::convert_surface_to_osg(
398 const ON_NurbsSurface
&sOrig
,
402 ON_NurbsSurface s
= sOrig
;
405 // const int cv_size = s.CVSize();
406 const int cv_count
[2] = {s
.CVCount(0), s
.CVCount(1)};
408 OSG::SurfaceUnrecPtr surface
;
410 OSG::NodeTransitPtr ret
=
411 OSG::makeCoredNode
<OSG::Surface
>(&surface
);
413 OSG::GeoPnt4fPropertyUnrecPtr cps4
;
414 OSG::GeoPnt3fPropertyUnrecPtr cps3
;
416 m_cCurrentSurface
= surface
;
418 const bool isRational
= s
.IsRational();
422 cps4
= OSG::GeoPnt4fProperty::create();
427 for(int i
= 0; i
< cv_count
[0]; i
++)
429 for(int j
= 0; j
< cv_count
[1]; j
++)
431 ON_4dPoint tmpON_Point
;
433 bool success
= s
.GetCV(i
, j
, tmpON_Point
) != 0;
434 //printf("i%d j: %d on_point: %f %f %f %f\n", i, j,
435 //tmpON_Point.x, tmpON_Point.y, tmpON_Point.z,
437 //tmpON_Point.w = 1.0;
441 cps4
->editFieldPtr()->push_back(OSG::Pnt4f(tmpON_Point
.x
,
451 cps3
= OSG::GeoPnt3fProperty::create();
456 for(int i
= 0; i
< cv_count
[0]; i
++)
458 for(int j
= 0; j
< cv_count
[1]; j
++)
460 ON_4dPoint tmpON_Point
;
462 bool success
= s
.GetCV(i
, j
, tmpON_Point
) != 0;
465 //printf("i%d j: %d on_point: %f %f %f %f\n", i, j,
466 //tmpON_Point.x, tmpON_Point.y, tmpON_Point.z,
471 if(tmpON_Point
.w
!= 0.0)
473 weight
= 1.0/tmpON_Point
.w
;
476 OSG::Pnt3f
thePoint(tmpON_Point
.x
*weight
,
477 tmpON_Point
.y
*weight
,
478 tmpON_Point
.z
*weight
);
480 cps3
->editFieldPtr()->push_back(thePoint
);
486 int nControl
= cv_count
[0]*cv_count
[1];
487 GLint sknot_count
= s
.KnotCount(0) + 2;
488 GLint tknot_count
= s
.KnotCount(1) + 2;
490 GLint orderU
, orderV
;
495 if((sknot_count
-orderU
)*(tknot_count
-orderV
) != nControl
)
497 printf( "inconsistent control points\n" );
498 return OSG::NodeTransitPtr(NULL
);
502 // let's clear the trimming
503 surface
->removeCurves();
505 // set up dimensions and knot vectors:
506 surface
->setDimU(orderU
- 1);
507 surface
->setDimV(orderV
- 1);
509 surface
->editMFKnotsU()->clear();
510 surface
->editMFKnotsV()->clear();
512 for(int i
= 0; i
< sknot_count
; ++i
)
514 surface
->editMFKnotsU()->push_back(sknot
[i
]);
515 // printf( "knot s %f\n", (float)sknot[i] );
518 for(int i
= 0; i
< tknot_count
; ++i
)
520 surface
->editMFKnotsV()->push_back(tknot
[i
]);
521 // printf( "knot t %f\n", (float)tknot[i] );
524 // set control points
526 surface
->setControlPoints(cps4
);
528 surface
->setControlPoints(cps3
);
531 surface
->setError(m_tessellationError
);
533 // and finally set the material
534 surface
->setMaterial(m_actMaterial
);
540 // See comments in opennurbs_gl.h for calling instructions.
541 OSG::NodeTransitPtr
rhino2osb::process_NURBS_surface(
542 const ON_NurbsSurface
&sOrig
,
543 int bPermitKnotScaling
,
549 ON_NurbsSurface s
= sOrig
;
560 // The "bPermitScaling" parameters to the ON_GL() call that
561 // fills in the knot vectors is set to FALSE because any
562 // rescaling that is applied to a surface domain must also
563 // be applied to parameter space trimming curve geometry.
566 GLint sknot_count
= s
.KnotCount(0) + 2;
567 GLfloat
*sknot
= static_cast<GLfloat
*>(onmalloc(sknot_count
* sizeof(*sknot
)));
569 convert_knots(s
.Order (0),
577 GLint tknot_count
= s
.KnotCount(1) + 2;
578 GLfloat
*tknot
= static_cast<GLfloat
*>(onmalloc(tknot_count
* sizeof(*tknot
)));
580 convert_knots(s
.Order (1),
588 const int cv_size
= s
.CVSize();
589 const int cv_count
[2] = {s
.CVCount(0), s
.CVCount(1)};
591 GLint s_stride
= cv_size
* cv_count
[1];
592 GLint t_stride
= cv_size
;
594 GLfloat
*ctlarray
= static_cast<GLfloat
*>(onmalloc(
595 s_stride
* cv_count
[0] * sizeof(*ctlarray
)));
597 for(i
= 0; i
< cv_count
[0]; i
++)
599 for(j
= 0; j
< cv_count
[1]; j
++)
601 const double *cv
= s
.CV(i
,j
);
603 GLfloat
*gl_cv
= ctlarray
+ s_stride
* i
+ t_stride
* j
;
605 for(k
= 0; k
< cv_size
; k
++)
607 gl_cv
[k
] = GLfloat(cv
[k
]);
612 // GLint sorder = s.Order(0);
613 // GLint torder = s.Order(1);
616 // instead of calling gluNurbsSurface, try to convert the nurbs into
618 OSG::NodeTransitPtr ret
= convert_surface_to_osg(s
, sknot
, tknot
);
627 OSG::NodeTransitPtr
rhino2osb::process_brep(const ON_Brep
&brep
)
629 const int face_count
= brep
.m_F
.Count();
632 OSG::NodeTransitPtr child
, parent
= OSG::makeCoredNode
<OSG::Group
>();
635 //printf("brep face count: %d\n", face_count);
636 for(face_index
= 0; face_index
< face_count
; face_index
++)
638 const ON_BrepFace
&face
= brep
.m_F
[face_index
];
640 child
= process_brepface(face
);
644 parent
->addChild(child
);
652 void rhino2osb::doTess(OSG::Node
*node
)
654 if(m_bDoTessellation
== false)
659 OSG::Surface
*surf
= dynamic_cast<OSG::Surface
*>(node
->getCore());
663 // so that all the dirty flags are up-to-date
664 OSG::commitChanges();
666 // printf("tess start\n");
667 surf
->forceTessellate();
669 // printf("tess end\n");
670 unsigned int numtris
= surf
->getIndices()->size32();
672 OSG::osgSinkUnusedWarning(numtris
);
674 // printf("number of tris: %d\n", numtris);
678 OSG::NodeTransitPtr
rhino2osb::process_brepface(const ON_BrepFace
&face
)
680 OSG::NodeUnrecPtr
ret(NULL
);
682 const ON_Mesh
*mesh
= NULL
;
684 mesh
= face
.Mesh(ON::render_mesh
);
688 // use saved render mesh
689 //printf("Found mesh associated with brepface, ignoring\n");
690 if(m_bImportRenderMeshes
== true)
691 return process_mesh(mesh
);
694 // convert to OpenSG struct
695 double knot_scale
[2][2] = {{0.0,1.0}, {0.0,1.0}};
697 const ON_Brep
*brep
= face
.Brep();
701 printf("Invalid brep for brepface\n");
702 return OSG::NodeTransitPtr(ret
);
706 ON_NurbsSurface tmp_nurbssrf
;
707 const ON_Surface
*srf
= brep
->m_S
[face
.m_si
];
708 const ON_NurbsSurface
*nurbs_srf
= ON_NurbsSurface::Cast(srf
);
712 // attempt to get NURBS form of this surface
713 if(srf
->GetNurbForm(tmp_nurbssrf
))
714 nurbs_srf
= &tmp_nurbssrf
;
719 printf("NURBS surface of face is invalid\n");
720 return OSG::NodeTransitPtr(ret
);
723 ret
= process_NURBS_surface( *nurbs_srf
, true, knot_scale
[0], knot_scale
[1]);
725 if(brep
->FaceIsSurface(face
.m_face_index
))
727 //printf("trivially trimmed face\n");
729 return OSG::NodeTransitPtr(ret
); // face is trivially trimmed
732 int fli
, li
, lti
, ti
;
734 // any knot scaling applied to the surface must also be applied to
735 // the parameter space trimming geometry
737 { {knot_scale
[0][1], 0.0, 0.0, -knot_scale
[0][0]*knot_scale
[0][1]},
738 {0.0, knot_scale
[1][1], 0.0, -knot_scale
[1][0]*knot_scale
[1][1]},
739 {0.0, 0.0, 1.0, 0.0},
743 // Add face's 2d trimming loop(s)
744 const int face_loop_count
= face
.m_li
.Count();
746 for(fli
= 0; fli
< face_loop_count
; fli
++)
750 const ON_BrepLoop
&loop
= brep
->m_L
[li
];
751 const int loop_trim_count
= loop
.m_ti
.Count();
753 // set flag for opensg trimming semantics
754 m_bNewTrimLoop
= true;
756 for(lti
= 0; lti
< loop_trim_count
; lti
++)
760 const ON_BrepTrim
&trim
= brep
->m_T
[ti
];
763 // printf("converting loop: %d curve: %d\n", fli, lti);
764 process_curve(trim
, xform
);
768 // if not trivially trimmed, only tessellate after the trimcurves have been added
771 return OSG::NodeTransitPtr(ret
);
774 OSG::NodeTransitPtr
rhino2osb::process_surface(const ON_Surface
&surface
)
777 const ON_NurbsSurface
*nurbs_surface
;
779 nurbs_surface
= ON_NurbsSurface::Cast(&surface
);
783 if(surface
.GetNurbForm(tmp
))
785 nurbs_surface
= &tmp
;
789 printf("Unable to get NURBS representation of surface\n");
790 return OSG::NodeTransitPtr(NULL
);
796 // if it's not a brepface, it can't be trimmed
797 OSG::NodeUnrecPtr
ret(NULL
);
799 ret
= process_NURBS_surface(*nurbs_surface
, true);
803 return OSG::NodeTransitPtr(ret
);
806 return OSG::NodeTransitPtr(NULL
);
809 void rhino2osb::process_material(const ONX_Model
&model
, int index
)
812 // debug checks for material
814 ON_3dmObjectAttributes on_attr = model.m_object_table[index].m_attributes;
815 int material_index = -1;
816 if (on_attr.MaterialSource() == ON::material_from_layer )
818 printf("material is from layer attribs\n");
819 if ( on_attr.m_layer_index >= 0 &&
820 on_attr.m_layer_index < model.m_layer_table.Count() )
822 material_index = model.m_layer_table[on_attr.m_layer_index].RenderMaterialIndex();
825 else if (on_attr.MaterialSource() == ON::material_from_object )
827 printf("material is from object\n");
829 else if (on_attr.MaterialSource() == ON::material_from_parent )
831 printf("material is from parent\n");
835 printf("unknown material attrib: %x\n", on_attr.MaterialSource());
837 printf("material index: %d\n", material_index);
839 const ONX_Model_Object
&mo
= model
.m_object_table
[index
];
840 const ON_Object
*geometry
= mo
.m_object
;
842 // we have to check if it's a curve and adjust its material accordingly
843 const ON_Curve
*curve
= NULL
;
846 model
.GetRenderMaterial(mo
.m_attributes
, mat
);
848 std::map
<int, OSG::SimpleMaterialUnrecPtr
>::iterator it
=
849 m_materials
.find(mat
.MaterialIndex());
851 if(it
!= m_materials
.end())
853 m_actMaterial
= (*it
).second
;
858 curve
= ON_Curve::Cast(geometry
);
862 ON_Color c
= model
.WireframeColor( mo
.m_attributes
);
864 ON_Color
black(0,0,0);
867 mat
.SetAmbient (black
);
868 mat
.SetDiffuse (black
);
869 mat
.SetSpecular(black
);
873 m_actMaterial
= OSG::SimpleMaterial::create();
876 actcol
= mat
.Diffuse();
877 m_actMaterial
->setDiffuse(OSG::Color3f(actcol
.FractionRed (),
878 actcol
.FractionGreen(),
879 actcol
.FractionBlue ()));
881 actcol
= mat
.Ambient();
882 m_actMaterial
->setAmbient(OSG::Color3f(actcol
.FractionRed (),
883 actcol
.FractionGreen(),
884 actcol
.FractionBlue ()));
885 actcol
= mat
.Emission();
886 m_actMaterial
->setEmission(OSG::Color3f(actcol
.FractionRed (),
887 actcol
.FractionGreen(),
888 actcol
.FractionBlue ()));
889 actcol
= mat
.Specular();
890 m_actMaterial
->setSpecular(OSG::Color3f(actcol
.FractionRed (),
891 actcol
.FractionGreen(),
892 actcol
.FractionBlue ()));
894 // dunno why it's done this way, but this is how the Rhino GL example
895 // gets sort of okay lighting
896 if(mat
.Shine() < ON_EPSILON
)
898 m_actMaterial
->setSpecular(OSG::Color3f(0.0f
, 0.0f
, 0.0f
));
901 m_actMaterial
->setShininess(128.0 * (mat
.Shine() / ON_Material::MaxShine()));
903 m_actMaterial
->setTransparency(mat
.Transparency());
906 ON_String mat_name
= mat
.m_material_name
;
908 if(mat_name
.Array() != NULL
)
909 OSG::setName(m_actMaterial
, mat_name
.Array());
911 m_materials
.insert(std::make_pair(mat
.MaterialIndex(), m_actMaterial
));
913 //m_actMaterial->dump();
916 OSG::NodeTransitPtr
rhino2osb::buildNode(const ONX_Model
&model
, int index
)
918 // Called from myDisplay() to show geometry.
919 // Uses ON_GL() functions found in rhinoio_gl.cpp.
920 const ON_Point
*point
= NULL
;
921 const ON_PointCloud
*cloud
= NULL
;
922 const ON_PointGrid
*grid
= NULL
;
923 const ON_Brep
*brep
= NULL
;
924 const ON_Mesh
*mesh
= NULL
;
925 const ON_Curve
*curve
= NULL
;
926 const ON_Surface
*surface
= NULL
;
927 const ONX_Model_Object
&mo
= model
.m_object_table
[index
];
928 const ON_Object
*geometry
= mo
.m_object
;
932 return OSG::NodeTransitPtr(NULL
);
935 brep
= ON_Brep::Cast(geometry
);
939 //printf("found brep\n");
940 process_material(model
, index
);
942 return process_brep(*brep
);
945 mesh
= ON_Mesh::Cast(geometry
);
949 //printf("found mesh\n");
950 process_material(model
, index
);
952 return process_mesh(mesh
);
955 // curve = ON_Curve::Cast(geometry);
958 // printf("found curve\n");
959 // process_material(model, index);
960 // return process_curve( *curve, 0 );
963 surface
= ON_Surface::Cast(geometry
);
967 //printf("found surface\n");
968 process_material(model
, index
);
970 return process_surface( *surface
);
973 point
= ON_Point::Cast(geometry
);
977 //printf("found point\n");
978 process_material(model
, index
);
980 return process_point(point
);
983 cloud
= ON_PointCloud::Cast(geometry
);
987 //printf("found pointcloud\n");
988 process_material(model
, index
);
990 return process_pointcloud(cloud
);
993 grid
= ON_PointGrid::Cast(geometry
);
997 //printf("found pointgrid\n");
998 process_material(model
, index
);
999 return process_pointgrid(grid
);
1002 curve
= ON_Curve::Cast(geometry
);
1006 //printf("found curve\n");
1007 process_material(model
, index
);
1008 return process_curve(curve
);
1011 printf("found unkown object\n");
1012 return OSG::NodeTransitPtr(NULL
);
1015 OSG::NodeTransitPtr
rhino2osb::process_point(const ON_Point
*theGeometry
)
1017 return process_points(theGeometry
);
1020 OSG::NodeTransitPtr
rhino2osb::process_pointcloud(const ON_PointCloud
*theGeometry
)
1022 return process_points(theGeometry
);
1025 OSG::NodeTransitPtr
rhino2osb::process_pointgrid(const ON_PointGrid
*theGeometry
)
1027 return process_points(theGeometry
);
1031 OSG::NodeTransitPtr
rhino2osb::process_points(const ON_Geometry
*theGeometry
)
1033 OSG::NodeTransitPtr
result(NULL
);
1035 if(theGeometry
!= NULL
)
1037 const ON_Point
*thePoint
= ON_Point ::Cast(theGeometry
);
1038 const ON_PointCloud
*theCloud
= ON_PointCloud::Cast(theGeometry
);
1039 const ON_PointGrid
*theGrid
= ON_PointGrid ::Cast(theGeometry
);
1043 if(NULL
!= thePoint
)
1045 else if(NULL
!= theCloud
)
1046 nbPoints
= theCloud
->m_P
.Count();
1047 else if(NULL
!= theGrid
)
1048 nbPoints
= theGrid
->PointCount(0) * theGrid
->PointCount(1);
1052 OSG::GeometryUnrecPtr geom
;
1054 OSG::GeoPnt3fPropertyUnrecPtr points
;
1055 OSG::GeoUInt32PropertyUnrecPtr lens
;
1056 OSG::GeoUInt8PropertyUnrecPtr type
;
1058 geom
= OSG::Geometry ::create();
1059 points
= OSG::GeoPnt3fProperty::create();
1061 lens
= OSG::GeoUInt32Property::create();
1062 type
= OSG::GeoUInt8Property ::create();
1064 // set the points and normals
1065 OSG::GeoVec3fPropertyUnrecPtr norms
;
1067 if(NULL
!= thePoint
)
1069 type
->addValue(GL_POINTS
);
1071 points
->addValue(OSG::Pnt3f(thePoint
->point
.x
,
1073 thePoint
->point
.z
));
1075 else if(NULL
!= theCloud
)
1077 for(int i
= 0; i
< nbPoints
; i
++)
1079 type
->addValue(GL_POINT
);
1082 const ON_3dPoint
*tmpPoint
= theCloud
->m_P
.At(i
);
1084 points
->addValue(OSG::Pnt3f(tmpPoint
->x
, tmpPoint
->y
, tmpPoint
->z
));
1087 else if (NULL
!= theGrid
)
1089 for(long i
= 0; i
< theGrid
->PointCount(0); i
++)
1091 for(long j
= 0; j
< theGrid
->PointCount(1); j
++)
1093 type
->addValue(GL_POINT
);
1096 const ON_3dPoint
&tmpPoint
= theGrid
->Point(i
,j
);
1098 points
->addValue(OSG::Pnt3f(tmpPoint
.x
, tmpPoint
.y
, tmpPoint
.z
));
1105 geom
->setTypes (type
);
1106 geom
->setLengths (lens
);
1107 geom
->setPositions(points
);
1108 geom
->setMaterial (m_actMaterial
);
1111 result
= OSG::makeCoredNode
<OSG::Geometry
>(&geom
);
1119 OSG::NodeTransitPtr
rhino2osb::process_curve(const ON_Geometry
*theGeometry
)
1121 if(theGeometry
!= NULL
)
1123 const ON_Curve
*theCurve
= ON_Curve::Cast(theGeometry
);
1125 if(theCurve
!= NULL
)
1127 if(theCurve
->IsValid())
1129 const ON_LineCurve
*lineCurve
= ON_LineCurve::Cast(theCurve
);
1132 return process_linecurve(lineCurve
);
1134 const ON_PolylineCurve
*polylineCurve
= ON_PolylineCurve::Cast(theCurve
);
1137 return process_polylinecurve(polylineCurve
);
1139 const ON_NurbsCurve
*actNurbsCurve
= ON_NurbsCurve::Cast(theCurve
);
1142 return process_nurbscurve(actNurbsCurve
);
1144 actNurbsCurve
= theCurve
->NurbsCurve();
1147 return process_curve(actNurbsCurve
);
1152 return OSG::NodeTransitPtr(NULL
);
1155 OSG::NodeTransitPtr
rhino2osb::process_nurbscurve(const ON_NurbsCurve
*theGeometry
)
1157 OSG::NodeTransitPtr
result(NULL
);
1159 if(theGeometry
!= NULL
)
1161 result
= OSG::Node::create();
1163 ON_Interval startEnd
= theGeometry
->Domain();
1166 const double length
= OSG::osgAbs(startEnd
.m_t
[1] - startEnd
.m_t
[0]);
1167 const double step
= length
/ m_curveInterpolationSteps
;
1169 OSG::GeoPnt3fPropertyUnrecPtr points
;
1170 OSG::GeoUInt32PropertyUnrecPtr lens
;
1171 OSG::GeoUInt8PropertyUnrecPtr type
;
1173 OSG::GeometryUnrecPtr geom
= OSG::Geometry::create();
1175 points
= OSG::GeoPnt3fProperty ::create();
1176 lens
= OSG::GeoUInt32Property::create();
1177 type
= OSG::GeoUInt8Property ::create();
1182 ON_3dPoint tmpPoint
;
1184 for(double i
= startEnd
.m_t
[0]; i
<= startEnd
.m_t
[1]; i
+= step
)
1186 if(theGeometry
->EvPoint(i
, tmpPoint
))
1188 points
->addValue(OSG::Pnt3f(tmpPoint
.x
, tmpPoint
.y
, tmpPoint
.z
));
1193 if(theGeometry
->IsClosed())
1195 if (theGeometry
->EvPoint(startEnd
.m_t
[0], tmpPoint
))
1197 points
->addValue(OSG::Pnt3f(tmpPoint
.x
, tmpPoint
.y
, tmpPoint
.z
));
1202 type
->addValue(GL_LINE_STRIP
);
1203 lens
->addValue(nbPoints
);
1205 geom
->setTypes (type
);
1206 geom
->setLengths (lens
);
1207 geom
->setPositions(points
);
1208 geom
->setMaterial (m_actMaterial
);
1210 result
->setCore(geom
);
1216 OSG::NodeTransitPtr
rhino2osb::process_polylinecurve(const ON_PolylineCurve
* theGeometry
)
1218 OSG::NodeTransitPtr
result(NULL
);
1220 if(theGeometry
!= NULL
)
1222 OSG::GeoPnt3fPropertyUnrecPtr points
;
1223 OSG::GeoUInt32PropertyUnrecPtr lens
;
1224 OSG::GeoUInt8PropertyUnrecPtr type
;
1226 result
= OSG::Node::create();
1228 OSG::GeometryUnrecPtr geom
= OSG::Geometry::create();
1230 points
= OSG::GeoPnt3fProperty ::create();
1231 lens
= OSG::GeoUInt32Property::create();
1232 type
= OSG::GeoUInt8Property ::create();
1234 int nbPoints
= theGeometry
->PointCount();
1237 for(int i
= 0; i
< nbPoints
; i
++)
1239 const ON_3dPoint
*tmpPoint
= theGeometry
->m_pline
.At(i
);
1241 points
->addValue(OSG::Pnt3f(tmpPoint
->x
, tmpPoint
->y
, tmpPoint
->z
));
1244 if(theGeometry
->IsClosed())
1246 const ON_3dPoint
* tmpPoint
= theGeometry
->m_pline
.At(0);
1248 points
->addValue(OSG::Pnt3f(tmpPoint
->x
, tmpPoint
->y
, tmpPoint
->z
));
1252 type
->addValue(GL_LINE_STRIP
);
1253 lens
->addValue(nbPoints
);
1255 geom
->setTypes (type
);
1256 geom
->setLengths (lens
);
1257 geom
->setPositions(points
);
1258 geom
->setMaterial (m_actMaterial
);
1260 result
->setCore(geom
);
1267 OSG::NodeTransitPtr
rhino2osb::process_linecurve(const ON_LineCurve
*theGeometry
)
1269 OSG::NodeTransitPtr
result(NULL
);
1271 if(theGeometry
!= NULL
)
1273 result
= OSG::Node::create();
1275 OSG::GeoPnt3fPropertyUnrecPtr points
;
1276 OSG::GeoUInt32PropertyUnrecPtr lens
;
1277 OSG::GeoUInt8PropertyUnrecPtr type
;
1279 OSG::GeometryUnrecPtr geom
= OSG::Geometry::create();
1281 points
= OSG::GeoPnt3fProperty ::create();
1282 lens
= OSG::GeoUInt32Property::create();
1283 type
= OSG::GeoUInt8Property ::create();
1285 // set the points and normals
1287 points
->addValue(OSG::Pnt3f(theGeometry
->m_line
.from
.x
,
1288 theGeometry
->m_line
.from
.y
,
1289 theGeometry
->m_line
.from
.z
));
1291 points
->addValue(OSG::Pnt3f(theGeometry
->m_line
.to
.x
,
1292 theGeometry
->m_line
.to
.y
,
1293 theGeometry
->m_line
.to
.z
));
1295 type
->addValue(GL_LINES
);
1298 geom
->setTypes (type
);
1299 geom
->setLengths (lens
);
1300 geom
->setPositions(points
);
1301 geom
->setMaterial (m_actMaterial
);
1303 result
->setCore(geom
);
1309 OSG::NodeTransitPtr
rhino2osb::process_mesh(const ON_Mesh
*theMesh
)
1311 OSG::NodeTransitPtr
result(NULL
);
1316 const int face_count
= theMesh
->FaceCount();
1321 result
= OSG::Node::create();
1323 OSG::GeometryUnrecPtr geo
= OSG::Geometry::create();
1325 result
->setCore(geo
);
1327 const bool bHasNormals
= theMesh
->HasVertexNormals ();
1328 const bool bHasTCoords
= theMesh
->HasTextureCoordinates();
1330 OSG::GeoPnt3fPropertyUnrecPtr points
= OSG::GeoPnt3fProperty::create();
1331 OSG::GeoVec3fPropertyUnrecPtr normals
= NULL
;
1334 normals
= OSG::GeoVec3fProperty::create();
1336 OSG::GeoVec2fPropertyUnrecPtr texcoords
= NULL
;
1339 texcoords
= OSG::GeoVec2fProperty::create();
1342 int i0
, i1
, i2
, j0
, j1
, j2
;
1348 for(int fi
= 0; fi
< face_count
; ++fi
)
1350 const ON_MeshFace
&f
= theMesh
->m_F
[fi
];
1352 v
[0] = theMesh
->m_V
[f
.vi
[0]];
1353 v
[1] = theMesh
->m_V
[f
.vi
[1]];
1354 v
[2] = theMesh
->m_V
[f
.vi
[2]];
1358 n
[0] = theMesh
->m_N
[f
.vi
[0]];
1359 n
[1] = theMesh
->m_N
[f
.vi
[1]];
1360 n
[2] = theMesh
->m_N
[f
.vi
[2]];
1365 t
[0] = theMesh
->m_T
[f
.vi
[0]];
1366 t
[1] = theMesh
->m_T
[f
.vi
[1]];
1367 t
[2] = theMesh
->m_T
[f
.vi
[2]];
1372 // quadrangle - render as two triangles
1373 v
[3] = theMesh
->m_V
[f
.vi
[3]];
1376 n
[3] = theMesh
->m_N
[f
.vi
[3]];
1379 t
[3] = theMesh
->m_T
[f
.vi
[3]];
1381 if(v
[0].DistanceTo(v
[2]) <= v
[1].DistanceTo(v
[3]))
1383 i0
= 0; i1
= 1; i2
= 2;
1384 j0
= 0; j1
= 2; j2
= 3;
1388 i0
= 1; i1
= 2; i2
= 3;
1389 j0
= 1; j1
= 3; j2
= 0;
1397 i0
= 0; i1
= 1; i2
= 2;
1404 points
->editFieldPtr()->push_back(OSG::Pnt3f(v
[i0
].x
, v
[i0
].y
, v
[i0
].z
));
1405 points
->editFieldPtr()->push_back(OSG::Pnt3f(v
[i1
].x
, v
[i1
].y
, v
[i1
].z
));
1406 points
->editFieldPtr()->push_back(OSG::Pnt3f(v
[i2
].x
, v
[i2
].y
, v
[i2
].z
));
1410 normals
->editFieldPtr()->push_back(OSG::Vec3f(n
[i0
].x
, n
[i0
].y
, n
[i0
].z
));
1411 normals
->editFieldPtr()->push_back(OSG::Vec3f(n
[i1
].x
, n
[i1
].y
, n
[i1
].z
));
1412 normals
->editFieldPtr()->push_back(OSG::Vec3f(n
[i2
].x
, n
[i2
].y
, n
[i2
].z
));
1417 texcoords
->editFieldPtr()->push_back(OSG::Vec2f(t
[i0
].x
, t
[i0
].y
));
1418 texcoords
->editFieldPtr()->push_back(OSG::Vec2f(t
[i1
].x
, t
[i1
].y
));
1419 texcoords
->editFieldPtr()->push_back(OSG::Vec2f(t
[i2
].x
, t
[i2
].y
));
1424 // if we have a quad, second triangle
1425 points
->editFieldPtr()->push_back(OSG::Pnt3f(v
[j0
].x
, v
[j0
].y
, v
[j0
].z
));
1426 points
->editFieldPtr()->push_back(OSG::Pnt3f(v
[j1
].x
, v
[j1
].y
, v
[j1
].z
));
1427 points
->editFieldPtr()->push_back(OSG::Pnt3f(v
[j2
].x
, v
[j2
].y
, v
[j2
].z
));
1431 normals
->editFieldPtr()->push_back(OSG::Vec3f(n
[j0
].x
, n
[j0
].y
, n
[j0
].z
));
1432 normals
->editFieldPtr()->push_back(OSG::Vec3f(n
[j1
].x
, n
[j1
].y
, n
[j1
].z
));
1433 normals
->editFieldPtr()->push_back(OSG::Vec3f(n
[j2
].x
, n
[j2
].y
, n
[j2
].z
));
1438 texcoords
->editFieldPtr()->push_back(OSG::Vec2f(t
[j0
].x
, t
[j0
].y
));
1439 texcoords
->editFieldPtr()->push_back(OSG::Vec2f(t
[j1
].x
, t
[j1
].y
));
1440 texcoords
->editFieldPtr()->push_back(OSG::Vec2f(t
[j2
].x
, t
[j2
].y
));
1445 int nv
= tri_count
* 3;
1447 OSG::GeoUInt32PropertyUnrecPtr lengths
= OSG::GeoUInt32Property::create();
1448 OSG::GeoUInt8PropertyUnrecPtr types
= OSG::GeoUInt8Property ::create();
1449 OSG::GeoUInt32PropertyUnrecPtr indices
= OSG::GeoUInt32Property::create();
1451 lengths
->push_back(nv
);
1452 types
->push_back (GL_TRIANGLES
);
1454 indices
->editFieldPtr()->reserve(nv
);
1456 for(int i
= 0; i
< nv
; ++i
)
1457 indices
->editFieldPtr()->push_back(i
);
1459 geo
->setMaterial (m_actMaterial
);
1461 geo
->setPositions(points
);
1462 geo
->setIndex (indices
,
1463 OSG::Geometry::PositionsIndex
);
1467 geo
->setNormals(normals
);
1468 geo
->setIndex (indices
,
1469 OSG::Geometry::NormalsIndex
);
1472 if(texcoords
!= NULL
)
1474 geo
->setTexCoords(texcoords
);
1475 geo
->setIndex (indices
,
1476 OSG::Geometry::TexCoordsIndex
);
1479 geo
->setLengths(lengths
);
1480 geo
->setTypes (types
);
1486 OSG::NodeTransitPtr
rhino2osb::load(const OSG::Char8
*fileName
)
1488 OSG::NodeTransitPtr
returnValue(NULL
);
1490 ON_TextLog on_error_log
;
1495 if(!model
.Read(fileName
, &on_error_log
))
1500 OSG::NodeUnrecPtr child
= NULL
;
1502 m_pRootNode
= OSG::makeCoredNode
<OSG::Group
>();
1504 int object_count
= model
.m_object_table
.Count();
1506 printf("object count: %d\n", object_count
);
1508 for(int i
= 0; i
< object_count
; i
++)
1510 child
= buildNode(model
, i
);
1514 ON_3dmObjectAttributes
&attr
= model
.m_object_table
[i
].m_attributes
;
1515 ON_String node_name
= attr
.m_name
;
1517 if(node_name
.Array() != NULL
)
1518 OSG::setName(child
, node_name
.Array());
1520 m_pRootNode
->addChild(child
);
1524 return OSG::NodeTransitPtr(m_pRootNode
);