/******************************Module*Header*******************************\ * Module Name: eval.c * * OpenGL Evaluator functions on the client side. * * Created: * Author: * * Copyright (c) 1993 Microsoft Corporation \**************************************************************************/ #include "precomp.h" #pragma hdrstop #include "glsbcltu.h" #include "glclt.h" #include "compsize.h" #include "glsize.h" #include "context.h" #include "global.h" #include "attrib.h" #include "imports.h" //////////////////////////////////////////////////////////////////// // Stuff needed for PA_EvalMesh2 /////////////////////////////////// //////////////////////////////////////////////////////////////////// #define MV_VERTEX3 0x0001 #define MV_VERTEX4 0x0002 #define MV_NORMAL 0x0004 #define MV_COLOR 0x0008 #define MV_INDEX 0x0010 #define MV_TEXTURE1 0x0020 #define MV_TEXTURE2 0x0040 #define MV_TEXTURE3 0x0080 #define MV_TEXTURE4 0x0100 // Assumption: U is moving, left to right. V is moving top to bottom #define MV_TOP 0x0001 #define MV_LEFT 0x0002 typedef struct { __GLcoord vertex; __GLcoord normal; __GLcoord texture; __GLcolor color; } MESHVERTEX; #define MAX_MESH_VERTICES MAX_U_SIZE*MAX_V_SIZE #define MAX_U_SIZE 16 #define MAX_V_SIZE 16 GLubyte *dBufFill; //fill only GLuint totFillPts; GLubyte *dBufTopLeft; //for mv_left GLuint totTopLeftPts; GLubyte *dBufTopRight; //for non mv_left GLuint totTopRightPts; ////////////////////////////////////////////////////////////////////// /// Function Prototypes ////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// void FASTCALL PADoEval1(__GLcontext *, __GLfloat); void FASTCALL PADoEval2(__GLcontext *, __GLfloat, __GLfloat); void FASTCALL PADoEval2VArray(__GLcontext *, __GLfloat, __GLfloat, MESHVERTEX *, GLuint *); static void PreEvaluate(GLint , __GLfloat , __GLfloat *); static void PreEvaluateWithDeriv(GLint, __GLfloat, __GLfloat *, __GLfloat *); void DoDomain2(__GLevaluatorMachine *, __GLfloat, __GLfloat, __GLevaluator2 *, __GLfloat *, __GLfloat *); void DoDomain2WithDerivs(__GLevaluatorMachine *, __GLfloat, __GLfloat, __GLevaluator2 *, __GLfloat *, __GLfloat *, __GLfloat *, __GLfloat *); int FASTCALL genMeshElts (GLenum, GLuint, GLint, GLint, GLubyte *); void FASTCALL PA_EvalMesh2Fast(__GLcontext *, GLint, GLint, GLint, GLint, GLint, GLenum, GLuint); void glcltColor4fv_Eval (__GLfloat *c4); void glcltIndexf_Eval (__GLfloat ci); void glcltNormal3fv_Eval(__GLfloat *n3); void glcltTexCoord1fv_Eval(__GLfloat *t1); void glcltTexCoord2fv_Eval(__GLfloat *t2); void glcltTexCoord3fv_Eval(__GLfloat *t3); void glcltTexCoord4fv_Eval(__GLfloat *t4); /************************************************************************/ /********************** Client-side entry points ************************/ /********************** for 1-D Evaluators ************************/ /************************************************************************/ void APIENTRY glcltEvalMesh1 ( IN GLenum mode, IN GLint u1, IN GLint u2 ) { __GL_SETUP (); POLYARRAY *pa; GLenum primType; GLint i; WORD flags = (WORD) GET_EVALSTATE (gc); __GLfloat u; __GLfloat du; __GLevaluatorGrid *gu; // Not allowed in begin/end. pa = GLTEB_CLTPOLYARRAY(); if (pa->flags & POLYARRAY_IN_BEGIN) { GLSETERROR(GL_INVALID_OPERATION); return; } switch(mode) { case GL_LINE: primType = GL_LINE_STRIP; break; case GL_POINT: primType = GL_POINTS; break; default: GLSETERROR(GL_INVALID_ENUM); return; } // if there are any pending API calls that affect the Evaluator state // then flush the message buffer if (flags & (__EVALS_AFFECTS_1D_EVAL| __EVALS_AFFECTS_ALL_EVAL)) glsbAttention(); gu = &gc->state.evaluator.u1; //du = (gu->finish - gu->start)/(__GLfloat)gu->n; du = gu->step; // Call Begin/End. glcltBegin(primType); for (i = u1; i <= u2; i++) { u = (i == gu->n) ? gu->finish : (gu->start + i * du); PADoEval1(gc, u); } glcltEnd(); } void APIENTRY glcltEvalPoint1 ( IN GLint i ) { __GL_SETUP (); POLYARRAY *pa; __GLfloat u; __GLfloat du; __GLevaluatorGrid *gu; // This call has no effect outside begin/end // (unless it is being compiled). pa = GLTEB_CLTPOLYARRAY(); if (!(pa->flags & POLYARRAY_IN_BEGIN)) { return; } gu = &gc->state.evaluator.u1; du = gu->step; //du = (gu->finish - gu->start)/(__GLfloat)gu->n; u = (i == gu->n) ? gu->finish : (gu->start + i * du); PADoEval1(gc, u); } void APIENTRY glcltEvalCoord1f ( IN GLfloat u ) { __GL_SETUP (); POLYARRAY *pa; // This call has no effect outside begin/end // (unless it is being compiled). pa = GLTEB_CLTPOLYARRAY(); // If not in Begin-End block, return without doing anything if (!(pa->flags & POLYARRAY_IN_BEGIN)) { return; } PADoEval1(gc, u); } void APIENTRY glcltEvalCoord1d ( IN GLdouble u ) { glcltEvalCoord1f((GLfloat) u); } void APIENTRY glcltEvalCoord1dv ( IN const GLdouble u[1] ) { glcltEvalCoord1f((GLfloat) u[0]); } void APIENTRY glcltEvalCoord1fv ( IN const GLfloat u[1] ) { glcltEvalCoord1f((GLfloat) u[0]); } void APIENTRY glcltMapGrid1d ( IN GLint un, IN GLdouble u1, IN GLdouble u2 ) { glcltMapGrid1f(un, (GLfloat) u1, (GLfloat) u2); } void APIENTRY glcltMapGrid1f ( IN GLint un, IN GLfloat u1, IN GLfloat u2 ) { POLYARRAY *pa; __GL_SETUP (); WORD flags = (WORD) GET_EVALSTATE (gc); // Check if it is called inside a Begin-End block // If we are already in the begin/end bracket, return an error. pa = GLTEB_CLTPOLYARRAY(); if (pa->flags & POLYARRAY_IN_BEGIN) { GLSETERROR(GL_INVALID_OPERATION); return; } // if there are any pending API calls that affect the Evaluator state // then flush the message buffer if (flags & (__EVALS_PUSH_EVAL_ATTRIB | __EVALS_POP_EVAL_ATTRIB)) glsbAttention (); #ifdef NT if (un <= 0) { __glSetError(GL_INVALID_VALUE); return; } #endif gc->state.evaluator.u1.start = (__GLfloat)u1; gc->state.evaluator.u1.finish = (__GLfloat)u2; gc->state.evaluator.u1.n = un; gc->state.evaluator.u1.step = ((__GLfloat)u2 - (__GLfloat)u1)/(__GLfloat)un; } void APIENTRY glcltMap1d ( IN GLenum target, IN GLdouble u1, IN GLdouble u2, IN GLint stride, IN GLint order, IN const GLdouble points[] ) { __GLevaluator1 *ev; __GLfloat *data; POLYARRAY *pa; __GL_SETUP (); // Check if it is called inside a Begin-End block // If we are already in the begin/end bracket, return an error. pa = GLTEB_CLTPOLYARRAY(); if (pa->flags & POLYARRAY_IN_BEGIN) { GLSETERROR(GL_INVALID_OPERATION); return; } ev = __glSetUpMap1(gc, target, order, u1, u2); if (ev == 0) { return; } if (stride < ev->k) { __glSetError(GL_INVALID_VALUE); return; } data = gc->eval.eval1Data[__GL_EVAL1D_INDEX(target)]; __glFillMap1d(ev->k, order, stride, points, data); } void APIENTRY glcltMap1f ( IN GLenum target, IN GLfloat u1, IN GLfloat u2, IN GLint stride, IN GLint order, IN const GLfloat points[] ) { __GLevaluator1 *ev; __GLfloat *data; POLYARRAY *pa; __GL_SETUP (); // Check if it is called inside a Begin-End block // If we are already in the begin/end bracket, return an error. pa = GLTEB_CLTPOLYARRAY(); if (pa->flags & POLYARRAY_IN_BEGIN) { GLSETERROR(GL_INVALID_OPERATION); return; } ev = __glSetUpMap1(gc, target, order, u1, u2); if (ev == 0) { return; } if (stride < ev->k) { __glSetError(GL_INVALID_VALUE); return; } data = gc->eval.eval1Data[__GL_EVAL1D_INDEX(target)]; __glFillMap1f(ev->k, order, stride, points, data); } /************************************************************************/ /********************** Client-side entry points ************************/ /********************** for 2-D Evaluators ************************/ /************************************************************************/ void APIENTRY glcltEvalMesh2 ( IN GLenum mode, IN GLint u1, IN GLint u2, IN GLint v1, IN GLint v2 ) { POLYARRAY *pa; GLint i, j, meshSize; __GL_SETUP(); GLboolean done_v, done_u; GLint v_beg, v_end, u_beg, u_end, u_len; GLuint sides; WORD flags = (WORD) GET_EVALSTATE (gc); // Flush the command buffer before we start. We need to access the // latest evaluator states in this function. // if there are any pending API calls that affect the Evaluator state // then flush the message buffer if (flags & (__EVALS_AFFECTS_2D_EVAL| __EVALS_AFFECTS_ALL_EVAL)) glsbAttention (); // Not allowed in begin/end. pa = gc->paTeb; if (pa->flags & POLYARRAY_IN_BEGIN) { GLSETERROR(GL_INVALID_OPERATION); return; } // If vertex map is not enabled, this is a noop. if (!(gc->state.enables.eval2 & (__GL_MAP2_VERTEX_4_ENABLE | __GL_MAP2_VERTEX_3_ENABLE))) return; // Make sure that the mesh is not empty. if (u1 > u2 || v1 > v2) return; if (mode == GL_FILL && dBufFill == NULL) { if (!(dBufFill = (GLubyte *) ALLOC ( 4 * MAX_U_SIZE * MAX_V_SIZE * sizeof (GLubyte)))) { GLSETERROR(GL_OUT_OF_MEMORY); return; } totFillPts = genMeshElts (GL_FILL, MV_TOP | MV_LEFT, MAX_U_SIZE, MAX_V_SIZE, dBufFill); } if (mode == GL_LINE && dBufTopLeft == NULL) { if (!(dBufTopLeft = (GLubyte *) ALLOC ( 2 * 4 * MAX_U_SIZE * MAX_V_SIZE * sizeof (GLubyte)))) { GLSETERROR(GL_OUT_OF_MEMORY); return; } dBufTopRight = &dBufTopLeft[4 * MAX_U_SIZE * MAX_V_SIZE]; totTopLeftPts = genMeshElts (GL_LINE, MV_TOP | MV_LEFT, MAX_U_SIZE, MAX_V_SIZE, dBufTopLeft); totTopRightPts = genMeshElts (GL_LINE, MV_TOP, MAX_U_SIZE, MAX_V_SIZE, dBufTopRight); } switch(mode) { case GL_POINT: glcltBegin(GL_POINTS); for (i = v1; i <= v2; i++) for (j = u1; j <= u2; j++) glcltEvalPoint2(j, i); glcltEnd(); break ; case GL_LINE: case GL_FILL: // the sides argument in the fastcall is ignored meshSize = (u2 - u1 + 1)*(v2 - v1 + 1); if (meshSize <= MAX_MESH_VERTICES) PA_EvalMesh2Fast(gc, u1, u2, v1, v2, meshSize, mode, (GLubyte) 15); else { u_beg = u1; u_end = u_beg + MAX_U_SIZE - 1; done_u = GL_FALSE; while (!done_u) { //Along U side if(u_end >= u2) { u_end = u2; done_u = GL_TRUE; } u_len = u_end - u_beg + 1; v_beg = v1; v_end = v_beg + MAX_V_SIZE - 1; done_v = GL_FALSE; while(!done_v) { //Along V side if(v_end >= v2) { v_end = v2; done_v = GL_TRUE; } meshSize = u_len*(v_end - v_beg + 1); sides = 0; if (u_beg == u1) sides |= MV_LEFT; if (v_beg == v1) sides |= MV_TOP; PA_EvalMesh2Fast(gc, u_beg, u_end, v_beg, v_end, meshSize, mode, sides); v_beg = v_end; v_end = v_beg+MAX_V_SIZE-1; } u_beg = u_end; u_end = u_beg + MAX_U_SIZE - 1; } } break ; default: GLSETERROR(GL_INVALID_ENUM); return; } } void APIENTRY glcltEvalCoord2f ( IN GLfloat u, IN GLfloat v ) { __GL_SETUP (); POLYARRAY *pa; // This call has no effect outside begin/end // (unless it is being compiled). pa = GLTEB_CLTPOLYARRAY(); if (!(pa->flags & POLYARRAY_IN_BEGIN)) { return; } PADoEval2(gc, u, v); } void APIENTRY glcltEvalCoord2d ( IN GLdouble u, IN GLdouble v ) { glcltEvalCoord2f((GLfloat) u, (GLfloat) v); } void APIENTRY glcltEvalCoord2dv ( IN const GLdouble u[2] ) { glcltEvalCoord2f((GLfloat) u[0], (GLfloat) u[1]); } void APIENTRY glcltEvalCoord2fv ( IN const GLfloat u[2] ) { glcltEvalCoord2f((GLfloat) u[0], (GLfloat) u[1]); } void APIENTRY glcltEvalPoint2 ( IN GLint i, IN GLint j ) { __GL_SETUP (); POLYARRAY *pa; __GLfloat u, v; __GLfloat du, dv; __GLevaluatorGrid *gu; __GLevaluatorGrid *gv; // This call has no effect outside begin/end // (unless it is being compiled). pa = GLTEB_CLTPOLYARRAY(); if (!(pa->flags & POLYARRAY_IN_BEGIN)) { return; } gu = &gc->state.evaluator.u2; gv = &gc->state.evaluator.v2; du = gu->step; dv = gv->step; //du = (gu->finish - gu->start)/(__GLfloat)gu->n; //dv = (gv->finish - gv->start)/(__GLfloat)gv->n; u = (i == gu->n) ? gu->finish : (gu->start + i * du); v = (j == gv->n) ? gv->finish : (gv->start + j * dv); PADoEval2 (gc, u, v); } void APIENTRY glcltMapGrid2d ( IN GLint un, IN GLdouble u1, IN GLdouble u2, IN GLint vn, IN GLdouble v1, IN GLdouble v2 ) { glcltMapGrid2f(un, (GLfloat) u1, (GLfloat) u2, vn, (GLfloat) v1, (GLfloat) v2); } void APIENTRY glcltMapGrid2f ( IN GLint un, IN GLfloat u1, IN GLfloat u2, IN GLint vn, IN GLfloat v1, IN GLfloat v2 ) { POLYARRAY *pa; __GL_SETUP (); WORD flags = (WORD) GET_EVALSTATE (gc); // Check if it is called inside a Begin-End block // If we are already in the begin/end bracket, return an error. pa = GLTEB_CLTPOLYARRAY(); if (pa->flags & POLYARRAY_IN_BEGIN) { GLSETERROR(GL_INVALID_OPERATION); return; } // if there are any pending API calls that affect the Evaluator state // then flush the message buffer if (flags & (__EVALS_PUSH_EVAL_ATTRIB| __EVALS_POP_EVAL_ATTRIB)) glsbAttention (); #ifdef NT if (un <= 0 || vn <= 0) { __glSetError(GL_INVALID_VALUE); return; } #endif gc->state.evaluator.u2.start = (__GLfloat)u1; gc->state.evaluator.u2.finish = (__GLfloat)u2; gc->state.evaluator.u2.n = un; gc->state.evaluator.u2.step = ((__GLfloat)u2 - (__GLfloat)u1)/(__GLfloat)un; gc->state.evaluator.v2.start = (__GLfloat)v1; gc->state.evaluator.v2.finish = (__GLfloat)v2; gc->state.evaluator.v2.n = vn; gc->state.evaluator.v2.step = ((__GLfloat)v2 - (__GLfloat)v1)/(__GLfloat)vn; } void APIENTRY glcltMap2d ( IN GLenum target, IN GLdouble u1, IN GLdouble u2, IN GLint ustride, IN GLint uorder, IN GLdouble v1, IN GLdouble v2, IN GLint vstride, IN GLint vorder, IN const GLdouble points[] ) { __GLevaluator2 *ev; __GLfloat *data; POLYARRAY *pa; __GL_SETUP (); // Check if it is called inside a Begin-End block // If we are already in the begin/end bracket, return an error. pa = GLTEB_CLTPOLYARRAY(); if (pa->flags & POLYARRAY_IN_BEGIN) { GLSETERROR(GL_INVALID_OPERATION); return; } ev = __glSetUpMap2(gc, target, uorder, vorder, u1, u2, v1, v2); if (ev == 0) { return; } if (ustride < ev->k) { __glSetError(GL_INVALID_VALUE); return; } if (vstride < ev->k) { __glSetError(GL_INVALID_VALUE); return; } data = gc->eval.eval2Data[__GL_EVAL2D_INDEX(target)]; __glFillMap2d(ev->k, uorder, vorder, ustride, vstride, points, data); } void APIENTRY glcltMap2f ( IN GLenum target, IN GLfloat u1, IN GLfloat u2, IN GLint ustride, IN GLint uorder, IN GLfloat v1, IN GLfloat v2, IN GLint vstride, IN GLint vorder, IN const GLfloat points[] ) { __GLevaluator2 *ev; __GLfloat *data; POLYARRAY *pa; __GL_SETUP (); // Check if it is called inside a Begin-End block // If we are already in the begin/end bracket, return an error. pa = GLTEB_CLTPOLYARRAY(); if (pa->flags & POLYARRAY_IN_BEGIN) { GLSETERROR(GL_INVALID_OPERATION); return; } ev = __glSetUpMap2(gc, target, uorder, vorder, u1, u2, v1, v2); if (ev == 0) { return; } if (ustride < ev->k) { __glSetError(GL_INVALID_VALUE); return; } if (vstride < ev->k) { __glSetError(GL_INVALID_VALUE); return; } data = gc->eval.eval2Data[__GL_EVAL2D_INDEX(target)]; __glFillMap2f(ev->k, uorder, vorder, ustride, vstride, points, data); } /************************************************************************/ /********************** Evaluator helper functions **********************/ /********************** taken from so_eval.c **********************/ /************************************************************************/ GLint FASTCALL __glEvalComputeK(GLenum target) { switch(target) { case GL_MAP1_VERTEX_4: case GL_MAP1_COLOR_4: case GL_MAP1_TEXTURE_COORD_4: case GL_MAP2_VERTEX_4: case GL_MAP2_COLOR_4: case GL_MAP2_TEXTURE_COORD_4: return 4; case GL_MAP1_VERTEX_3: case GL_MAP1_TEXTURE_COORD_3: case GL_MAP1_NORMAL: case GL_MAP2_VERTEX_3: case GL_MAP2_TEXTURE_COORD_3: case GL_MAP2_NORMAL: return 3; case GL_MAP1_TEXTURE_COORD_2: case GL_MAP2_TEXTURE_COORD_2: return 2; case GL_MAP1_TEXTURE_COORD_1: case GL_MAP2_TEXTURE_COORD_1: case GL_MAP1_INDEX: case GL_MAP2_INDEX: return 1; default: return -1; } } void ComputeNormal2(__GLcontext *gc, __GLfloat *n, __GLfloat *pu, __GLfloat *pv) { n[0] = pu[1]*pv[2] - pu[2]*pv[1]; n[1] = pu[2]*pv[0] - pu[0]*pv[2]; n[2] = pu[0]*pv[1] - pu[1]*pv[0]; #ifdef NT // Only need to normalize auto normals if normalization is not enabled! if (!(gc->state.enables.general & __GL_NORMALIZE_ENABLE)) #endif __glNormalize(n, n); } void ComputeFirstPartials(__GLfloat *p, __GLfloat *pu, __GLfloat *pv) { pu[0] = pu[0]*p[3] - pu[3]*p[0]; pu[1] = pu[1]*p[3] - pu[3]*p[1]; pu[2] = pu[2]*p[3] - pu[3]*p[2]; pv[0] = pv[0]*p[3] - pv[3]*p[0]; pv[1] = pv[1]*p[3] - pv[3]*p[1]; pv[2] = pv[2]*p[3] - pv[3]*p[2]; } /* ** define a one dimensional map */ __GLevaluator1 *__glSetUpMap1(__GLcontext *gc, GLenum type, GLint order, __GLfloat u1, __GLfloat u2) { __GLevaluator1 *ev; __GLfloat **evData; __GLfloat *pevData; switch (type) { case GL_MAP1_COLOR_4: case GL_MAP1_INDEX: case GL_MAP1_NORMAL: case GL_MAP1_TEXTURE_COORD_1: case GL_MAP1_TEXTURE_COORD_2: case GL_MAP1_TEXTURE_COORD_3: case GL_MAP1_TEXTURE_COORD_4: case GL_MAP1_VERTEX_3: case GL_MAP1_VERTEX_4: ev = &gc->eval.eval1[__GL_EVAL1D_INDEX(type)]; evData = &gc->eval.eval1Data[__GL_EVAL1D_INDEX(type)]; break; default: __glSetError(GL_INVALID_ENUM); return 0; } if (u1 == u2 || order < 1 || order > gc->constants.maxEvalOrder) { __glSetError(GL_INVALID_VALUE); return 0; } pevData = (__GLfloat *) GCREALLOC(gc, *evData, (__glMap1_size(ev->k, order) * sizeof(__GLfloat))); if (!pevData) { __glSetError(GL_OUT_OF_MEMORY); return 0; } *evData = pevData; ev->order = order; ev->u1 = u1; ev->u2 = u2; return ev; } /* ** define a two dimensional map */ __GLevaluator2 *__glSetUpMap2(__GLcontext *gc, GLenum type, GLint majorOrder, GLint minorOrder, __GLfloat u1, __GLfloat u2, __GLfloat v1, __GLfloat v2) { __GLevaluator2 *ev; __GLfloat **evData; __GLfloat *pevData; switch (type) { case GL_MAP2_COLOR_4: case GL_MAP2_INDEX: case GL_MAP2_NORMAL: case GL_MAP2_TEXTURE_COORD_1: case GL_MAP2_TEXTURE_COORD_2: case GL_MAP2_TEXTURE_COORD_3: case GL_MAP2_TEXTURE_COORD_4: case GL_MAP2_VERTEX_3: case GL_MAP2_VERTEX_4: ev = &gc->eval.eval2[__GL_EVAL2D_INDEX(type)]; evData = &gc->eval.eval2Data[__GL_EVAL2D_INDEX(type)]; break; default: __glSetError(GL_INVALID_ENUM); return 0; } if (minorOrder < 1 || minorOrder > gc->constants.maxEvalOrder || majorOrder < 1 || majorOrder > gc->constants.maxEvalOrder || u1 == u2 || v1 == v2) { __glSetError(GL_INVALID_VALUE); return 0; } pevData = (__GLfloat *) GCREALLOC(gc, *evData, (__glMap2_size(ev->k, majorOrder, minorOrder) * sizeof(__GLfloat))); if (!pevData) { __glSetError(GL_OUT_OF_MEMORY); return 0; } *evData = pevData; ev->majorOrder = majorOrder; ev->minorOrder = minorOrder; ev->u1 = u1; ev->u2 = u2; ev->v1 = v1; ev->v2 = v2; return ev; } /* ** Fill our data from user data */ void APIPRIVATE __glFillMap1f(GLint k, GLint order, GLint stride, const GLfloat *points, __GLfloat *data) { int i,j; #ifndef __GL_DOUBLE /* Optimization always hit during display list execution */ if (k == stride) { __GL_MEMCOPY(data, points, __glMap1_size(k, order) * sizeof(__GLfloat)); return; } #endif for (i=0; iu2 != e->u1, "Assert in DoDomain1 failed\n"); // assert(e->u2 != e->u1); #else if(e->u2 == e->u1) return; #endif uprime = (u - e->u1) / (e->u2 - e->u1); /* Use already cached values if possible */ if (em->uvalue != uprime || em->uorder != e->order) { /* Compute coefficients for values */ PreEvaluate(e->order, uprime, em->ucoeff); em->utype = TYPE_COEFF; em->uorder = e->order; em->uvalue = uprime; } k=e->k; for (j = 0; j < k; j++) { data=baseData+j; v[j] = 0; for (row = 0; row < e->order; row++) { v[j] += em->ucoeff[row] * (*data); data += k; } } } // Helper Macro used in PADoEval1 and PADoEval2 #ifdef __NO_OPTIMIZE_FOR_DLIST #define PropagateToNextPolyData (eval, pa) \ { \ if ((gc)->eval.accFlags & EVAL_COLOR_VALID) \ { \ (pa)->pdNextVertex->flags &= ~POLYDATA_EVAL_COLOR; \ if ((gc)->modes.colorIndexMode) \ glcltIndexf_InCI((gc)->eval.color.r); \ else \ glcltColor4f_InRGBA ((gc)->eval.color.r, \ (gc)->eval.color.g, \ (gc)->eval.color.b, \ (gc)->eval.color.a); \ } \ \ if ((gc)->eval.accFlags & EVAL_NORMAL_VALID) \ { \ (pa)->pdNextVertex->flags &= ~POLYDATA_EVAL_NORMAL; \ glcltNormal3f ((gc)->eval.normal.x, \ (gc)->eval.normal.y, \ (gc)->eval.normal.z); \ } \ \ if ((gc)->eval.accFlags & EVAL_TEXTURE_VALID) \ { \ (pa)->pdNextVertex->flags &= ~POLYDATA_EVAL_TEXCOORD; \ if (__GL_FLOAT_COMPARE_PONE((gc)->eval.texture.w, !=)) \ glcltTexCoord4f ((gc)->eval.texture.x, \ (gc)->eval.texture.y, \ (gc)->eval.texture.z, \ (gc)->eval.texture.w); \ else if (__GL_FLOAT_NEZ((gc)->eval.texture.z)) \ glcltTexCoord3f ((gc)->eval.texture.x, \ (gc)->eval.texture.y, \ (gc)->eval.texture.z); \ else if (__GL_FLOAT_NEZ((gc)->eval.texture.y)) \ glcltTexCoord2f ((gc)->eval.texture.x, \ (gc)->eval.texture.y); \ else \ glcltTexCoord1f ((gc)->eval.texture.x); \ } \ } #else #define PropagateToNextPolyData(eval,pa) \ \ if ((gc)->eval.accFlags & EVAL_COLOR_VALID) \ { \ (pa)->pdNextVertex->flags &= ~POLYDATA_EVAL_COLOR; \ if ((gc)->modes.colorIndexMode) \ glcltIndexf_InCI((gc)->eval.color.r); \ else \ glcltColor4f_InRGBA ((gc)->eval.color.r, \ (gc)->eval.color.g, \ (gc)->eval.color.b, \ (gc)->eval.color.a); \ } \ \ if ((gc)->eval.accFlags & EVAL_NORMAL_VALID) \ { \ (pa)->pdNextVertex->flags &= ~POLYDATA_EVAL_NORMAL; \ glcltNormal3f ((gc)->eval.normal.x, \ (gc)->eval.normal.y, \ (gc)->eval.normal.z); \ } \ \ if ((gc)->eval.accFlags & EVAL_TEXTURE_VALID) \ { \ (pa)->pdNextVertex->flags &= ~POLYDATA_EVAL_TEXCOORD; \ glcltTexCoord4f ((gc)->eval.texture.x, \ (gc)->eval.texture.y, \ (gc)->eval.texture.z, \ (gc)->eval.texture.w); \ } #endif ////////////////////////////////////////////////////// // Assuming that the latest State is available here // ////////////////////////////////////////////////////// void FASTCALL PADoEval1(__GLcontext *gc, __GLfloat u) { __GLevaluator1 *eval; __GLfloat **evalData; __GLevaluatorMachine em; __GLfloat v4[4]; __GLfloat n3[3]; __GLfloat t4[4]; __GLfloat c4[4]; __GLfloat ci; POLYARRAY *pa; pa = gc->paTeb; eval = gc->eval.eval1; evalData = gc->eval.eval1Data; em = gc->eval; // Initialize the flag gc->eval.accFlags = 0; // Evaluated color, index, normal and texture coords are ignored // in selection if ((gc->renderMode != GL_SELECT) && (gc->state.enables.eval1 & (__GL_MAP1_VERTEX_4_ENABLE | __GL_MAP1_VERTEX_3_ENABLE )) ) { if (gc->modes.colorIndexMode) { if (!(gc->state.enables.general & __GL_LIGHTING_ENABLE)) { if (gc->state.enables.eval1 & __GL_MAP1_INDEX_ENABLE) { DoDomain1(&em, u, &eval[__GL_I], &ci, evalData[__GL_I]); glcltIndexf_Eval(ci); } } } else { if (gc->state.enables.eval1 & __GL_MAP1_COLOR_4_ENABLE) { // NOTE: In OpenGL 1.0, color material does not apply to // evaluated colors. // In OpenGL 1.1, this behavior was changed. // This (1.1) code assumes that ColorMaterial applies to // evaluated colors to simplify the graphics pipeline. // Otherwise, the evaluated colors have no effect when // lighting is enabled. DoDomain1(&em, u, &eval[__GL_C4], c4, evalData[__GL_C4]); // If some color is set in the current polydata, then // Save it in a temporary buffer and call glcltColor later // Also make sure that the current-color pointer is updated // appropriately glcltColor4fv_Eval(c4); } if (gc->state.enables.eval1 & __GL_MAP1_TEXTURE_COORD_4_ENABLE) { DoDomain1(&em, u, &eval[__GL_T4], t4, evalData[__GL_T4]); glcltTexCoord4fv_Eval(t4); } else if (gc->state.enables.eval1 & __GL_MAP1_TEXTURE_COORD_3_ENABLE) { DoDomain1(&em, u, &eval[__GL_T3], t4, evalData[__GL_T3]); glcltTexCoord3fv_Eval(t4); } else if (gc->state.enables.eval1 & __GL_MAP1_TEXTURE_COORD_2_ENABLE) { DoDomain1(&em, u, &eval[__GL_T2], t4, evalData[__GL_T2]); glcltTexCoord2fv_Eval(t4); } else if (gc->state.enables.eval1 & __GL_MAP1_TEXTURE_COORD_1_ENABLE) { DoDomain1(&em, u, &eval[__GL_T1], t4, evalData[__GL_T1]); glcltTexCoord1fv_Eval(t4); } } if (gc->state.enables.eval1 & __GL_MAP1_NORMAL_ENABLE) { DoDomain1(&em, u, &eval[__GL_N3], n3, evalData[__GL_N3]); glcltNormal3fv_Eval(n3); } } /* Vertex */ if (gc->state.enables.eval1 & __GL_MAP1_VERTEX_4_ENABLE) { DoDomain1(&em, u, &eval[__GL_V4], v4, evalData[__GL_V4]); glcltVertex4fv (v4); } else if (gc->state.enables.eval1 & __GL_MAP1_VERTEX_3_ENABLE) { DoDomain1(&em, u, &eval[__GL_V3], v4, evalData[__GL_V3]); glcltVertex3fv (v4); } // If there are any prior glcltColor, glcltIndex, glcltTexCoord // or glcltNormal calls. The values are saved in gc->eval. Use // these and propagate them, to the next PolyData PropagateToNextPolyData (eval, pa); } // Compute the color, texture, normal, vertex based upon u and v. // // NOTE: This function is called by the client side EvalMesh2 functions. // If you modify it, make sure that you modify the callers too! ////////////////////////////////////////////////////// // Assuming that the latest State is available here // ////////////////////////////////////////////////////// void FASTCALL PADoEval2(__GLcontext *gc, __GLfloat u, __GLfloat v) { __GLevaluator2 *eval = gc->eval.eval2; __GLfloat **evalData = gc->eval.eval2Data; __GLevaluatorMachine em = gc->eval; __GLfloat v4[4]; __GLfloat n3[3]; __GLfloat t4[4]; __GLfloat c4[4]; __GLfloat ci; POLYARRAY *pa; pa = gc->paTeb; // Mark this PolyArray to indicate that it has a Evaluator vertex // pa->flags |= POLYARRAY_EVALCOORD; // Evaluated colors, normals and texture coords are ignored in selection. if (gc->renderMode == GL_SELECT) { if (gc->state.enables.eval2 & __GL_MAP2_VERTEX_4_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_V4], v4, evalData[__GL_V4]); glcltVertex4fv (v4); } else if (gc->state.enables.eval2 & __GL_MAP2_VERTEX_3_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_V3], v4, evalData[__GL_V3]); glcltVertex3fv (v4); } return; } if (gc->state.enables.eval2 & (__GL_MAP2_VERTEX_3_ENABLE | __GL_MAP2_VERTEX_4_ENABLE)) { if (gc->modes.colorIndexMode) { if (!(gc->state.enables.general & __GL_LIGHTING_ENABLE)) { if (gc->state.enables.eval2 & __GL_MAP2_INDEX_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_I], &ci, evalData[__GL_I]); glcltIndexf_Eval(ci); } } } else { if (gc->state.enables.eval2 & __GL_MAP2_COLOR_4_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_C4], c4, evalData[__GL_C4]); glcltColor4fv_Eval(c4); } if (gc->state.enables.eval2 & __GL_MAP2_TEXTURE_COORD_4_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_T4], t4, evalData[__GL_T4]); glcltTexCoord4fv_Eval(t4); } else if (gc->state.enables.eval2 & __GL_MAP2_TEXTURE_COORD_3_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_T3], t4, evalData[__GL_T3]); glcltTexCoord3fv_Eval(t4); } else if (gc->state.enables.eval2 & __GL_MAP2_TEXTURE_COORD_2_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_T2], t4, evalData[__GL_T2]); glcltTexCoord2fv_Eval(t4); } else if (gc->state.enables.eval2 & __GL_MAP2_TEXTURE_COORD_1_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_T1], t4, evalData[__GL_T1]); glcltTexCoord1fv_Eval(t4); } } if (gc->state.enables.general & __GL_AUTO_NORMAL_ENABLE) { if (gc->state.enables.eval2 & __GL_MAP2_VERTEX_4_ENABLE) { __GLfloat du[4]; __GLfloat dv[4]; DoDomain2WithDerivs(&em, u, v, &eval[__GL_V4], v4, du, dv, evalData[__GL_V4]); ComputeFirstPartials(v4, du, dv); ComputeNormal2(gc, n3, du, dv); glcltNormal3fv_Eval(n3); glcltVertex4fv(v4); } else if (gc->state.enables.eval2 & __GL_MAP2_VERTEX_3_ENABLE) { __GLfloat du[3]; __GLfloat dv[3]; DoDomain2WithDerivs(&em, u, v, &eval[__GL_V3], v4, du, dv, evalData[__GL_V3]); ComputeNormal2(gc, n3, du, dv); glcltNormal3fv_Eval(n3); glcltVertex3fv(v4); } } else { if (gc->state.enables.eval2 & __GL_MAP2_NORMAL_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_N3], n3, evalData[__GL_N3]); glcltNormal3fv_Eval(n3); } if (gc->state.enables.eval2 & __GL_MAP2_VERTEX_4_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_V4], v4, evalData[__GL_V4]); glcltVertex4fv(v4); } else if (gc->state.enables.eval2 & __GL_MAP2_VERTEX_3_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_V3], v4, evalData[__GL_V3]); glcltVertex3fv(v4); } } } // If there are any prior glcltColor, glcltIndex, glcltTexCoord // or glcltNormal calls. The values are saved in gc->eval. Use // these and propagate them, to the next PolyData PropagateToNextPolyData (eval, pa); } #define COPYMESHVERTEX(m,v) \ { \ (m)->vertex.x = (v)[0]; \ (m)->vertex.y = (v)[1]; \ (m)->vertex.z = (v)[2]; \ (m)->vertex.w = (v)[3]; \ } #define COPYMESHNORMAL(m,n) \ { \ (m)->normal.x = (n)[0]; \ (m)->normal.y = (n)[1]; \ (m)->normal.z = (n)[2]; \ } #define COPYMESHCOLOR(m,c) \ { \ (m)->color.r = (c)[0]; \ (m)->color.g = (c)[1]; \ (m)->color.b = (c)[2]; \ (m)->color.a = (c)[3]; \ } #define COPYMESHTEXTURE(m,t) \ { \ (m)->texture.x = (t)[0]; \ (m)->texture.y = (t)[1]; \ (m)->texture.z = (t)[2]; \ (m)->texture.w = (t)[3]; \ } ////////////////////////////////////////////////////// // Assuming that the latest State is available here // ////////////////////////////////////////////////////// void FASTCALL PADoEval2VArray(__GLcontext *gc, __GLfloat u, __GLfloat v, MESHVERTEX *mv, GLuint *flags) { __GLevaluator2 *eval = gc->eval.eval2; __GLfloat **evalData = gc->eval.eval2Data; __GLevaluatorMachine em = gc->eval; __GLfloat v4[4]; __GLfloat n3[3]; __GLfloat t4[4]; __GLfloat c4[4]; __GLfloat ci; // Evaluated colors, normals and texture coords are ignored in selection. if (gc->renderMode == GL_SELECT) { if (gc->state.enables.eval2 & __GL_MAP2_VERTEX_4_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_V4], v4, evalData[__GL_V4]); *flags = *flags | MV_VERTEX4; } else if (gc->state.enables.eval2 & __GL_MAP2_VERTEX_3_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_V3], v4, evalData[__GL_V3]); *flags = *flags | MV_VERTEX3; } COPYMESHVERTEX (mv, v4); return; } if (gc->state.enables.general & __GL_AUTO_NORMAL_ENABLE) { if (gc->state.enables.eval2 & __GL_MAP2_VERTEX_4_ENABLE) { __GLfloat du[4]; __GLfloat dv[4]; DoDomain2WithDerivs(&em, u, v, &eval[__GL_V4], v4, du, dv, evalData[__GL_V4]); ComputeFirstPartials(v4, du, dv); ComputeNormal2(gc, n3, du, dv); *flags = *flags | MV_VERTEX4 | MV_NORMAL; } else if (gc->state.enables.eval2 & __GL_MAP2_VERTEX_3_ENABLE) { __GLfloat du[3]; __GLfloat dv[3]; DoDomain2WithDerivs(&em, u, v, &eval[__GL_V3], v4, du, dv, evalData[__GL_V3]); ComputeNormal2(gc, n3, du, dv); *flags = *flags | MV_VERTEX3 | MV_NORMAL; } COPYMESHNORMAL (mv, n3); COPYMESHVERTEX (mv, v4); } else { if (gc->state.enables.eval2 & __GL_MAP2_NORMAL_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_N3], n3, evalData[__GL_N3]); COPYMESHNORMAL (mv, n3); *flags = *flags | MV_NORMAL; } if (gc->state.enables.eval2 & __GL_MAP2_VERTEX_4_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_V4], v4, evalData[__GL_V4]); COPYMESHVERTEX (mv, v4); *flags = *flags | MV_VERTEX4; } else if (gc->state.enables.eval2 & __GL_MAP2_VERTEX_3_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_V3], v4, evalData[__GL_V3]); COPYMESHVERTEX (mv, v4); *flags = *flags | MV_VERTEX3; } } if (gc->modes.colorIndexMode) { if (!(gc->state.enables.general & __GL_LIGHTING_ENABLE)) { if (gc->state.enables.eval2 & __GL_MAP2_INDEX_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_I], &(mv->color.r), evalData[__GL_I]); *flags = *flags | MV_INDEX; } } } else { if (gc->state.enables.eval2 & __GL_MAP2_COLOR_4_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_C4], c4, evalData[__GL_C4]); COPYMESHCOLOR (mv, c4); *flags = *flags | MV_COLOR; } if (gc->state.enables.eval2 & __GL_MAP2_TEXTURE_COORD_4_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_T4], t4, evalData[__GL_T4]); COPYMESHTEXTURE (mv, t4); *flags = *flags | MV_TEXTURE4; } else if (gc->state.enables.eval2 & __GL_MAP2_TEXTURE_COORD_3_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_T3], t4, evalData[__GL_T3]); COPYMESHTEXTURE (mv, t4); *flags = *flags | MV_TEXTURE3; } else if (gc->state.enables.eval2 & __GL_MAP2_TEXTURE_COORD_2_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_T2], t4, evalData[__GL_T2]); COPYMESHTEXTURE (mv, t4); *flags = *flags | MV_TEXTURE2; } else if (gc->state.enables.eval2 & __GL_MAP2_TEXTURE_COORD_1_ENABLE) { DoDomain2(&em, u, v, &eval[__GL_T1], t4, evalData[__GL_T1]); COPYMESHTEXTURE (mv, t4); *flags = *flags | MV_TEXTURE1; } } } /* ** Optimization to precompute coefficients for polynomial evaluation. */ static void PreEvaluate(GLint order, __GLfloat vprime, __GLfloat *coeff) { GLint i, j; __GLfloat oldval, temp; __GLfloat oneMinusvprime; /* ** Minor optimization ** Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to ** their i==1 loop values to avoid the initialization and the i==1 loop. */ if (order == 1) { coeff[0] = ((__GLfloat) 1.0); return; } oneMinusvprime = 1-vprime; coeff[0] = oneMinusvprime; coeff[1] = vprime; if (order == 2) return; for (i = 2; i < order; i++) { oldval = coeff[0] * vprime; coeff[0] = oneMinusvprime * coeff[0]; for (j = 1; j < i; j++) { temp = oldval; oldval = coeff[j] * vprime; coeff[j] = temp + oneMinusvprime * coeff[j]; } coeff[j] = oldval; } } /* ** Optimization to precompute coefficients for polynomial evaluation. */ static void PreEvaluateWithDeriv(GLint order, __GLfloat vprime, __GLfloat *coeff, __GLfloat *coeffDeriv) { GLint i, j; __GLfloat oldval, temp; __GLfloat oneMinusvprime; oneMinusvprime = 1-vprime; /* ** Minor optimization ** Compute orders 1 and 2 outright, and set coeff[0], coeff[1] to ** their i==1 loop values to avoid the initialization and the i==1 loop. */ if (order == 1) { coeff[0] = ((__GLfloat) 1.0); coeffDeriv[0] = __glZero; return; } else if (order == 2) { coeffDeriv[0] = __glMinusOne; coeffDeriv[1] = ((__GLfloat) 1.0); coeff[0] = oneMinusvprime; coeff[1] = vprime; return; } coeff[0] = oneMinusvprime; coeff[1] = vprime; for (i = 2; i < order - 1; i++) { oldval = coeff[0] * vprime; coeff[0] = oneMinusvprime * coeff[0]; for (j = 1; j < i; j++) { temp = oldval; oldval = coeff[j] * vprime; coeff[j] = temp + oneMinusvprime * coeff[j]; } coeff[j] = oldval; } coeffDeriv[0] = -coeff[0]; /* ** Minor optimization: ** Would make this a "for (j=1; ju2 != e->u1) && (e->v2 != e->v1), "In DoDomain2\n"); // assert((e->u2 != e->u1) && (e->v2 != e->v1)); #else if((e->u2 == e->u1) || (e->v2 == e->v1)) return; #endif uprime = (u - e->u1) / (e->u2 - e->u1); vprime = (v - e->v1) / (e->v2 - e->v1); /* Compute coefficients for values */ /* Use already cached values if possible */ if (em->uvalue != uprime || em->uorder != e->majorOrder) { PreEvaluate(e->majorOrder, uprime, em->ucoeff); em->utype = TYPE_COEFF; em->uorder = e->majorOrder; em->uvalue = uprime; } if (em->vvalue != vprime || em->vorder != e->minorOrder) { PreEvaluate(e->minorOrder, vprime, em->vcoeff); em->vtype = TYPE_COEFF; em->vorder = e->minorOrder; em->vvalue = vprime; } k=e->k; for (j = 0; j < k; j++) { data=baseData+j; r[j] = 0; for (row = 0; row < e->majorOrder; row++) { /* ** Minor optimization. ** The col == 0 part of the loop is extracted so we don't ** have to initialize p to 0. */ p=em->vcoeff[0] * (*data); data += k; for (col = 1; col < e->minorOrder; col++) { p += em->vcoeff[col] * (*data); data += k; } r[j] += em->ucoeff[row] * p; } } } void DoDomain2WithDerivs(__GLevaluatorMachine *em, __GLfloat u, __GLfloat v, __GLevaluator2 *e, __GLfloat *r, __GLfloat *du, __GLfloat *dv, __GLfloat *baseData) { GLint j, row, col; __GLfloat uprime; __GLfloat vprime; __GLfloat p; __GLfloat pdv; __GLfloat n[3]; __GLfloat *data; GLint k; #ifdef NT ASSERTOPENGL((e->u2 != e->u1) && (e->v2 != e->v1), "In Dodomain2WithDerivs\n"); // assert((e->u2 != e->u1) && (e->v2 != e->v1)); #else if((e->u2 == e->u1) || (e->v2 == e->v1)) return; #endif uprime = (u - e->u1) / (e->u2 - e->u1); vprime = (v - e->v1) / (e->v2 - e->v1); /* Compute coefficients for values and derivs */ /* Use already cached values if possible */ if (em->uvalue != uprime || em->utype != TYPE_COEFF_AND_DERIV || em->uorder != e->majorOrder) { PreEvaluateWithDeriv(e->majorOrder, uprime, em->ucoeff, em->ucoeffDeriv); em->utype = TYPE_COEFF_AND_DERIV; em->uorder = e->majorOrder; em->uvalue = uprime; } if (em->vvalue != vprime || em->vtype != TYPE_COEFF_AND_DERIV || em->vorder != e->minorOrder) { PreEvaluateWithDeriv(e->minorOrder, vprime, em->vcoeff, em->vcoeffDeriv); em->vtype = TYPE_COEFF_AND_DERIV; em->vorder = e->minorOrder; em->vvalue = vprime; } k=e->k; for (j = 0; j < k; j++) { data=baseData+j; r[j] = du[j] = dv[j] = __glZero; for (row = 0; row < e->majorOrder; row++) { /* ** Minor optimization. ** The col == 0 part of the loop is extracted so we don't ** have to initialize p and pdv to 0. */ p = em->vcoeff[0] * (*data); pdv = em->vcoeffDeriv[0] * (*data); data += k; for (col = 1; col < e->minorOrder; col++) { /* Incrementally build up p, pdv value */ p += em->vcoeff[col] * (*data); pdv += em->vcoeffDeriv[col] * (*data); data += k; } /* Use p, pdv value to incrementally add up r, du, dv */ r[j] += em->ucoeff[row] * p; du[j] += em->ucoeffDeriv[row] * p; dv[j] += em->ucoeff[row] * pdv; } } } int FASTCALL genMeshElts (GLenum mode, GLuint sides, GLint nu, GLint nv, GLubyte *buff) { GLint start; GLint i, j, k; // Compute the DrawElements Indices switch(mode) { case GL_LINE : // Draw lines along U direction start = 1; k = 0; if (sides & MV_TOP) start = 0 ; for (i=start; istate.evaluator.u2; gv = &gc->state.evaluator.v2; du = gu->step; dv = gv->step; //du = (gu->finish - gu->start)/(__GLfloat)gu->n; //dv = (gv->finish - gv->start)/(__GLfloat)gv->n; mv = &mvBuf[0]; nu = u2 - u1 + 1; nv = v2 - v1 + 1; for (i = v1; i < nv+v1; i++) //along V { for (j = u1; j < nu+u1; j++) //along U { u = (j == gu->n) ? gu->finish : (gu->start + j * du); v = (i == gv->n) ? gv->finish : (gv->start + i * dv); PADoEval2VArray(gc, u, v, mv, &mflags); mv++; } } if ((nv != MAX_V_SIZE) || (nu != MAX_U_SIZE)) { disBuf = dBufSmall; totalPts = genMeshElts (mode, sides, nu, nv, disBuf); } else { if (mode == GL_FILL) { disBuf = dBufFill; totalPts = totFillPts; } else switch (sides) { case (MV_TOP | MV_LEFT): disBuf = dBufTopLeft; totalPts = totTopLeftPts; break; case (MV_TOP): disBuf = dBufTopRight; totalPts = totTopRightPts; break; case (MV_LEFT): disBuf = &dBufTopLeft [(MAX_U_SIZE - 1) * 2]; totalPts = totTopLeftPts - (MAX_U_SIZE - 1) * 2; break; default : //NONE disBuf = &dBufTopRight [(MAX_V_SIZE - 1) * 2]; totalPts = totTopRightPts - (MAX_V_SIZE - 1) * 2; break; } } if (mflags & MV_TEXTURE4) texSize = 4; else if (mflags & MV_TEXTURE3) texSize = 3; else if (mflags & MV_TEXTURE2) texSize = 2; else if (mflags & MV_TEXTURE1) texSize = 1; // Save current values. if (mflags & MV_NORMAL) currentNormal = gc->state.current.normal; if (mflags & MV_INDEX) currentColor.r = gc->state.current.userColorIndex; else if (mflags & MV_COLOR) currentColor = gc->state.current.userColor; if (texSize) currentTexture = gc->state.current.texture; // Always force edge flag on in GL_FILL mode. The spec uses QUAD_STRIP // which implies that edge flag is on for the evaluated mesh. currentEdgeFlag = gc->state.current.edgeTag; gc->state.current.edgeTag = GL_TRUE; currentVertexInfo = gc->vertexArray; //Enable the appropriate arrays // Disable the arrays followed by enabling each individual array. gc->vertexArray.flags |= __GL_VERTEX_ARRAY_DIRTY; gc->vertexArray.mask &= ~(VAMASK_VERTEX_ENABLE_MASK | VAMASK_NORMAL_ENABLE_MASK | VAMASK_COLOR_ENABLE_MASK | VAMASK_INDEX_ENABLE_MASK | VAMASK_TEXCOORD_ENABLE_MASK | VAMASK_EDGEFLAG_ENABLE_MASK); stride = sizeof(MESHVERTEX); if (mflags & MV_NORMAL) { gc->vertexArray.mask |= VAMASK_NORMAL_ENABLE_MASK; glcltNormalPointer(GL_FLOAT, stride, &(mvBuf[0].normal.x)); } if (mflags & MV_INDEX) { gc->vertexArray.mask |= VAMASK_INDEX_ENABLE_MASK; glcltIndexPointer(GL_FLOAT, stride, &(mvBuf[0].color.r)); } else if (mflags & MV_COLOR) { gc->vertexArray.mask |= VAMASK_COLOR_ENABLE_MASK; glcltColorPointer(3, GL_FLOAT, stride, &(mvBuf[0].color.r)); } if (texSize) { glcltTexCoordPointer(texSize, GL_FLOAT, stride, &(mvBuf[0].texture.x)); gc->vertexArray.mask |= VAMASK_TEXCOORD_ENABLE_MASK; } if (mflags & MV_VERTEX3) glcltVertexPointer(3, GL_FLOAT, stride, &(mvBuf[0].vertex.x)); else glcltVertexPointer(4, GL_FLOAT, stride, &(mvBuf[0].vertex.x)); gc->vertexArray.mask |= VAMASK_VERTEX_ENABLE_MASK; if (mode == GL_FILL) glcltDrawElements(GL_QUADS, totalPts, GL_UNSIGNED_BYTE, disBuf); else glcltDrawElements(GL_LINES, totalPts, GL_UNSIGNED_BYTE, disBuf); // Execute the command now. // Otherwise, the current states will be messed up. glsbAttention(); // Restore current values. if (mflags & MV_NORMAL) gc->state.current.normal = currentNormal; if (mflags & MV_INDEX) gc->state.current.userColorIndex = currentColor.r; else if (mflags & MV_COLOR) gc->state.current.userColor = currentColor; if (texSize) gc->state.current.texture = currentTexture; gc->state.current.edgeTag = currentEdgeFlag; gc->vertexArray = currentVertexInfo ; } void glcltColor4fv_Eval (__GLfloat *c4) { __GL_SETUP (); POLYARRAY *pa; POLYDATA *pd; // POLYDATA *pdNext; pa = gc->paTeb; pd = pa->pdNextVertex; // We are in RGBA mode. ASSERTOPENGL (!gc->modes.colorIndexMode, "We should be in RGBA mode\n"); // Do not update the CurColor pointer // If the color has already been set by a previous glcltColor call, // simply, push this color to the next POLYDATA. // This is a COLOR and not an INDEX. if ((pd->flags & POLYDATA_COLOR_VALID) && !(pd->flags & POLYDATA_EVAL_COLOR)) { gc->eval.color.r = pd->colors[0].r; gc->eval.color.g = pd->colors[0].g; gc->eval.color.b = pd->colors[0].b; gc->eval.color.a = pd->colors[0].a; gc->eval.accFlags |= EVAL_COLOR_VALID; } __GL_SCALE_AND_CHECK_CLAMP_RGBA(pd->colors[0].r, pd->colors[0].g, pd->colors[0].b, pd->colors[0].a, gc, pa->flags, c4[0], c4[1], c4[2], c4[3]); pd->flags |= (POLYDATA_COLOR_VALID | POLYDATA_DLIST_COLOR_4 | POLYDATA_EVAL_COLOR) ; pa->pdLastEvalColor = pd; } void glcltIndexf_Eval (__GLfloat ci) { __GL_SETUP (); POLYARRAY *pa; POLYDATA *pd; pa = gc->paTeb; pd = pa->pdNextVertex; // We are in CI mode. ASSERTOPENGL (gc->modes.colorIndexMode, "We should be in CI mode\n"); // Do not update the CurColor pointer // If the index has already been set by a previous glcltIndex call, // simply, push this color to the next POLYDATA. // This is an INDEX and not a COLOR. if ((pd->flags & POLYDATA_COLOR_VALID) && !(pd->flags & POLYDATA_EVAL_COLOR)) { gc->eval.color.r = pd->colors[0].r; gc->eval.accFlags |= EVAL_COLOR_VALID; } __GL_CHECK_CLAMP_CI(pd->colors[0].r, gc, pa->flags, ci); pd->flags |= (POLYDATA_COLOR_VALID | POLYDATA_EVAL_COLOR) ; pa->pdLastEvalColor = pd; } void glcltTexCoord1fv_Eval (__GLfloat *t1) { __GL_SETUP (); POLYARRAY *pa; POLYDATA *pd; pa = GLTEB_CLTPOLYARRAY(); pa->flags |= POLYARRAY_TEXTURE1; pd = pa->pdNextVertex; // Do not update the CurTexture pointer if (pd->flags & POLYDATA_TEXTURE_VALID) { ASSERTOPENGL (!(pd->flags & POLYDATA_EVAL_TEXCOORD), "This cannot have been generated by an evaluator\n"); gc->eval.texture.x = pd->texture.x; gc->eval.texture.y = pd->texture.y; gc->eval.texture.z = pd->texture.z; gc->eval.texture.w = pd->texture.w; gc->eval.accFlags |= EVAL_TEXTURE_VALID; } pd->texture.x = t1[0]; pd->texture.y = __glZero; pd->texture.z = __glZero; pd->texture.w = __glOne; pd->flags |= (POLYDATA_TEXTURE_VALID | POLYDATA_DLIST_TEXTURE1 | POLYDATA_EVAL_TEXCOORD); pa->pdLastEvalTexture = pd; } void glcltTexCoord2fv_Eval (__GLfloat *t2) { __GL_SETUP (); POLYARRAY *pa; POLYDATA *pd; pa = GLTEB_CLTPOLYARRAY(); pa->flags |= POLYARRAY_TEXTURE2; pd = pa->pdNextVertex; // Do not update the CurTexture pointer if (pd->flags & POLYDATA_TEXTURE_VALID) { ASSERTOPENGL (!(pd->flags & POLYDATA_EVAL_TEXCOORD), "This cannot have been generated by an evaluator\n"); gc->eval.texture.x = pd->texture.x; gc->eval.texture.y = pd->texture.y; gc->eval.texture.z = pd->texture.z; gc->eval.texture.w = pd->texture.w; gc->eval.accFlags |= EVAL_TEXTURE_VALID; } pd->texture.x = t2[0]; pd->texture.y = t2[1]; pd->texture.z = __glZero; pd->texture.w = __glOne; pd->flags |= (POLYDATA_TEXTURE_VALID | POLYDATA_DLIST_TEXTURE2 | POLYDATA_EVAL_TEXCOORD); pa->pdLastEvalTexture = pd; } void glcltTexCoord3fv_Eval (__GLfloat *t3) { __GL_SETUP (); POLYARRAY *pa; POLYDATA *pd; pa = GLTEB_CLTPOLYARRAY(); pa->flags |= POLYARRAY_TEXTURE3; pd = pa->pdNextVertex; if (pd->flags & POLYDATA_TEXTURE_VALID) { ASSERTOPENGL (!(pd->flags & POLYDATA_EVAL_TEXCOORD), "This cannot have been generated by an evaluator\n"); gc->eval.texture.x = pd->texture.x; gc->eval.texture.y = pd->texture.y; gc->eval.texture.z = pd->texture.z; gc->eval.texture.w = pd->texture.w; gc->eval.accFlags |= EVAL_TEXTURE_VALID; } pd->texture.x = t3[0]; pd->texture.y = t3[1]; pd->texture.z = t3[2]; pd->texture.w = __glOne; pd->flags |= (POLYDATA_TEXTURE_VALID | POLYDATA_DLIST_TEXTURE3 | POLYDATA_EVAL_TEXCOORD) ; pa->pdLastEvalTexture = pd; } // Do not update the CurTexture pointer void glcltTexCoord4fv_Eval (__GLfloat *t4) { __GL_SETUP (); POLYARRAY *pa; POLYDATA *pd; pa = GLTEB_CLTPOLYARRAY(); pa->flags |= POLYARRAY_TEXTURE4; pd = pa->pdNextVertex; if (pd->flags & POLYDATA_TEXTURE_VALID) { ASSERTOPENGL (!(pd->flags & POLYDATA_EVAL_TEXCOORD), "This cannot have been generated by an evaluator\n"); gc->eval.texture.x = pd->texture.x; gc->eval.texture.y = pd->texture.y; gc->eval.texture.z = pd->texture.z; gc->eval.texture.w = pd->texture.w; gc->eval.accFlags |= EVAL_TEXTURE_VALID; } pd->texture.x = t4[0]; pd->texture.y = t4[1]; pd->texture.z = t4[2]; pd->texture.w = t4[4]; pd->flags |= (POLYDATA_TEXTURE_VALID | POLYDATA_DLIST_TEXTURE4 | POLYDATA_EVAL_TEXCOORD); pa->pdLastEvalTexture = pd; } // We do not update the CurNormal pointer here void glcltNormal3fv_Eval (__GLfloat *n3) { __GL_SETUP (); POLYARRAY *pa; POLYDATA *pd; pa = GLTEB_CLTPOLYARRAY(); pd = pa->pdNextVertex; // If the existing normal is not from an evaluator, store it // so that it can be set later. if (pd->flags & POLYDATA_NORMAL_VALID) { ASSERTOPENGL (!(pd->flags & POLYDATA_EVAL_NORMAL), "This cannot have been generated by an evaluator\n"); gc->eval.normal.x = pd->normal.x; gc->eval.normal.y = pd->normal.y; gc->eval.normal.z = pd->normal.z; gc->eval.accFlags |= EVAL_NORMAL_VALID; } pd->normal.x = n3[0]; pd->normal.y = n3[1]; pd->normal.z = n3[2]; pd->flags |= (POLYDATA_NORMAL_VALID | POLYDATA_EVAL_NORMAL); pa->pdLastEvalNormal = pd; }