33#include <libFreeWRL.h>
35#include "../vrml_parser/Structs.h"
36#include "../main/headers.h"
39#include "LinearAlgebra.h"
40#include "../opengl/Frustum.h"
41#include "../opengl/Material.h"
42#include "Component_Geometry3D.h"
43#include "../opengl/OpenGL_Utils.h"
44#include "../opengl/Textures.h"
46#include "Component_Shape.h"
47#include "../scenegraph/RenderFuncs.h"
48#include "../vrml_parser/CRoutes.h"
51#if defined(_MSC_VER) && _MSC_VER < 1500
60void *Component_NURBS_constructor(){
65void Component_NURBS_init(
struct tComponent_NURBS *t){
68 t->prv = Component_NURBS_constructor();
70 ppComponent_NURBS p = (ppComponent_NURBS)t->prv;
186 glDeleteBuffers(VBO_COUNT, rep->VBO_buffers);
187 FREE_IF_NZ(rep->actualCoord);
188 FREE_IF_NZ(rep->cindex);
189 FREE_IF_NZ(rep->colindex);
190 FREE_IF_NZ(rep->GeneratedTexCoords[0]);
191 FREE_IF_NZ(rep->norindex);
192 FREE_IF_NZ(rep->normal);
193 FREE_IF_NZ(rep->tcindex);
212 polyrep->streamed = FALSE;
215 polyrep->minVals[0] = 999999.9f;
216 polyrep->minVals[1] = 999999.9f;
217 polyrep->minVals[2] = 999999.9f;
218 polyrep->maxVals[0] = -999999.9f;
219 polyrep->maxVals[1] = -999999.9f;
220 polyrep->maxVals[2] = -999999.9f;
222 for (i=0; i<VBO_COUNT; i++)
223 polyrep->VBO_buffers[i] = 0;
230 glGenBuffers(1,&polyrep->VBO_buffers[VERTEX_VBO]);
231 glGenBuffers(1,&polyrep->VBO_buffers[INDEX_VBO]);
240int uniformKnot(
int n,
int p,
float *U){
245 uniform = 1.0f/(float)(n-p);
246 for(j=0;j<p;k++,j++){
250 for(j=0;j<mm;j++,k++){
253 for(j=0;j<p;j++,k++){
259 printf(
" U[%d]=%f",j,U[j]);
265int FindSpan(
int n,
int p,
float u,
float *U)
293 int i, span, m, order;
299 if(u >= U[i] && u < U[i+1])
306 if(u == U[n])
return n-1;
307 low = p; high = n+1; mid = (low+high)/2;
308 while(u < U[mid] || u >= U[mid+1]){
309 if(u < U[mid]) high = mid;
311 mid = (low + high)/2;
317int BasisFuns(
int span,
float u,
int p,
float *U,
float *N){
330 float left[5], right[5], saved, temp;
334 left[j] = u - U[span+1 - j];
335 right[j] = U[span+j] - u;
341 temp = N[r]/(right[r+1]+left[j-r]);
342 N[r] = saved + right[r+1]*temp;
343 saved = left[j-r]*temp;
351int CurvePoint(
int n,
int p,
float* U,
float *Pw,
float u,
float *C )
372 span = FindSpan(n,p,u,U);
373 BasisFuns(span,u,p,U,N);
375 for(i=0;i<4;i++) Cw[i] = 0.0f;
379 Cw[i] += N[j]*Pw[(span-p+j)*4 + i];
398int SurfacePoint(
int n,
int p,
float *U,
399 int m,
int q,
float *V,
400 float *Pw,
float u,
float v,
float *S)
419 int uspan, vspan, i, l, k;
420 float Nu[100], Nv[100], temp[6][4], Sw[4];
422 uspan = FindSpan(n,p,u,U);
423 BasisFuns(uspan,u,p,U,Nu);
424 vspan = FindSpan(m,q,v,V);
425 BasisFuns(vspan,v,q,V,Nv);
432 temp[l][i] += Nu[k]*Pw[((uspan-p+k)*n + (vspan-q+l))*4 + i];
436 for(i=0;i<4;i++) Sw[i] = 0.0f;
439 Sw[i] += Nv[l]*temp[l][i];
447#include <OpenGL/gl.h>
448#include <OpenGL/glu.h>
455#include <../libnurbs/libnurbs2.h>
456#include <../libtess/libtess2.h>
465#define NNC(A) NNC0(X3D_NODE(A))
466#define MNC(A) MNC0(X3D_NODE(A))
467#define MNX(A) MNX0(X3D_NODE(A))
468#define PPX(A) getTypeNode(X3D_NODE(A))
470void CALLBACK nurbsError(GLenum errorCode)
476 printf(
"ouch from nurbsError\n");
481void CALLBACK nurbscurveBegincb(GLenum type,
void *ud)
484 if(DEBGC) printf(
"nurbscurveBegin\n");
486void CALLBACK nurbscurveVertexcb(GLfloat *vertex,
void *ud)
491 ns = node->__points.n;
492 np = node->__numPoints;
495 node->__points.p = REALLOC(node->__points.p,ns *
sizeof(
struct SFVec3f));
496 node->__points.n = ns;
498 pp = &node->__points.p[np];
500 pp->c[i] = vertex[i];
501 node->__numPoints ++;
503 if(DEBGC) printf(
"nurbscurveVertex\n");
505void CALLBACK nurbscurveNormalcb(GLfloat *nml,
void *ud)
508 if(DEBGC) printf(
"nurbscurveNormal\n");
510void CALLBACK nurbscurveEndcb(
void *ud)
514 if(DEBGC) printf(
"nurbscurveEnd\n");
519int generateUniformKnotVector(
int order,
int ncontrol,
float *knots){
535 m = ncontrol - order;
537 uniform = 1.0f/(float)(m + 1);
538 for(j=0;j<order;k++,j++){
541 for(j=0;j<m;j++,k++){
542 knots[k] =uniform*(float)(j+1);
544 for(j=0;j<order;j++,k++){
549int knotsOK(
int order,
int ncontrol,
int nknots,
double *knots){
552 if(nknots < 2 || nknots != ncontrol + order )
556 double lastval = knots[0];
557 for(i=1;i<nknots;i++){
558 if(lastval == knots[i]) nconsec++;
562 if(knots[i] < lastval)
570int knotsOKf(
int order,
int ncontrol,
int nknots,
float *knots){
573 if(nknots < 2 || nknots != ncontrol + order )
577 double lastval = knots[0];
578 for(i=1;i<nknots;i++){
579 if(lastval == knots[i]) nconsec++;
583 if(knots[i] < lastval)
593 if(node->point.n && !node->controlPoint.n){
596 node->controlPoint.p = MALLOC(
struct SFVec2d*,node->point.n *
sizeof(
struct SFVec2d));
597 for(i=0;i<node->point.n;i++)
598 float2double(node->controlPoint.p[i].c,node->point.p[i].c,2);
606 GLfloat *xyzw, *knots;
609 if(node->controlPoint){
610 if(node->controlPoint->_nodeType == NODE_CoordinateDouble){
614 xyzw = MALLOC(
void *, n * 4 *
sizeof(GLfloat));
615 for(i=0;i<mfd->n;i++){
617 xyzw[i*4 + j] = (float) mfd->p[i].c[j];
620 }
else if(node->controlPoint->_nodeType == NODE_Coordinate){
624 xyzw = MALLOC(
void *, n * 4 *
sizeof(GLfloat));
625 for(i=0;i<mff->n;i++){
627 xyzw[i*4 + j] = mff->p[i].c[j];
634 if(node->weight.n && node->weight.n == n){
637 m = min(node->weight.n, n);
639 im = i < m ? i : m-1;
640 w = node->weight.p[im];
641 xyzw[i*4 + 3] = (float)w;
644 for(i=0;i<n;i++) xyzw[i*4 + 3] = 1.0;
647 if(knotsOK(node->order,n,node->knot.n,node->knot.p)){
650 knots = MALLOC(
void *, nk *
sizeof(GLfloat));
652 knots[i] = (GLfloat)node->knot.p[i];
661 nk = n + node->order ;
663 knots = MALLOC(
void *, nk *
sizeof(GLfloat));
664 generateUniformKnotVector(node->order,n, knots);
667 printf(
"bad knot vector, replacing with:\n");
669 printf(
"[%d]=%f \n",ii,knots[ii]);
675 if(n && nk && nk >= n){
676 GLUnurbsObj *theNurb;
678 mtess = node->order + 1;
679 ntess = node->tessellation;
680 theNurb = gluNewNurbsRenderer();
681 gluNurbsProperty(theNurb, GLU_NURBS_MODE, GLU_NURBS_TESSELLATOR);
682 gluNurbsCallbackData(theNurb,(GLvoid*)node);
688 double model[16], proj[16];
689 float modelf[16], projf[16];
695 node->__points.p = MALLOC(
void *,
sizeof(
struct SFVec3f)*n*10);
696 node->__points.n = n*10;
698 gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, (
float)(mtess));
700 gluNurbsProperty(theNurb,GLU_SAMPLING_METHOD,GLU_PATH_LENGTH);
702 gluNurbsProperty(theNurb,GLU_SAMPLING_METHOD,GLU_PARAMETRIC_TOLERANCE);
703 gluNurbsProperty(theNurb, GLU_AUTO_LOAD_MATRIX,GL_FALSE);
705 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, model);
706 FW_GL_GETDOUBLEV(GL_PROJECTION_MATRIX, proj);
707 FW_GL_GETINTEGERV(GL_VIEWPORT, viewPort);
709 modelf[i] = (float)model[i];
710 projf[i] = (float)proj[i];
712 gluLoadSamplingMatrices(theNurb,modelf,projf,viewPort);
719 mtess = max(mtess,ntess+1);
721 mtess = max(mtess,(-ntess * n) + 1);
723 mtess = max(mtess,2*n + 1);
724 mtess = (int)((
float)mtess * node->_tscale);
725 node->__points.p = MALLOC(
void *,
sizeof(
struct SFVec3f)*mtess+1);
726 node->__points.n = mtess;
727 gluNurbsProperty(theNurb,GLU_SAMPLING_METHOD,GLU_DOMAIN_DISTANCE);
728 gluNurbsProperty(theNurb,GLU_U_STEP,(GLfloat)mtess);
730 gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_FILL);
731 gluNurbsCallback(theNurb, GLU_ERROR, nurbsError);
732 gluNurbsCallback(theNurb, GLU_NURBS_BEGIN_DATA, nurbscurveBegincb);
733 gluNurbsCallback(theNurb, GLU_NURBS_VERTEX_DATA, nurbscurveVertexcb);
734 gluNurbsCallback(theNurb, GLU_NURBS_NORMAL_DATA, nurbscurveNormalcb);
735 gluNurbsCallback(theNurb, GLU_NURBS_END_DATA, nurbscurveEndcb);
736 gluBeginCurve(theNurb);
737 node->__numPoints = 0;
738 gluNurbsCurve(theNurb,nk,knots,4,xyzw,node->order,GL_MAP1_VERTEX_4);
739 gluEndCurve(theNurb);
740 gluDeleteNurbsRenderer(theNurb);
741 node->__points.n = node->__numPoints;
747 ttglobal tg = gglobal();
750 if (node->__numPoints>0) {
752 setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
753 node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
760 FW_GL_VERTEX_POINTER (3,GL_FLOAT,0,(GLfloat *)node->__points.p);
761 sendArraysToGPU (GL_LINE_STRIP, 0, node->__numPoints);
762 tg->Mainloop.trisThisLoop += node->__numPoints;
768 int nc, nu, nku, nkv, nv, i,j;
769 float *knotsu, *knotsv, *xyzw;
772 mff = &node->controlPoint;
774 xyzw = MALLOC(
void *, nc * 4 *
sizeof(GLfloat));
775 for(i=0;i<mff->n;i++){
777 xyzw[i*4 + j] = mff->p[i].c[j];
779 xyzw[i*4 + 2] = 0.0f;
780 xyzw[i*4 + 3] = 1.0f;
782 nu = node->uDimension;
783 nv = node->vDimension;
784 if(node->weight.n && node->weight.n == nc){
787 m = min(node->weight.n, nc);
789 im = i < m ? i : m-1;
790 w = node->weight.p[im];
791 xyzw[i*4 + 3] = (float) w;
794 for(i=0;i<nc;i++) xyzw[i*4 + 3] = 1.0;
796 nu = node->uDimension;
797 nv = node->vDimension;
800 if(knotsOK(node->uOrder,nu,node->uKnot.n,node->uKnot.p)){
804 knotsu = MALLOC(
void *, nku *
sizeof(GLfloat));
806 knotsu[i] = (GLfloat)node->uKnot.p[i];
810 printf(
"good u knot vector nk=%d\n",nku);
811 for(ii=0;ii<nku;ii++)
812 printf(
"[%d]=%f \n",ii,knotsu[ii]);
818 nku = nu + node->uOrder ;
820 knotsu = MALLOC(
void *, nku *
sizeof(GLfloat));
821 generateUniformKnotVector(node->uOrder,nu, knotsu);
824 printf(
"bad u knot vector given, replacing with:\n");
825 for(ii=0;ii<nku;ii++)
826 printf(
"[%d]=%f \n",ii,knotsu[ii]);
832 if(knotsOK(node->vOrder,nv,node->vKnot.n,node->vKnot.p)){
835 knotsv = MALLOC(
void *, nkv *
sizeof(GLfloat));
837 knotsv[i] = (GLfloat)node->vKnot.p[i];
841 printf(
"good v knot vector nk=%d\n",nkv);
842 for(ii=0;ii<nkv;ii++)
843 printf(
"[%d]=%f \n",ii,knotsv[ii]);
849 nkv = nv + node->vOrder ;
851 knotsv = MALLOC(
void *, nkv *
sizeof(GLfloat));
852 generateUniformKnotVector(node->vOrder,nv, knotsv);
855 printf(
"bad v knot vector given, replacing with:\n");
856 for(ii=0;ii<nkv;ii++)
857 printf(
"[%d]=%f \n",ii,knotsv[ii]);
860 if(!knotsOKf(node->vOrder,nv,nkv,knotsv))
861 printf(
"ouch still not right knot vector\n");
864 node->_uKnot.p = knotsu;
865 node->_uKnot.n = nku;
866 node->_vKnot.p = knotsv;
867 node->_vKnot.n = nkv;
868 node->_controlPoint.p = (
struct SFVec4f*)xyzw;
869 node->_controlPoint.n = nc;
873int getNurbsSurfacePoint(
struct X3D_Node *nurbsSurfaceNode,
float *uv,
float *xyz){
875 if(nurbsSurfaceNode){
876 switch(nurbsSurfaceNode->_nodeType){
877 case NODE_NurbsTextureCoordinate:
880 if(NNC(node)) compile_NurbsTextureCoordinate(node);
881 ret = SurfacePoint( node->uDimension,node->uOrder-1,node->_uKnot.p,
882 node->vDimension,node->vOrder-1,node->_vKnot.p,
883 (
float *)node->_controlPoint.p,uv[0],uv[1],xyz);
886 case NODE_NurbsPatchSurface:
888 case NODE_NurbsTrimmedSurface:
928void CALLBACK nurbssurfBegincb(GLenum type,
void *ud)
932 if(0)
if(DEBG) printf(
"callback nurbsSurfaceBegin\n");
934 printf(
"nurbssurfBegin type = ");
936 case GL_QUAD_STRIP: printf(
"QUAD_STRIP");
break;
937 case GL_TRIANGLE_STRIP: printf(
"TRIANGLE_STRIP");
break;
938 case GL_TRIANGLE_FAN: printf(
"TRIANGLE_FAN");
break;
939 case GL_TRIANGLES: printf(
"TRIANGLES");
break;
941 printf(
"not sure %x %d",type,type);
957void CALLBACK nurbssurfVertexcb(GLfloat *vertex,
void *ud)
962 ss = vector_get_ptr(
struct stripState,strips,strips->n -1);
963 memcpy(&pp,vertex,
sizeof(
struct SFVec3f));
964 vector_pushBack(
struct SFVec3f,&ss->pv,pp);
967 if(0) printf(
"callback nurbssurfVertex %f %f %f\n",vertex[0],vertex[1],vertex[2]);
969void CALLBACK nurbssurfNormalcb(GLfloat *nml,
void *ud)
974 ss = vector_get_ptr(
struct stripState,strips,strips->n -1);
975 memcpy(&pp,nml,
sizeof(
struct SFVec3f));
976 vector_pushBack(
struct SFVec3f,&ss->nv,pp);
979 if(0) printf(
"callback nurbssurfNormal\n");
981void CALLBACK nurbssurfEndcb(
void *ud)
985 ss = vector_get_ptr(
struct stripState,strips,strips->n -1);
988 printf(
"nurbssurfEnd #p %d #n %d\n",ss->pv.n, ss->nv.n);
989 for(i=0;i<ss->pv.n;i++){
991 printf(
"%f %f %f\n",pp.c[0],pp.c[1],pp.c[2]);
994 if(0)
if(DEBG) printf(
"callback nurbsSurfaceEnd\n");
997void CALLBACK nurbssurfTexcoordcb(GLfloat *tCrd,
void *ud){
998 static int count = 0;
1002 ss = vector_get_ptr(
struct stripState,strips,strips->n -1);
1003 memcpy(&tp,tCrd,
sizeof(
struct SFVec2f));
1004 vector_pushBack(
struct SFVec2f,&ss->tv,tp);
1011 printf(
"callback nurbssufTexcoordcb\n");
1016#define GL_QUAD_STRIP 0x0008
1018static int USETXCOORD = 1;
1022 int i, j, npoints, np, ni, ntri, nindex, ntc;
1026 GLuint *cindex, *norindex, *tcindex;
1027 float *tcoord = NULL;
1036 FREE_IF_NZ(polyrep->cindex);
1037 FREE_IF_NZ(polyrep->actualCoord);
1038 FREE_IF_NZ(polyrep->GeneratedTexCoords[0]);
1039 FREE_IF_NZ(polyrep->colindex);
1040 FREE_IF_NZ(polyrep->color);
1041 FREE_IF_NZ(polyrep->norindex);
1042 FREE_IF_NZ(polyrep->normal);
1043 FREE_IF_NZ(polyrep->flat_normal);
1044 FREE_IF_NZ(polyrep->tcindex);
1045 FREE_IF_NZ(polyrep->wire_indices);
1049 node->_intern = (
struct X3D_GeomRep*) create_polyrep();
1051 rep_ = polyrep = (
struct X3D_PolyRep*) node->_intern;
1062 rep_->ntexdim[0] = 2;
1063 rep_->tcoordtype = NODE_TextureCoordinate;
1070 tcnode = createNewX3DNode(NODE_TextureCoordinate);
1071 npoints = nindex = ntc = 0;
1072 for(i=0;i<strips->n;i++){
1073 ss = vector_get_ptr(
struct stripState,strips,i);
1074 npoints += ss->pv.n;
1077 case GL_QUAD_STRIP: nindex += (ss->pv.n -2)/2 * 5;
break;
1078 case GL_TRIANGLE_STRIP: nindex += (ss->pv.n -2);
break;
1079 case GL_TRIANGLE_FAN: nindex += (ss->pv.n -2);
break;
1080 case GL_TRIANGLES: nindex += (ss->pv.n -2);
break;
1082 nindex += (ss->pv.n -2);
1088 rep_->actualCoord = MALLOC(
void *, npoints * 3 *
sizeof(
float));
1089 rep_->normal = MALLOC(
void *, npoints * 3 *
sizeof(
float));
1097 rep_->ntri = ntri = nindex;
1101 cindex = rep_->cindex = MALLOC(GLuint *,
sizeof(GLuint)*3*(ntri));
1102 norindex = rep_->norindex = MALLOC(GLuint *,
sizeof(GLuint)*3*ntri);
1104 tcindex = rep_->tcindex = MALLOC(GLuint*,
sizeof(GLuint)*3*(ntri));
1109 tcoord = MALLOC (
float *,
sizeof (
float) * ntri * 2 * 3);
1116 for(i=0;i<strips->n;i++){
1117 ss = vector_get_ptr(
struct stripState,strips,i);
1119 memcpy(&rep_->actualCoord[np*3],ss->pv.data,ss->pv.n * 3 *
sizeof(
float));
1120 memcpy(&rep_->normal[np*3],ss->nv.data,ss->nv.n * 3 *
sizeof(
float));
1121 if(USETXCOORD && tcoord) memcpy(&tcoord[np*2],ss->tv.data,ss->tv.n * 2 *
sizeof(
float));
1124 for(j=0;j<ss->pv.n -2;j+=2){
1125 rep_->cindex[ni++] = np+j;
1126 rep_->cindex[ni++] = np+j+1;
1127 rep_->cindex[ni++] = np+j+3;
1129 rep_->cindex[ni++] = np+j+3;
1130 rep_->cindex[ni++] = np+j+2;
1131 rep_->cindex[ni++] = np+j;
1134 memcpy(&rep_->norindex[ntri*3],&rep_->cindex[ntri*3],2*3*
sizeof(
int));
1135 if(USETXCOORD) memcpy(&rep_->tcindex[ntri*3],&rep_->cindex[ntri*3],2*3*
sizeof(
int));
1139 case GL_TRIANGLE_STRIP:
1140 nindex += (ss->pv.n -2);
1142 case GL_TRIANGLE_FAN:
1144 for(j=0;j<ss->pv.n -2;j+=1){
1145 rep_->cindex[ni++] = np;
1146 rep_->cindex[ni++] = np+j+1;
1147 rep_->cindex[ni++] = np+j+2;
1148 memcpy(&rep_->norindex[ntri*3],&rep_->cindex[ntri*3],3*
sizeof(
int));
1149 if(USETXCOORD) memcpy(&rep_->tcindex[ntri*3],&rep_->cindex[ntri*3],3*
sizeof(
int));
1154 nindex += (ss->pv.n -2);
1157 nindex += (ss->pv.n -2);
1162 if(node->texCoord && node->texCoord->_nodeType == NODE_NurbsTextureCoordinate){
1163 static FILE *fp = NULL;
1169 xyz[0] = tcoord[i*2 + 1];
1170 xyz[1] = tcoord[i*2 + 0];
1172 xyz[3] = tcoord[i*2 + 3];
1173 getNurbsSurfacePoint(node->texCoord, xyz, stru);
1175 tcoord[i*2 + 0] = stru[0];
1176 tcoord[i*2 + 1] = stru[1];
1186 tcnode->point.p = (
struct SFVec2f*)tcoord;
1187 tcnode->point.n = np;
1188 if(0)
for(i=0;i<tcnode->point.n;i++){
1189 printf(
"%d %f %f\n",i,tcnode->point.p[i].c[0],tcnode->point.p[i].c[1]);
1197 if (polyrep->ntri != 0) {
1199 stream_polyrep(node, NULL,NULL,NULL,NULL, tcnode);
1202 FREE_IF_NZ(tcnode->point.p);
1205 polyrep->irep_change = node->_change;
1230 int i,j, n, nu, nv, nku, nkv;
1231 GLfloat *xyzw, *knotsu, *knotsv;
1232 ppComponent_NURBS p = (ppComponent_NURBS)gglobal()->Component_NURBS.prv;
1234 nku = nkv = nu = nv = n = 0;
1235 xyzw = knotsu = knotsv = NULL;
1242 if(node->controlPoint){
1243 if(node->controlPoint->_nodeType == NODE_CoordinateDouble){
1247 xyzw = MALLOC(
void *, n * 4 *
sizeof(GLfloat));
1248 for(i=0;i<mfd->n;i++){
1250 xyzw[i*4 + j] = (float)mfd->p[i].c[j];
1253 }
else if(node->controlPoint->_nodeType == NODE_Coordinate){
1257 xyzw = MALLOC(
void *, n * 4 *
sizeof(GLfloat));
1258 for(i=0;i<mff->n;i++){
1260 xyzw[i*4 + j] = mff->p[i].c[j];
1267 if(node->weight.n && node->weight.n == n){
1270 m = min(node->weight.n, n);
1272 im = i < m ? i : m-1;
1273 w = node->weight.p[im];
1274 xyzw[i*4 + 3] = (float)w;
1277 for(i=0;i<n;i++) xyzw[i*4 + 3] = 1.0;
1279 nu = node->uDimension;
1280 nv = node->vDimension;
1283 if(knotsOK(node->uOrder,nu,node->uKnot.n,node->uKnot.p)){
1286 nku = node->uKnot.n;
1287 knotsu = MALLOC(
void *, nku *
sizeof(GLfloat));
1289 knotsu[i] = (GLfloat)node->uKnot.p[i];
1293 printf(
"good u knot vector nk=%d\n",nku);
1294 for(ii=0;ii<nku;ii++)
1295 printf(
"[%d]=%f \n",ii,knotsu[ii]);
1300 static int once = 0;
1301 nku = nu + node->uOrder ;
1303 knotsu = MALLOC(
void *, nku *
sizeof(GLfloat));
1304 generateUniformKnotVector(node->uOrder,nu, knotsu);
1307 printf(
"bad u knot vector given, replacing with:\n");
1308 for(ii=0;ii<nku;ii++)
1309 printf(
"[%d]=%f \n",ii,knotsu[ii]);
1315 if(knotsOK(node->vOrder,nv,node->vKnot.n,node->vKnot.p)){
1317 nkv = node->vKnot.n;
1318 knotsv = MALLOC(
void *, nkv *
sizeof(GLfloat));
1320 knotsv[i] = (GLfloat)node->vKnot.p[i];
1324 printf(
"good v knot vector nk=%d\n",nkv);
1325 for(ii=0;ii<nkv;ii++)
1326 printf(
"[%d]=%f \n",ii,knotsv[ii]);
1330 static int once = 0;
1332 nkv = nv + node->vOrder ;
1334 knotsv = MALLOC(
void *, nkv *
sizeof(GLfloat));
1335 generateUniformKnotVector(node->vOrder,nv, knotsv);
1338 printf(
"bad v knot vector given, replacing with:\n");
1339 for(ii=0;ii<nkv;ii++)
1340 printf(
"[%d]=%f \n",ii,knotsv[ii]);
1346 if(n && nku && nkv){
1347 static GLUnurbsObj *theNurb = NULL;
1348 int ntessu, ntessv, mtessu, mtessv;
1351 int texcoordnodeIsGenerated;
1353 mtessu = node->uOrder + 1;
1354 ntessu = node->uTessellation;
1355 mtessv = node->vOrder + 1;
1356 ntessv = node->vTessellation;
1358 if(DEBG) printf(
"gluNewNurbsRenderer\n");
1360 theNurb = gluNewNurbsRenderer();
1361 gluNurbsProperty(theNurb, GLU_NURBS_MODE, GLU_NURBS_TESSELLATOR);
1367 double model[16], proj[16];
1368 float modelf[16], projf[16];
1375 gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, (
float)(mtessu));
1377 gluNurbsProperty(theNurb,GLU_SAMPLING_METHOD,GLU_PATH_LENGTH);
1379 gluNurbsProperty(theNurb,GLU_SAMPLING_METHOD,GLU_PARAMETRIC_TOLERANCE);
1380 gluNurbsProperty(theNurb, GLU_AUTO_LOAD_MATRIX,GL_FALSE);
1382 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, model);
1383 FW_GL_GETDOUBLEV(GL_PROJECTION_MATRIX, proj);
1384 FW_GL_GETINTEGERV(GL_VIEWPORT, viewPort);
1386 modelf[i] = (float)model[i];
1387 projf[i] = (float)proj[i];
1389 gluLoadSamplingMatrices(theNurb,modelf,projf,viewPort);
1396 mtessu = max(mtessu,ntessu+1);
1398 mtessu = max(mtessu,(-ntessu * nu) + 1);
1400 mtessu = max(mtessu,2*nu + 1);
1403 mtessv = max(mtessv,ntessv+1);
1405 mtessv = max(mtessv,(-ntessv * nv) + 1);
1407 mtessv = max(mtessv,2*nv + 1);
1408 mtessu = (int)((
float)mtessu * node->_tscale);
1409 mtessv = (int)((
float)mtessv * node->_tscale);
1411 gluNurbsProperty(theNurb,GLU_SAMPLING_METHOD,GLU_DOMAIN_DISTANCE);
1412 gluNurbsProperty(theNurb,GLU_U_STEP,(GLfloat)mtessu);
1413 gluNurbsProperty(theNurb,GLU_V_STEP,(GLfloat)mtessv);
1415 gluNurbsProperty(theNurb, GLU_DISPLAY_MODE, GLU_FILL);
1417 gluNurbsCallback(theNurb, GLU_ERROR, nurbsError);
1418 gluNurbsCallback(theNurb, GLU_NURBS_BEGIN_DATA, nurbssurfBegincb);
1419 gluNurbsCallback(theNurb, GLU_NURBS_VERTEX_DATA, nurbssurfVertexcb);
1420 gluNurbsCallback(theNurb, GLU_NURBS_NORMAL_DATA, nurbssurfNormalcb);
1421 gluNurbsCallback(theNurb, GLU_NURBS_END_DATA, nurbssurfEndcb);
1422 gluNurbsCallback(theNurb, GLU_NURBS_TEXTURE_COORD_DATA, nurbssurfTexcoordcb);
1425 gluNurbsCallbackData(theNurb,(GLvoid*)strips);
1427 if(DEBG) printf(
"gluBeginSurface \n");
1428 gluBeginSurface(theNurb);
1429 gluNurbsSurface(theNurb,nku,knotsu,nkv,knotsv,4,4*nu,xyzw,node->uOrder,node->vOrder,GL_MAP2_VERTEX_4);
1463 texcoordnodeIsGenerated = FALSE;
1464 texCoordNode = node->texCoord;
1474 float du, dv, uu, vv;
1477 texcoordnodeIsGenerated = TRUE;
1478 texCoord->point.p = MALLOC(
struct SFVec2f*,nu * nv *
sizeof(
struct SFVec2f));
1479 du = 1.0f / (float)max(1,(nu -1));
1480 dv = 1.0f / (float)max(1,(nv -1));
1484 if(k == nv-1) vv = 1.0f;
1487 if(j == nu-1) uu = 1.0f;
1488 texCoord->point.p[jj].c[0] = uu;
1489 texCoord->point.p[jj].c[1] = vv;
1495 texCoord->point.n = jj;
1496 texCoordNode = X3D_NODE(texCoord);
1506 if(texCoordNode->_nodeType == NODE_TextureCoordinate){
1509 float *control2D = (
float*)texCoord->point.p;
1510 int nctrl = texCoord->point.n;
1515 gluNurbsSurface(theNurb,nku,knotsu,nkv,knotsv,2,2*nu,control2D,node->uOrder,node->vOrder,GL_MAP2_TEXTURE_COORD_2);
1519 float *tknotsu, *tknotsv;
1522 tknotsu = MALLOC(
float *, (nu+2) *
sizeof(GLfloat));
1523 tknotsv = MALLOC(
float *, (nv+2) *
sizeof(GLfloat));
1524 generateUniformKnotVector(2,nu,tknotsu);
1525 generateUniformKnotVector(2,nv,tknotsv);
1526 printf(
"tknotsu = [");
1527 for(k=0;k<nu+2;k++) printf(
"%f ",tknotsu[k]);
1528 printf(
"]\ntknotsv = [");
1529 for(k=0;k<nv+2;k++) printf(
"%f ",tknotsv[k]);
1531 gluNurbsSurface(theNurb,nu+2,knotsu,nv+2,knotsv,4,4*nu,control2D,2,2,GL_MAP2_TEXTURE_COORD_2);
1533 }
else if(texCoordNode->_nodeType == NODE_NurbsTextureCoordinate){
1540 float tknots[4] = {0.0f, 0.0f, 1.0f, 1.0f};
1541 float unit_control2D [8] = {0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
1543 gluNurbsSurface(theNurb,4,tknots,4,tknots,2,2*2,unit_control2D,2,2,GL_MAP2_TEXTURE_COORD_2);
1548 float du, dv, uu, vv;
1552 texcoordnodeIsGenerated = TRUE;
1553 FREE_IF_NZ(texCoord->point.p);
1554 texCoord->point.p = MALLOC(
struct SFVec2f*,nu * nv *
sizeof(
struct SFVec2f));
1555 du = 1.0f / (float)max(1,(nu -1));
1556 dv = 1.0f / (float)max(1,(nv -1));
1560 if(k == nv-1) vv = 1.0f;
1563 if(j == nu-1) uu = 1.0f;
1564 texCoord->point.p[jj].c[0] = uu;
1565 texCoord->point.p[jj].c[1] = vv;
1571 texCoord->point.n = jj;
1572 texCoordNode = X3D_NODE(texCoord);
1576 control2D = (
float*)texCoord->point.p;
1577 gluNurbsSurface(theNurb,nku,knotsu,nkv,knotsv,2,2*nu,control2D,node->uOrder,node->vOrder,GL_MAP2_TEXTURE_COORD_2);
1589 if(DEBG) printf(
"gluBeginTrim \n");
1590 gluBeginTrim (theNurb);
1594 GLfloat edgePt[5][2] = {{0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}, {0.0, 0.0}};
1595 if(DEBG) printf(
"gluPwlCurve 0\n");
1596 gluPwlCurve (theNurb, 5, &edgePt[0][0], 2, GLU_MAP1_TRIM_2);
1600 GLfloat *edges = MALLOC(
void *, (2 * ntessu + 2 * ntessv) *2*
sizeof(GLfloat));
1601 GLfloat uspan, vspan;
1602 uspan = 1.0f/(float)(ntessu -1);
1603 vspan = 1.0f/(float)(ntessv -1);
1604 for(i=0;i<ntessu-1;i++){
1605 edges[i*2 +0] = (float)(i)*uspan;
1606 edges[i*2 +1] = 0.0;
1607 edges[(ntessu+ntessv+i)*2 + 0] = (
float)(ntessu - 1 - i)*uspan;
1608 edges[(ntessu+ntessv+i)*2 + 1] = 1.0;
1610 for(i=0;i<ntessv;i++){
1611 edges[(ntessu+i)*2 + 0] = 1.0;
1612 edges[(ntessu+i)*2 + 1] = (
float)(i)*vspan;
1613 edges[(ntessu+ntessv+ntessu+i)*2 + 0] = 0.0;
1614 edges[(ntessu+ntessv+ntessu+i)*2 + 1] = (
float)(ntessv - 1 - i)*vspan;
1617 edges[((ntessu -1)*2 + (ntessv -1)*2)*2 + 0] = 0.0;
1618 edges[((ntessu -1)*2 + (ntessv -1)*2)*2 + 1] = 0.0;
1619 if(DEBG) printf(
"gluPwlCurve 1\n");
1620 gluPwlCurve (theNurb, 2*(ntessu -1 + ntessv -1) +1, edges, 2, GLU_MAP1_TRIM_2);
1622 if(DEBG) printf(
"gluEndTrim\n");
1623 gluEndTrim (theNurb);
1629 GLfloat curvePt[4][2] =
1630 {{0.25, 0.5}, {0.25, 0.75}, {0.75, 0.75}, {0.75, 0.5}};
1631 GLfloat curveKnots[8] =
1632 {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0};
1633 GLfloat pwlPt[4][2] =
1634 {{0.75, 0.5}, {0.5, 0.25}, {0.25, 0.5}};
1636 if(DEBG) printf(
"gluBeginTrim A\n");
1637 gluBeginTrim (theNurb);
1638 if(DEBG) printf(
"gluNurbsCurve A\n");
1639 gluNurbsCurve (theNurb, 8, curveKnots, 2,
1640 &curvePt[0][0], 4, GLU_MAP1_TRIM_2);
1641 if(DEBG) printf(
"gluPwlCurve A\n");
1642 gluPwlCurve (theNurb, 3, &pwlPt[0][0], 2, GLU_MAP1_TRIM_2);
1643 if(DEBG) printf(
"gluEndTrim A\n");
1644 gluEndTrim (theNurb);
1647 for(i=0;i<trim->n;i++){
1650 if(DEBG) printf(
"gluBeginTrim B\n");
1651 gluBeginTrim (theNurb);
1652 for(m=0;m<tc->children.n;m++)
1657 struct X3D_Node *ctr = tc->children.p[m];
1658 GLfloat *cknot, *ctrl, *cweight;
1659 cknot = ctrl = cweight = NULL;
1660 switch(ctr->_nodeType){
1661 case NODE_ContourPolyline2D:
1663 ctrl = MALLOC(
void *, cp2d->controlPoint.n * 2*
sizeof(GLfloat));
1664 for(j=0;j<cp2d->controlPoint.n;j++) {
1666 ctrl[j*2 + k] = (
float)cp2d->controlPoint.p[j].c[k];
1668 if(DEBG) printf(
"gluPwlCurve B\n");
1669 gluPwlCurve (theNurb, cp2d->controlPoint.n, ctrl, 2, GLU_MAP1_TRIM_2);
1672 case NODE_NurbsCurve2D:
1675 nk = nc2d->controlPoint.n + nc2d->order;
1676 if(nk == nc2d->knot.n)
1678 cknot = MALLOC(
void *, nk *
sizeof(GLfloat));
1681 cweight = MALLOC(
void *, nc2d->controlPoint.n *
sizeof(GLfloat));
1682 if(nc2d->weight.n == nc2d->controlPoint.n){
1683 for(j=0;j<nc2d->weight.n;j++) cweight[j] = (
float)nc2d->weight.p[j];
1685 for(j=0;j<nc2d->controlPoint.n;j++) cweight[j] = 1.0f;
1688 ctrl = MALLOC(
void *, nc2d->controlPoint.n * dim*
sizeof(GLfloat));
1689 for(j=0;j<nc2d->controlPoint.n;j++) {
1691 ctrl[j*dim + k] = (float)nc2d->controlPoint.p[j].c[k];
1692 if(dim == 3) ctrl[j*dim + k] *= cweight[j];
1694 if(dim == 3) ctrl[j*dim + dim-1] = (float)cweight[j];
1696 if(knotsOK(nc2d->order,nc2d->controlPoint.n,nc2d->knot.n,nc2d->knot.p)){
1698 for(j=0;j<nc2d->knot.n;j++)
1699 cknot[j] = (
float)nc2d->knot.p[j];
1701 generateUniformKnotVector(nc2d->order,nc2d->controlPoint.n,cknot);
1702 printf(
"replacing nurbscurve2D knotvector with:\n");
1704 printf(
"%f ",cknot[j]);
1710 printf(
"knot %d ={",nc2d->knot.n);
1711 for(j=0;j<nc2d->knot.n;j++){
1712 printf(
"%f ",cknot[j]);
1715 printf(
"control %d = {\n",nc2d->controlPoint.n);
1716 for(j=0;j<nc2d->controlPoint.n;j++) {
1717 for(k=0;k<dim;k++) printf(
"%f \n",ctrl[j*dim +k]);
1722 if(DEBG) printf(
"gluNurbsCurve B\n");
1725 mtess = nc2d->order + 1;
1726 ntess = nc2d->tessellation;
1732 double model[16], proj[16];
1733 float modelf[16], projf[16];
1740 gluNurbsProperty(theNurb, GLU_SAMPLING_TOLERANCE, (
float)(mtess));
1742 gluNurbsProperty(theNurb,GLU_SAMPLING_METHOD,GLU_PATH_LENGTH);
1744 gluNurbsProperty(theNurb,GLU_SAMPLING_METHOD,GLU_PARAMETRIC_TOLERANCE);
1745 gluNurbsProperty(theNurb, GLU_AUTO_LOAD_MATRIX,GL_FALSE);
1747 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, model);
1748 FW_GL_GETDOUBLEV(GL_PROJECTION_MATRIX, proj);
1749 FW_GL_GETINTEGERV(GL_VIEWPORT, viewPort);
1751 modelf[i] = (float)model[i];
1752 projf[i] = (float)proj[i];
1754 gluLoadSamplingMatrices(theNurb,modelf,projf,viewPort);
1761 mtess = max(mtess,ntess+1);
1763 mtess = max(mtess,(-ntess * n) + 1);
1765 mtess = max(mtess,2*n + 1);
1766 gluNurbsProperty(theNurb,GLU_SAMPLING_METHOD,GLU_DOMAIN_DISTANCE);
1767 gluNurbsProperty(theNurb,GLU_U_STEP,(GLfloat)mtess);
1770 gluNurbsCurve (theNurb, nk, cknot, dim, ctrl, nc2d->order, GLU_MAP1_TRIM_2);
1773 ConsoleMessage(
"%s %d",
"unknown trimming contour node",ctr->_nodeType);
1777 FREE_IF_NZ(cweight);
1779 if(DEBG) printf(
"gluEndTrim B\n");
1780 gluEndTrim (theNurb);
1783 if(DEBG) printf(
"gluEndSurface \n");
1784 gluEndSurface(theNurb);
1785 if(DEBG) printf(
"gluDeleteNurbsRenderer \n");
1786 if(0) gluDeleteNurbsRenderer(theNurb);
1791 if(texcoordnodeIsGenerated){
1793 FREE_IF_NZ(texCoord->point.p);
1794 FREE_IF_NZ(texCoordNode);
1798 for(i=0;i<vectorSize(strips);i++){
1800 FREE_IF_NZ(ss->pv.data); ss->pv.allocn = 0; ss->pv.n = 0;
1801 FREE_IF_NZ(ss->nv.data); ss->nv.allocn = 0; ss->nv.n = 0;
1802 FREE_IF_NZ(ss->tv.data); ss->tv.allocn = 0; ss->tv.n = 0;
1804 FREE_IF_NZ(strips->data); strips->allocn = 0; strips->n = 0;
1815void render_ray_polyrep(
void *node);
1816void render_polyrep(
void *node);
1820 compile_NurbsSurface(node, NULL);
1824 if (!node->_intern)
return;
1825 render_ray_polyrep(node);
1830 if (!node->_intern)
return;
1831 collide_genericfaceset(X3D_INDEXEDFACESET(node));
1836 if (!node->_intern)
return;
1837 CULL_FACE(node->solid)
1838 render_polyrep(node);
1848 if (!node->_intern)
return;
1849 render_ray_polyrep(node);
1854 if (!node->_intern)
return;
1855 collide_genericfaceset(X3D_INDEXEDFACESET(node));
1860 if (!node->_intern)
return;
1861 CULL_FACE(node->solid)
1862 render_polyrep(node);
1865void do_NurbsPositionInterpolator (
void *node) {
1879 if(!px->_OK == TRUE){
1881 if(!(px->knot.n > 1))
1883 if(!px->controlPoint )
1885 if(px->controlPoint->_nodeType != NODE_Coordinate)
1888 if(control->point.n < 2)
1890 n = control->point.n;
1892 if(px->weight.n == n)
1893 weight = px->weight.p;
1894 px->_xyzw.p = MALLOC(
struct SFVec4f*,control->point.n *
sizeof(
struct SFVec4f));
1896 for(i=0;i<control->point.n;i++){
1898 wt = weight ? (float)weight[i] : 1.0f;
1899 veccopy3f(xyzw,control->point.p[i].c);
1900 vecscale3f(xyzw,xyzw,wt);
1902 veccopy4f(px->_xyzw.p[i].c,xyzw);
1904 if(knotsOK(px->order,px->_xyzw.n,px->knot.n,px->knot.p)){
1907 knots = MALLOC(
void *, nk *
sizeof(GLfloat));
1909 knots[i] = (GLfloat)px->knot.p[i];
1916 static int once = 0;
1918 nk = n + px->order ;
1920 knots = MALLOC(
void *, nk *
sizeof(GLfloat));
1921 generateUniformKnotVector(px->order,n, knots);
1924 printf(
"bad knot vector, replacing with:\n");
1925 for(ii=0;ii<nk;ii++)
1926 printf(
"[%d]=%f \n",ii,knots[ii]);
1931 px->_knot.p = knots;
1933 px->_knotrange.c[0] = px->_knot.p[0];
1934 px->_knotrange.c[1] = px->_knot.p[px->_knot.n-1];
1942 fraction = max(px->_knotrange.c[0],px->set_fraction);
1943 fraction = min(px->_knotrange.c[1],px->set_fraction);
1944 CurvePoint(px->_xyzw.n, px->order-1, px->_knot.p, (
float*)px->_xyzw.p, fraction, cw );
1945 veccopy3f(px->value_changed.c,cw);
1949 printf(
"do_PositionInt: Position/Vec3f interp, node %u kin %d kvin %d set_fraction %f\n",
1950 node, kin, kvin, px->set_fraction);
1962void do_NurbsOrientationInterpolator (
void *node) {
1976 if(!px->_OK == TRUE){
1978 if(!(px->knot.n > 1))
1980 if(!px->controlPoint )
1982 if(px->controlPoint->_nodeType != NODE_Coordinate)
1985 if(control->point.n < 2)
1987 n = control->point.n;
1989 if(px->weight.n == n)
1990 weight = px->weight.p;
1991 px->_xyzw.p = MALLOC(
struct SFVec4f*,control->point.n *
sizeof(
struct SFVec4f));
1993 for(i=0;i<control->point.n;i++){
1995 wt = weight ? (float)weight[i] : 1.0f;
1996 veccopy3f(xyzw,control->point.p[i].c);
1997 vecscale3f(xyzw,xyzw,wt);
1999 veccopy4f(px->_xyzw.p[i].c,xyzw);
2001 if(knotsOK(px->order,px->_xyzw.n,px->knot.n,px->knot.p)){
2004 knots = MALLOC(
void *, nk *
sizeof(GLfloat));
2006 knots[i] = (GLfloat)px->knot.p[i];
2013 static int once = 0;
2015 nk = n + px->order ;
2017 knots = MALLOC(
void *, nk *
sizeof(GLfloat));
2018 generateUniformKnotVector(px->order,n, knots);
2021 printf(
"bad knot vector, replacing with:\n");
2022 for(ii=0;ii<nk;ii++)
2023 printf(
"[%d]=%f \n",ii,knots[ii]);
2028 px->_knot.p = knots;
2030 px->_knotrange.c[0] = px->_knot.p[0];
2031 px->_knotrange.c[1] = px->_knot.p[px->_knot.n-1];
2039 fraction = max(px->_knotrange.c[0],px->set_fraction);
2040 fraction = min(px->_knotrange.c[1],px->set_fraction);
2045 float f1, f2, cw1[4], cw2[4], dir[3], rot[4];
2049 f2 = fraction + .01f;
2051 f1 = fraction - .01f;
2055 CurvePoint(px->_xyzw.n, px->order-1, px->_knot.p, (
float*)px->_xyzw.p, f1, cw1 );
2056 CurvePoint(px->_xyzw.n, px->order-1, px->_knot.p, (
float*)px->_xyzw.p, f2, cw2 );
2057 vecdif3f(dir,cw2,cw1);
2058 vecnormalize3f(dir,dir);
2064 float perp[3], dirx[3], sine;
2065 memset(dirx,0,3*
sizeof(
float));
2067 veccross3f(perp,dirx,dir);
2068 sine = veclength3f(perp);
2071 float default_direction [4] = {1.0f, 0.0f, 0.0f, 0.0f};
2072 veccopy4f(rot,default_direction);
2074 float cosine, angle;
2075 vecnormalize3f(perp,perp);
2076 cosine = vecdot3f(dir,dirx);
2077 angle = atan2f(sine,cosine);
2078 veccopy3f(rot,perp);
2085 float perp[3],dir0[3];
2087 CurvePoint(px->_xyzw.n, px->order-1, px->_knot.p, (
float*)px->_xyzw.p, 0.0f, cw1 );
2088 CurvePoint(px->_xyzw.n, px->order-1, px->_knot.p, (
float*)px->_xyzw.p, .001f, cw2 );
2089 vecdif3f(dir0,cw2,cw1);
2090 vecnormalize3f(dir0,dir0);
2092 veccross3f(perp,dir,dir0);
2093 if(veclength3f(perp) == 0.0f){
2095 float default_direction [4] = {1.0f, 0.0f, 0.0f, 0.0f};
2096 veccopy4f(rot,default_direction);
2100 vecnormalize3f(perp,perp);
2101 cosine = vecdot3f(dir0,dir);
2102 angle = acosf(cosine);
2103 veccopy3f(rot,perp);
2107 veccopy4f(px->value_changed.c,rot);
2109 float default_direction [4] = {1.0f, 0.0f, 0.0f, 0.0f};
2110 veccopy4f(px->value_changed.c,default_direction);
2115 printf(
"do_NurbsOrientInt: set_fraction %f value_changed %f %f %f %f\n",fraction,
2116 px->value_changed.c[0],px->value_changed.c[1],px->value_changed.c[2],px->value_changed.c[3] );
2121void do_NurbsSurfaceInterpolator (
void *_node) {
2122 float uv[2], xyzw[4];
2128 if(node->_nodeType != NODE_NurbsSurfaceInterpolator)
return;
2132 if(node->_OK != TRUE){
2133 int i,j, n, nu, nv, nku, nkv;
2134 GLfloat *xyzw, *knotsu, *knotsv;
2136 nku = nkv = nu = nv = n = 0;
2137 xyzw = knotsu = knotsv = NULL;
2138 if(node->controlPoint){
2139 if(node->controlPoint->_nodeType == NODE_CoordinateDouble){
2143 xyzw = MALLOC(
void *, n * 4 *
sizeof(GLfloat));
2144 for(i=0;i<mfd->n;i++){
2146 xyzw[i*4 + j] = (float)mfd->p[i].c[j];
2149 }
else if(node->controlPoint->_nodeType == NODE_Coordinate){
2153 xyzw = MALLOC(
void *, n * 4 *
sizeof(GLfloat));
2154 for(i=0;i<mff->n;i++){
2156 xyzw[i*4 + j] = mff->p[i].c[j];
2164 if(node->weight.n && node->weight.n == n){
2167 m = min(node->weight.n, n);
2169 im = i < m ? i : m-1;
2170 w = node->weight.p[im];
2171 xyzw[i*4 + 3] = (float)w;
2174 for(i=0;i<n;i++) xyzw[i*4 + 3] = 1.0;
2176 nu = node->uDimension;
2177 nv = node->vDimension;
2178 if(nu * nv != n)
return;
2179 if(nu < node->uOrder)
return;
2180 if(nv < node->vOrder)
return;
2183 if(knotsOK(node->uOrder,nu,node->uKnot.n,node->uKnot.p)){
2186 nku = node->uKnot.n;
2187 knotsu = MALLOC(
void *, nku *
sizeof(GLfloat));
2189 knotsu[i] = (GLfloat)node->uKnot.p[i];
2193 printf(
"good u knot vector nk=%d\n",nku);
2194 for(ii=0;ii<nku;ii++)
2195 printf(
"[%d]=%f \n",ii,knotsu[ii]);
2200 static int once = 0;
2201 nku = nu + node->uOrder ;
2203 knotsu = MALLOC(
void *, nku *
sizeof(GLfloat));
2204 generateUniformKnotVector(node->uOrder,nu, knotsu);
2207 printf(
"bad u knot vector given, replacing with:\n");
2208 for(ii=0;ii<nku;ii++)
2209 printf(
"[%d]=%f \n",ii,knotsu[ii]);
2215 if(knotsOK(node->vOrder,nv,node->vKnot.n,node->vKnot.p)){
2217 nkv = node->vKnot.n;
2218 knotsv = MALLOC(
void *, nkv *
sizeof(GLfloat));
2220 knotsv[i] = (GLfloat)node->vKnot.p[i];
2224 printf(
"good v knot vector nk=%d\n",nkv);
2225 for(ii=0;ii<nkv;ii++)
2226 printf(
"[%d]=%f \n",ii,knotsv[ii]);
2230 static int once = 0;
2232 nkv = nv + node->vOrder ;
2234 knotsv = MALLOC(
void *, nkv *
sizeof(GLfloat));
2235 generateUniformKnotVector(node->vOrder,nv, knotsv);
2238 printf(
"bad v knot vector given, replacing with:\n");
2239 for(ii=0;ii<nkv;ii++)
2240 printf(
"[%d]=%f \n",ii,knotsv[ii]);
2245 node->_controlPoint.p = (
struct SFVec4f*)xyzw;
2246 node->_controlPoint.n = n;
2247 node->_uKnot.p = knotsu;
2248 node->_uKnot.n = nku;
2249 node->_vKnot.p = knotsv;
2250 node->_vKnot.n = nkv;
2256 if(!node->_OK)
return;
2258 veccopy2f(uv,node->set_fraction.c);
2260 ok = SurfacePoint(node->uDimension,node->uOrder-1,node->_uKnot.p,
2261 node->vDimension,node->vOrder-1,node->_vKnot.p,
2262 (
float *)node->_controlPoint.p,uv[1],uv[0],xyzw);
2264 veccopy3f(node->position_changed.c,xyzw);
2268 float udir[3], vdir[3], normal[3], xyz1[4];
2269 ok = SurfacePoint(node->uDimension,node->uOrder-1,node->_uKnot.p,
2270 node->vDimension,node->vOrder-1,node->_vKnot.p,
2271 (
float *)node->_controlPoint.p,uv[1],uv[0]+.01f,xyz1);
2272 vecdif3f(udir,xyz1,xyzw);
2273 ok = SurfacePoint(node->uDimension,node->uOrder-1,node->_uKnot.p,
2274 node->vDimension,node->vOrder-1,node->_vKnot.p,
2275 (
float *)node->_controlPoint.p,uv[1]+.01f,uv[0],xyz1);
2276 vecdif3f(vdir,xyz1,xyzw);
2277 veccross3f(normal,udir,vdir);
2278 vecnormalize3f(normal,normal);
2279 veccopy3f(node->normal_changed.c,normal);
2288 printf (
"Pos/Col, new value (%f %f %f)\n",
2289 px->value_changed.c[0],px->value_changed.c[1],px->value_changed.c[2]);
2301 int nt, np,ic,j,i,k;
2302 double *xyzp, *xyzt;
2312 controlPoint = (
struct X3D_Coordinate*)createNewX3DNode(NODE_Coordinate);
2313 node->_patch = X3D_NODE(patch);
2314 patch->controlPoint = X3D_NODE(controlPoint);
2322 nt = trajectoryxz->controlPoint.n;
2323 np = profileyz->controlPoint.n;
2324 xyzp = (
double*)profileyz->controlPoint.p;
2325 xyzt = (
double*)trajectoryxz->controlPoint.p;
2326 xyz = MALLOC(
float*,nt * np * 3 *
sizeof(
float));
2327 controlPoint->point.p = (
struct SFVec3f*)xyz;
2328 controlPoint->point.n = nt * np;
2332 double2float(pt,&xyzt[j*2],2);
2335 float cosine, sine, swingangle;
2336 double2float(pp,&xyzp[2*i],2);
2337 swingangle = atan2f(pt[1],pt[0]);
2338 cosine = cosf(swingangle);
2339 sine = sinf(swingangle);
2340 xyz[ic*3 + 0] = pt[0] + cosine * pp[0];
2341 xyz[ic*3 + 1] = pp[1];
2342 xyz[ic*3 + 2] = pt[1] + sine * pp[0];
2346 patch->solid = node->solid;
2348 patch->uDimension = np;
2349 patch->uKnot.p = malloc(profileyz->knot.n *
sizeof(
double));
2350 memcpy(patch->uKnot.p,profileyz->knot.p,profileyz->knot.n *
sizeof(
double));
2351 patch->uKnot.n = profileyz->knot.n;
2352 patch->uOrder = profileyz->order;
2353 patch->uTessellation = (int)((
float)profileyz->tessellation * profileyz->_tscale);
2355 patch->vDimension = nt;
2356 patch->vKnot.p = malloc(trajectoryxz->knot.n *
sizeof(
double));
2357 memcpy(patch->vKnot.p,trajectoryxz->knot.p,trajectoryxz->knot.n *
sizeof(
double));
2358 patch->vKnot.n = trajectoryxz->knot.n;
2359 patch->vOrder = trajectoryxz->order;
2360 patch->vTessellation = (int)((
float)trajectoryxz->tessellation * profileyz->_tscale);
2365 printf(
"%f %f %f,",xyz[ic*3 + 0], xyz[ic*3 +1], xyz[ic*3 +2]);
2370 printf(
"uDimension=%d vDimension=%d nc=%d\n",np,nt,ic);
2376 if (!node->_intern)
return;
2377 render_ray_polyrep(node->_patch);
2382 if (!node->_intern)
return;
2383 collide_genericfaceset(X3D_INDEXEDFACESET(node->_patch));
2389 if (!node->_patch->_intern)
2392 CULL_FACE(patch->solid)
2393 render_polyrep(X3D_NODE(patch));
2398int compute_tessellation(
int tessellation,
int order,
int ncontrol ){
2405 ntessu = tessellation;
2408 mtessu = max(mtessu,ntessu+1);
2410 mtessu = max(mtessu,(-ntessu * ncontrol) + 1);
2412 mtessu = max(mtessu,2*ncontrol + 1);
2415void compute_knotvector(
int order,
int ncontrol,
int nknots,
double *knots,
int *newnknots,
float **newknots,
float *range){
2421 if(knotsOK(order,ncontrol,nknots,knots)){
2425 knotsu = MALLOC(
void *, nku *
sizeof(GLfloat));
2427 knotsu[i] = (GLfloat)knots[i];
2430 printf(
"good u knot vector nk=%d\n",nku);
2431 for(ii=0;ii<nku;ii++)
2432 printf(
"[%d]=%f \n",ii,knotsu[ii]);
2438 static int once = 0;
2439 nku = ncontrol + order ;
2441 knotsu = MALLOC(
void *, nku *
sizeof(GLfloat));
2442 generateUniformKnotVector(order,ncontrol, knotsu);
2444 printf(
"bad u knot vector given, replacing with:\n");
2445 for(ii=0;ii<nku;ii++)
2446 printf(
"[%d]=%f \n",ii,knotsu[ii]);
2453 range[0] = knotsu[0];
2454 range[1] = knotsu[nku-1];
2456void compute_weightedcontrol(
double *xyz,
int dim,
int nc,
int nweight,
double *weights,
float **cxyzw){
2466 xyzw = MALLOC(
float *, nc * 4 *
sizeof(GLfloat));
2468 xyzw[i*4 +0] = xyzw[i*4 +1] =xyzw[i*4 +2] =xyzw[i*4 +3] = 0.0f;
2471 xyzw[i*4 + j] = (float)xyz[i*dim + j];
2473 xyzw[i*4 + 3] = 1.0f;
2475 if(nweight && nweight == nc ){
2477 float wt = (float)weights[i];
2479 vecscale3f(&xyzw[i*4],&xyzw[i*4],wt);
2484void compute_doublecontrol(
struct X3D_Node *controlPoint,
int *nc,
double** xyz ){
2489 double *xyzd = NULL;
2491 switch(controlPoint->_nodeType){
2492 case NODE_Coordinate:
2495 n = tcoord->point.n;
2496 xyzd = MALLOC(
double *,n * 3 *
sizeof(
double));
2497 for(i=0;i<tcoord->point.n;i++)
2498 float2double(&xyzd[i*3],tcoord->point.p[i].c,3);
2501 case NODE_CoordinateDouble:
2504 n = tcoord->point.n;
2505 xyzd = MALLOC(
double *,n * 3 *
sizeof(
double));
2506 for(i=0;i<tcoord->point.n;i++)
2507 veccopyd(&xyzd[i*3],tcoord->point.p[i].c);
2518float *vecabs3f(
float *res,
float *p){
2521 res[i] = fabsf(p[i]);
2524int ivecdominantdirection3f(
int *irank,
float *p){
2525 float rmax, rmin, vabs[3];
2528 rmax = max(vabs[0],max(vabs[1],vabs[2]));
2529 rmin = min(vabs[0],min(vabs[1],vabs[2]));
2532 if(vabs[i] == rmax) {
2536 if(vabs[i] == rmin) irank[i] = 0;
2540void convert_mesh_to_polyrep(
float *xyz,
int npts,
float *nxyz,
int* tindex,
int ntri,
struct X3D_Node *node){
2553 FREE_IF_NZ(polyrep->cindex);
2554 FREE_IF_NZ(polyrep->actualCoord);
2555 FREE_IF_NZ(polyrep->GeneratedTexCoords[0]);
2556 FREE_IF_NZ(polyrep->colindex);
2557 FREE_IF_NZ(polyrep->color);
2558 FREE_IF_NZ(polyrep->norindex);
2559 FREE_IF_NZ(polyrep->normal);
2560 FREE_IF_NZ(polyrep->flat_normal);
2561 FREE_IF_NZ(polyrep->tcindex);
2564 node->_intern = (
struct X3D_GeomRep*) create_polyrep();
2566 rep_ = polyrep = (
struct X3D_PolyRep*) node->_intern;
2579 rep_->actualCoord = xyz;
2580 rep_->normal = nxyz;
2586 rep_->cindex = tindex;
2587 norindex = rep_->norindex = MALLOC(GLuint *,
sizeof(GLuint)*3*ntri);
2588 memcpy(norindex,tindex,
sizeof(GLuint)*3*ntri);
2595 if (polyrep->ntri != 0) {
2597 stream_polyrep(node, NULL,NULL,NULL,NULL, NULL);
2601 polyrep->irep_change = node->_change;
2658 compute_doublecontrol(trajectory->controlPoint,&nt,&xyzt);
2661 np = xsection->controlPoint.n;
2662 xyzx = (
double*)xsection->controlPoint.p;
2694 if(!strcmp(node->method->strptr,
"FULL"))
2696 if(!strcmp(node->method->strptr,
"TRANSLATE"))
2698 if(
false && node->_method == 1){
2711 controlPoint = (
struct X3D_Coordinate*) createNewX3DNode(NODE_Coordinate);
2712 node->_patch = X3D_NODE(patch);
2713 patch->controlPoint = X3D_NODE(controlPoint);
2715 xyz = MALLOC(
float*,nt * np * 3 *
sizeof(
float));
2716 controlPoint->point.p = (
struct SFVec3f*) xyz;
2717 controlPoint->point.n = nt * np;
2722 double2float(pt,&xyzt[j*3],3);
2725 double2float(pp,&xyzx[2*i],2);
2726 xyz[ic*3 + 0] = pt[0] + pp[0];
2727 xyz[ic*3 + 1] = pt[1] + pp[1];
2728 xyz[ic*3 + 2] = pt[2];
2734 if((trajectory->weight.n && trajectory->weight.n == nt) ||
2735 (xsection->weight.n && xsection->weight.n == np)){
2738 weight = MALLOC(
double*,nt * np *
sizeof(
double));
2740 double wtTj = trajectory->weight.p[j];
2742 weight[j*np + i] = wtTj * xsection->weight.p[i];
2748 patch->weight.p = weight;
2749 patch->weight.n = nt * np;
2751 patch->solid = node->solid;
2753 patch->uDimension = np;
2754 patch->uKnot.p = malloc(xsection->knot.n *
sizeof(
double));
2755 memcpy(patch->uKnot.p,xsection->knot.p,xsection->knot.n *
sizeof(
double));
2756 patch->uKnot.n = xsection->knot.n;
2757 patch->uOrder = xsection->order;
2758 patch->uTessellation = (int)((
float)xsection->tessellation * xsection->_tscale);
2760 patch->vDimension = nt;
2761 patch->vKnot.p = malloc(xsection->knot.n *
sizeof(
double));
2762 memcpy(patch->vKnot.p,trajectory->knot.p,trajectory->knot.n *
sizeof(
double));
2763 patch->vKnot.n = trajectory->knot.n;
2764 patch->vOrder = trajectory->order;
2765 patch->vTessellation = (int)((
float)trajectory->tessellation * trajectory->_tscale);
2770 printf(
"%f %f %f,",xyz[ic*3 + 0], xyz[ic*3 +1], xyz[ic*3 +2]);
2775 printf(
"uDimension=%d vDimension=%d nc=%d\n",np,nt,ic);
2779 if(
true || node->_method == 2){
2781 int mtessv, mtessu, nku, nkv;
2783 float *knotsu,*knotsv,*xyzwu,*xyzwv, urange[2],vrange[2];
2784 float *Tv, *Tangentv, *Bup, *pts;
2793 int mtessu1, mtessv1;
2795 mtessu = compute_tessellation(xsection->tessellation,xsection->order,np);
2796 mtessu = (int)((
float)mtessu * xsection->_tscale);
2797 mtessv = compute_tessellation(trajectory->tessellation,trajectory->order,nt);
2798 mtessv = (int)((
float)mtessv * trajectory->_tscale);
2799 compute_knotvector(xsection->order,np,xsection->knot.n,xsection->knot.p,&nku,&knotsu,urange);
2800 compute_knotvector(trajectory->order,nt,trajectory->knot.n,trajectory->knot.p,&nkv,&knotsv,vrange);
2801 compute_weightedcontrol(xyzt,3,nt, trajectory->weight.n, trajectory->weight.p, &xyzwv);
2802 compute_weightedcontrol(xyzx,2,np, xsection->weight.n, xsection->weight.p, &xyzwu);
2806 printf(
"np %d mtessu %d nku %d, nt %d mtessv %d, nkv %d",np,mtessu,nku,nt,mtessv,nkv);
2807 printf(
"trajectory nt %d points:\n",nt);
2809 printf(
"%d %f %f %f %f\n",i,xyzwv[i*4 + 0],xyzwv[i*4 + 1],xyzwv[i*4 + 2],xyzwv[i*4 + 3]);
2810 printf(
"xsection np %d points:\n",np);
2812 printf(
"%d %f %f %f %f\n",i,xyzwu[i*4 + 0],xyzwu[i*4 + 1],xyzwu[i*4 + 2],xyzwu[i*4 + 3]);
2822 mtessu1 = mtessu + 1;
2823 mtessv1 = mtessv + 1;
2824 Tv = MALLOC(
float*,(mtessv1)*3*
sizeof(
float));
2825 Tangentv = MALLOC(
float*,(mtessv1)*3*
sizeof(
float));
2826 Bup = MALLOC(
float*,(mtessv1)*3*
sizeof(
float));
2827 for(i=0;i<mtessv1;i++){
2828 float cw[4], cw1[4], delta[3], v;
2829 v = (float)i*(vrange[1]-vrange[0])/(float)mtessv;
2830 CurvePoint(nt, trajectory->order-1, knotsv, xyzwv, v, cw );
2831 veccopy3f(&Tv[i*3],cw);
2833 CurvePoint(nt, trajectory->order-1, knotsv, xyzwv, v+.01f, cw1 );
2834 vecdif3f(delta,cw1,cw);
2836 vecnormalize3f(delta,delta);
2837 veccopy3f(&Tangentv[i*3],delta);
2841 int k,irank[3],idom, inondom;
2842 float perp[3], perp2[3];
2843 idom = ivecdominantdirection3f(irank,delta);
2844 inondom = idom + 1 > 2 ? 0 : idom + 1;
2845 for(k=0;k<3;k++)
if(irank[k] == 0) inondom = k;
2846 memset(perp,0,3*
sizeof(
float));
2847 perp[inondom] = 1.0;
2848 veccross3f(perp2,delta,perp);
2849 veccross3f(perp,perp2,delta);
2851 veccopy3f(&Bup[i*3],perp);
2855 float bi[3], bi1dotti, tiscaled[3];
2856 bi1dotti = vecdot3f(&Bup[(i-1)*3],&Tangentv[i*3]);
2857 vecdif3f(bi,&Bup[(i-1)*3],vecscale3f(tiscaled,&Tangentv[i*3],bi1dotti));
2858 vecnormalize3f(&Bup[i*3],bi);
2862 printf(
"trajectory T:\n");
2863 for(i=0;i<mtessv1;i++){
2864 printf(
"%d [%f %f %f] \n",i,
2865 Tv[i*3 +0],Tv[i*3 +1],Tv[i*3 +2]);
2867 printf(
"trajectory T', B:\n");
2868 for(i=0;i<mtessv1;i++){
2869 printf(
"%d [%f %f %f] [%f %f %f] \n",i,
2870 Tangentv[i*3 +0],Tangentv[i*3 +1],Tangentv[i*3 +2],
2871 Bup[i*3 +0],Bup[i*3 +1],Bup[i*3 +2]);
2879 Qu = MALLOC(
float*,(mtessu+1)*3*
sizeof(
float));
2880 Nu = MALLOC(
float*,(mtessu+1)*3*
sizeof(
float));
2881 if(DBGSW) printf(
"Xsection tess pts:\n");
2882 for(i=0;i<mtessu1;i++){
2883 float u, cw[4], cw1[4], delta[3], normal[3];
2884 float zzz[3] = {0.0f,0.0f,1.0f};
2885 u = (float)i*(urange[1]-urange[0])/(float)mtessu;
2886 CurvePoint(np, xsection->order-1, knotsu, xyzwu, u, cw );
2887 veccopy3f(&Qu[i*3],cw);
2888 CurvePoint(np, xsection->order-1, knotsu, xyzwu, u+.01f, cw1 );
2889 vecdif3f(delta,cw1,cw);
2890 vecnormalize3f(delta,delta);
2891 veccross3f(normal,zzz,delta);
2892 veccopy3f(&Nu[i*3],normal);
2893 if(DBGSW) printf(
"%d %f %f %f\n",i,Qu[i*3 +0],Qu[i*3 +1],Qu[i*3 +2]);
2899 pts = MALLOC(
float*,mtessu1 * mtessv1 * 3 *
sizeof(
float));
2900 normals = MALLOC(
float*,mtessu1 * mtessv1 * 3 *
sizeof(
float));
2901 idx = MALLOC(
int *, mtessu * mtessv * 2 * 3 *
sizeof(
int));
2904 for(i=0;i<mtessv1;i++){
2906 float mat[9], matt[9];
2911 veccross3f(&mat[0],&Bup[i*3],&Tangentv[i*3]);
2912 veccopy3f(&mat[3],&Bup[i*3]);
2913 veccopy3f(&mat[6],&Tangentv[i*3]);
2914 mattranspose3f(matt,mat);
2922 if (node->_method == 1) {
2925 memcpy(matB0,mat,9*
sizeof(
float));
2927 matmultiply3f(mat,matt,matB0);
2928 if (node->_method == 1) {
2931 for(j=0;j<mtessu1;j++){
2932 float pp[3], norm[3], qq[3];
2933 matmultvec3f(pp, mat, &Qu[j*3] );
2936 vecadd3f(qq, &Nu[j * 3], &Qu[j * 3]);
2937 matmultvec3f(qq, mat, qq);
2938 vecdif3f(norm, pp, qq);
2939 vecnormalize3f(norm, norm);
2940 veccopy3f(&normals[ic * 3], norm);
2943 vecadd3f(pp,pp,&Tv[i*3]);
2944 veccopy3f(&pts[ic*3],pp);
2945 if (node->_method == 1) {
2946 float tt[3], ee[3], ff[3], ii[3];
2951 vecset3f(ff, 0.0f, 0.0f, 1.0f);
2953 veccopy3f(ee, &Nu[j * 3]);
2955 if (i == 0) vecdif3f(tt, &Tv[(i+1) * 3], &Tv[i * 3]);
2956 else vecdif3f(tt, &Tv[i * 3], &Tv[(i - 1) * 3]);
2958 veccross3f(ii, ff, ee);
2959 veccross3f(norm, ii, tt);
2960 vecnormalize3f(norm, norm);
2961 veccopy3f(&normals[ic * 3], norm);
2970 for(j=0;j<mtessu;j++){
2987 printf(
"ntri %d triangle indexes:\n",ntri);
2988 for(i=0;i<ntri;i++){
2992 printf(
"%d ",idx[i*3 +j]);
2996 printf(
"triangle vertices:\n");
2997 for(i=0;i<ntri;i++){
3001 int ix = idx[i*3 +j];
3002 veccopy3f(pt,&pts[ix*3]);
3003 printf(
"%d %d %f %f %f\n",i,ix,pt[0],pt[1],pt[2]);
3009 convert_mesh_to_polyrep(pts,ic,normals,idx,ntri,X3D_NODE(node));
3015 if(node->_method == 1){
3016 if (!node->_patch)
return;
3017 render_ray_polyrep(node->_patch);
3019 if(node->_method == 2){
3020 if(!node->_intern)
return;
3021 render_ray_polyrep(node);
3027 if(node->_method == 1){
3028 if (!node->_patch)
return;
3029 collide_genericfaceset(X3D_INDEXEDFACESET(node->_patch));
3031 if(node->_method == 2){
3032 if (!node->_intern)
return;
3033 collide_genericfaceset(X3D_INDEXEDFACESET(node));
3039 if(
false && node->_method == 1){
3041 if (!node->_patch->_intern)
3044 CULL_FACE(patch->solid)
3045 render_polyrep(patch);
3047 if(true || node->_method == 2){
3051 render_polyrep(node);
3059 for(i=0;i<node->geometry.n;i++){
3061 switch(gn->_nodeType){
3062 case NODE_NurbsCurve:
3065 g->_tscale = node->tessellationScale;
3069 case NODE_NurbsCurve2D:
3072 g->_tscale = node->tessellationScale;
3076 case NODE_NurbsPatchSurface:
3079 g->_tscale = node->tessellationScale;
3083 case NODE_NurbsTrimmedSurface:
3086 g->_tscale = node->tessellationScale;
3090 case NODE_NurbsSweptSurface:
3093 if(g->_method == 1){
3096 patch->_tscale = node->tessellationScale;
3100 if(g->_method == 2){
3102 curve->_tscale = node->tessellationScale;
3103 MNX(g->crossSectionCurve);
3105 curve->_tscale = node->tessellationScale;
3106 MNX(g->trajectoryCurve);
3110 case NODE_NurbsSwungSurface:
3115 patch->_tscale = node->tessellationScale;
3138void do_NurbsPositionInterpolator (
void *node) {}
3139void do_NurbsOrientationInterpolator (
void *node){}
3140void do_NurbsSurfaceInterpolator (
void *_node){}