/* * $Id$ * * $Date$ * $Revision$ * * (C) 1999 by Thomas and Hans-Jörg Frieden * All rights reserved * * This file is part of the MiniGL library project * See the file Licence.txt for more details * */ /* Parts of this file are modeled after the SGI sample implementation. * The following comment block quotes the license for this. */ /* ** License Applicability. Except to the extent portions of this file are ** made subject to an alternative license as permitted in the SGI Free ** Software License B, Version 1.1 (the "License"), the contents of this ** file are subject only to the provisions of the License. You may not use ** this file except in compliance with the License. You may obtain a copy ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: ** ** http://oss.sgi.com/projects/FreeB ** ** Note that, as provided in the License, the Software is distributed on an ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. ** ** Original Code. The Original Code is: OpenGL Sample Implementation, ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. ** Copyright in any portions created by third parties is as indicated ** elsewhere herein. All Rights Reserved. ** ** Additional Notice Provisions: The application programming interfaces ** established by SGI in conjunction with the Original Code are The ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X ** Window System(R) (Version 1.3), released October 19, 1998. This software ** was created using the OpenGL(R) version 1.2.1 Sample Implementation ** published by SGI, but has not been independently verified as being ** compliant with the OpenGL(R) version 1.2.1 Specification. */ #include "displaylists.h" #include "sysinc.h" #include #include #include #include #include "mgl/gl.h" #include "mgl/mgltypes.h" #include #include #include "util.h" #include "mgl_profileitems.h" void light_UpdateColorMaterialColor(GLcontext context, GLfloat color[4]); void light_UpdateColorMaterial(GLcontext context); #define MGL_MAP_V3 0 #define MGL_MAP_V4 1 #define MGL_MAP_C4 2 #define MGL_MAP_N3 3 #define MGL_MAP_TC1 4 #define MGL_MAP_TC2 5 #define MGL_MAP_TC3 6 #define MGL_MAP_TC4 7 #define __CHANGED_COLOR (1<<0) #define __CHANGED_NORMAL (1<<1) #define __CHANGED_VERTEX (1<<2) #define __CHANGED_TEXCOORD (1<<3) struct __EvalBuffer { uint32 changed; GLfloat evalColor[4]; GLfloat evalNormal[3]; GLfloat evalVert[4]; GLfloat tu, tv, tw; GLboolean twvalid; }; int eval_TargetToIndex(GLenum target) { switch (target) { case GL_MAP1_VERTEX_3: case GL_MAP2_VERTEX_3: return MGL_MAP_V3; case GL_MAP1_VERTEX_4: case GL_MAP2_VERTEX_4: return MGL_MAP_V4; case GL_MAP1_COLOR_4: case GL_MAP2_COLOR_4: return MGL_MAP_C4; case GL_MAP1_NORMAL: case GL_MAP2_NORMAL: return MGL_MAP_N3; case GL_MAP1_TEXTURE_COORD_1: case GL_MAP2_TEXTURE_COORD_1: return MGL_MAP_TC1; case GL_MAP1_TEXTURE_COORD_2: case GL_MAP2_TEXTURE_COORD_2: return MGL_MAP_TC2; case GL_MAP1_TEXTURE_COORD_3: case GL_MAP2_TEXTURE_COORD_3: return MGL_MAP_TC3; case GL_MAP1_TEXTURE_COORD_4: case GL_MAP2_TEXTURE_COORD_4: return MGL_MAP_TC4; } return -1; } GLuint eval_GetMapK1(GLenum target) { GLint k[] = { /* VERTEX_3 */ 3, /* VERTEX_4 */ 4, /* COLOR_4 */ 4, /* NORMAL */ 3, /* TEXTURE_1 */ 1, /* TEXTURE_2 */ 2, /* TEXTURE_3 */ 3, /* TEXTURE_4 */ 4, }; return k[eval_TargetToIndex(target)]; } GLuint eval_GetMapK2(GLenum target) { return eval_GetMapK1(target); } int eval_TargetToComponents(GLenum target) { switch (target) { case GL_MAP1_TEXTURE_COORD_1: case GL_MAP2_TEXTURE_COORD_1: return 1; case GL_MAP1_TEXTURE_COORD_2: case GL_MAP2_TEXTURE_COORD_2: return 2; case GL_MAP1_VERTEX_3: case GL_MAP2_VERTEX_3: case GL_MAP1_NORMAL: case GL_MAP2_NORMAL: case GL_MAP1_TEXTURE_COORD_3: case GL_MAP2_TEXTURE_COORD_3: return 3; case GL_MAP1_VERTEX_4: case GL_MAP2_VERTEX_4: case GL_MAP1_COLOR_4: case GL_MAP2_COLOR_4: case GL_MAP1_TEXTURE_COORD_4: case GL_MAP2_TEXTURE_COORD_4: return 4; } return -1; } void eval_InitEvaluator(GLcontext context) { int i; struct defaultState_s { GLint k; GLfloat defValues[4]; } defaultState[] = { /* VERTEX_3 */ {3, {0.0, 0.0, 0.0, 0.0}}, /* VERTEX_4 */ {4, {0.0, 0.0, 0.0, 1.0}}, /* COLOR_4 */ {4, {1.0, 1.0, 1.0, 1.0}}, /* NORMAL */ {3, {0.0, 0.0, 1.0, 0.0}}, /* TEXTURE_1 */ {1, {0.0, 0.0, 0.0, 1.0}}, /* TEXTURE_2 */ {2, {0.0, 0.0, 0.0, 1.0}}, /* TEXTURE_3 */ {3, {0.0, 0.0, 0.0, 1.0}}, /* TEXTURE_4 */ {4, {0.0, 0.0, 0.0, 1.0}}, }; /* Enables */ for (i = 0; i < MGL_NUM_EVALUATORS; i++) { context->enable.Map1[i] = GL_FALSE; context->enable.Map2[i] = GL_FALSE; } context->enable.AutoNormal = GL_FALSE; /* Domains */ context->evaluator.u1.start = 0.0; context->evaluator.u1.end = 1.0; context->evaluator.u1.num = 1; context->evaluator.u2.start = 0.0; context->evaluator.u2.end = 1.0; context->evaluator.u2.num = 1; context->evaluator.v2.start = 0.0; context->evaluator.v2.end = 1.0; context->evaluator.v2.num = 1; /* Eval data */ for (i = 0; i < MGL_NUM_EVALUATORS; i++) { int j; context->evaldata.map1[i].k = defaultState[i].k; context->evaldata.map1[i].order = 1; context->evaldata.map1[i].u1 = 0.0; context->evaldata.map1[i].u2 = 1.0; context->evaldata.map1[i].data = (GLfloat *)AllocVecInternal(sizeof(GLfloat) * defaultState[i].k, MEMF_ANY); context->evaldata.map1[i].datasize = sizeof(GLfloat) * defaultState[i].k; for (j = 0; j < defaultState[i].k; j++) { context->evaldata.map1[i].data[j] = defaultState[i].defValues[j]; } context->evaldata.map2[i].k = defaultState[i].k; context->evaldata.map2[i].uOrder = 1; context->evaldata.map2[i].vOrder = 1; context->evaldata.map2[i].u1 = 0.0; context->evaldata.map2[i].u2 = 1.0; context->evaldata.map2[i].v1 = 0.0; context->evaldata.map2[i].v2 = 1.0; context->evaldata.map2[i].data = (GLfloat *)AllocVecInternal(sizeof(GLfloat) * defaultState[i].k, MEMF_ANY); context->evaldata.map2[i].datasize = sizeof(GLfloat) * defaultState[i].k; for (j = 0; j < defaultState[i].k; j++) { context->evaldata.map2[i].data[j] = defaultState[i].defValues[j]; } } context->evaldata.u.order = -1; context->evaldata.u.derivValid = GL_FALSE; context->evaldata.v.order = -1; context->evaldata.v.derivValid = GL_FALSE; } void eval_TermEvaluator(GLcontext context) { for (int i = 0; i < MGL_NUM_EVALUATORS; i++) { FreeVecInternalCheckAndClear((void**)&context->evaldata.map1[i].data); FreeVecInternalCheckAndClear((void**)&context->evaldata.map2[i].data); } } void eval_UpdateEnableSummary(GLcontext context) { context->evaluator.EnableSummary = GL_FALSE; for (int i = 0; i < MGL_NUM_EVALUATORS; i++) { if (context->enable.Map1[i] || context->enable.Map2[i]) { context->evaluator.EnableSummary = GL_TRUE; return; } } } int eval_SetupMap1(GLeval1 *map, GLfloat u1, GLfloat u2, GLint order) { map->order = order; map->u1 = u1; map->u2 = u2; /* Make sure data is large enough to take up all control points */ int needSize = map->k * map->order * sizeof(GLfloat); if (needSize > map->datasize) { FreeVecInternal(map->data); map->data = (GLfloat *)AllocVecInternal(needSize, MEMF_ANY); if (map->data) { map->datasize = needSize; } else { map->datasize = 0; } } return (map->data != 0); } void eval_ReadPoints1f(GLeval1 *map, GLint stride, const GLfloat *points) { int i, j; GLfloat *data = map->data; assert (map->datasize >= (map->order * map->k * sizeof(GLfloat))); for (i = 0; i < map->order; i++) { for (j = 0; j < map->k; j++) { *data++ = points[j]; } points += stride; //data += map->k; } } void eval_ReadPoints1d(GLeval1 *map, GLint stride, const GLdouble *points) { int i, j; GLfloat *data = map->data; assert (map->datasize >= (map->order * map->k * sizeof(GLfloat))); for (i = 0; i < map->order; i++) { for (j = 0; j < map->k; j++) { *data++ = (GLfloat)points[j]; } points += stride; //data += map->k; } } void cgl_GLMap1f( struct GLContextIFace *Self, GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points ) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(Map1f(Self, target, u1, u2, stride, order, points)); PROFILE_ENTRY(FID_CGL_GL_MAP_1F); /* Check input parameters */ GLFlagError(context, u1 == u2, GL_INVALID_VALUE); int k = eval_TargetToComponents(target); GLFlagError(context, stride < k, GL_INVALID_VALUE); int map = eval_TargetToIndex(target); GLFlagError(context, map < 0, GL_INVALID_ENUM); if (!eval_SetupMap1(&context->evaldata.map1[map], u1, u2, order)) { context->CurrentError = GL_INVALID_VALUE; return; } eval_ReadPoints1f(&context->evaldata.map1[map], stride, points); PROFILE_EXIT(FID_CGL_GL_MAP_1F); } void cgl_GLMap1d( struct GLContextIFace *Self, GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points ) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(Map1d(Self, target, u1, u2, stride, order, points)); PROFILE_ENTRY(FID_CGL_GL_MAP_1D); /* Check input parameters */ GLFlagError(context, u1 == u2, GL_INVALID_VALUE); int k = eval_TargetToComponents(target); GLFlagError(context, stride < k, GL_INVALID_VALUE); int map = eval_TargetToIndex(target); GLFlagError(context, map < 0, GL_INVALID_ENUM); if (!eval_SetupMap1(&context->evaldata.map1[map], (GLfloat)u1, (GLfloat)u2, order)) { context->CurrentError = GL_INVALID_VALUE; return; } eval_ReadPoints1d(&context->evaldata.map1[map], stride, points); PROFILE_EXIT(FID_CGL_GL_MAP_1D); } /* * Precalculate the coefficients for the evaulation. * Basically, we compute the sum over 1 to n of bernstein polynomials. * * n * ----- * \ n * p(u) = > B (u) * R * / i i * ----- * i = 0 * * n ( n ) i n-i * with B (u) = ( ) u + (1 - u) * i ( i ) * * (This function is derived from the sample implementation by SGI) */ void eval_Precalc(GLevalpre *pre, GLint order, GLfloat u) { /* Check if still valid */ if (pre->order == order && pre->u == u) { return; } pre->order = order; pre->u = u; pre->derivValid = GL_FALSE; /* Shortcut for order == 1 */ if (order == 1) { pre->factor[0] = 1.0; return; } GLfloat oneMinusU = 1.0 - u; pre->factor[0] = oneMinusU; pre->factor[1] = u; if (order == 2) { return; } for (int i = 2; i < order; i++) { int j; GLfloat old = pre->factor[0] * u; pre->factor[0] = oneMinusU * pre->factor[0]; for (j = 1; j < i; j++) { GLfloat t = old; old = pre->factor[j] * u; pre->factor[j] = t + oneMinusU * pre->factor[j]; } pre->factor[j] = old; } } void eval_DoEval1(GLcontext context, GLfloat u, GLeval1 *map, GLfloat *out) { /* This generates a k-dimensional output from the input vector using the * given map */ if (map->u2 == map->u1) { return; } GLfloat utick = (u - map->u1) / (map->u2 - map->u1); eval_Precalc(&context->evaldata.u, map->order, utick); for (int i = 0; i < map->k; i++) { GLfloat *data = out + i; GLfloat *control = &map->data[i]; *data = 0; for (int j = 0; j < map->order; j++) { *data += context->evaldata.u.factor[j] * *control; control += map->k; } } } void eval_DoEvalCoord1f(GLcontext context, GLfloat arg) { GLfloat evalColor[4]; GLfloat evalTexCoord[4]; GLfloat evalNormal[3]; GLfloat evalVert[4]; if (context->enable.Map1[MGL_MAP_C4]) { eval_DoEval1(context, arg, &context->evaldata.map1[MGL_MAP_C4], evalColor); THIS_VERTEX.r = evalColor[0]; THIS_VERTEX.g = evalColor[1]; THIS_VERTEX.b = evalColor[2]; THIS_VERTEX.a = evalColor[3]; #ifdef MGL_USE_LIGHTING if (context->enable.ColorMaterial) { light_UpdateColorMaterialColor(context, evalColor); } #endif } else { THIS_VERTEX.r = context->current.CurrentColor.r; THIS_VERTEX.g = context->current.CurrentColor.g; THIS_VERTEX.b = context->current.CurrentColor.b; THIS_VERTEX.a = context->current.CurrentColor.a; #ifdef MGL_USE_LIGHTING if (context->enable.ColorMaterial) { light_UpdateColorMaterial(context); } #endif } if (context->texture.MaxTextureUnit > -1) { if (context->enable.Map1[MGL_MAP_TC4] || context->enable.Map1[MGL_MAP_TC3] || context->enable.Map1[MGL_MAP_TC2] || context->enable.Map1[MGL_MAP_TC1] ) { if (context->enable.Map1[MGL_MAP_TC4]) { eval_DoEval1(context, arg, &context->evaldata.map1[MGL_MAP_TC4], evalTexCoord); THIS_VERTEX.uvw[0].u = evalTexCoord[0] / evalTexCoord[3]; THIS_VERTEX.uvw[0].v = evalTexCoord[1] / evalTexCoord[3]; THIS_VERTEX.uvw[0].w = evalTexCoord[3]; THIS_VERTEX.rhw_valid[0] = GL_TRUE; } else if (context->enable.Map1[MGL_MAP_TC3]) { eval_DoEval1(context, arg, &context->evaldata.map1[MGL_MAP_TC3], evalTexCoord); THIS_VERTEX.uvw[0].u = evalTexCoord[0]; THIS_VERTEX.uvw[0].v = evalTexCoord[1]; THIS_VERTEX.uvw[0].w = 1.0; THIS_VERTEX.rhw_valid[0] = GL_FALSE; } else if (context->enable.Map1[MGL_MAP_TC2]) { eval_DoEval1(context, arg, &context->evaldata.map1[MGL_MAP_TC2], evalTexCoord); THIS_VERTEX.uvw[0].u = evalTexCoord[0]; THIS_VERTEX.uvw[0].v = evalTexCoord[1]; THIS_VERTEX.uvw[0].w = 1.0; THIS_VERTEX.rhw_valid[0] = GL_FALSE; } else if (context->enable.Map1[MGL_MAP_TC1]) { eval_DoEval1(context, arg, &context->evaldata.map1[MGL_MAP_TC1], evalTexCoord); THIS_VERTEX.uvw[0].u = evalTexCoord[0]; THIS_VERTEX.uvw[0].v = 0.0; THIS_VERTEX.uvw[0].w = 1.0; THIS_VERTEX.rhw_valid[0] = GL_FALSE; } } else { int i; for (i = 0; i <= context->texture.MaxTextureUnit; i++) { if (context->enable.Texture2D[i] == GL_TRUE || context->enable.Texture1D[i] ) { if (context->current.CurTexQValid[i] == GL_TRUE) { THIS_VERTEX.uvw[i].u = context->current.CurTexS[i] / context->current.CurTexQ[i]; THIS_VERTEX.uvw[i].v = context->current.CurTexT[i] / context->current.CurTexQ[i]; THIS_VERTEX.uvw[i].w = context->current.CurTexQ[i]; THIS_VERTEX.rhw_valid[i] = GL_TRUE; } else { THIS_VERTEX.uvw[i].u = context->current.CurTexS[i]; THIS_VERTEX.uvw[i].v = context->current.CurTexT[i]; THIS_VERTEX.uvw[i].w = 1.0; THIS_VERTEX.rhw_valid[i] = GL_FALSE; } } } } } if (context->enable.Map1[MGL_MAP_N3]) { eval_DoEval1(context, arg, &context->evaldata.map1[MGL_MAP_N3], evalNormal); THIS_VERTEX.Normal.x = evalNormal[0]; THIS_VERTEX.Normal.y = evalNormal[1]; THIS_VERTEX.Normal.z = evalNormal[2]; } else { THIS_VERTEX.Normal.x = context->current.CurrentNormal.x; THIS_VERTEX.Normal.y = context->current.CurrentNormal.y; THIS_VERTEX.Normal.z = context->current.CurrentNormal.z; } if (context->enable.Map1[MGL_MAP_V4]) { eval_DoEval1(context, arg, &context->evaldata.map1[MGL_MAP_V4], evalVert); THIS_VERTEX.object.x = evalVert[0]; THIS_VERTEX.object.y = evalVert[1]; THIS_VERTEX.object.z = evalVert[2]; THIS_VERTEX.object.w = evalVert[3]; THIS_VERTEX.outcode = 0; THIS_VERTEX.inview = GL_FALSE; if (context->fog.CurrentFogSource == GL_FOG_COORD) { THIS_VERTEX.bf = context->current.CurrentFogDepth; } else { THIS_VERTEX.bf = evalVert[2]; } context->VertexBufferPointer ++; } else if (context->enable.Map1[MGL_MAP_V3]) { eval_DoEval1(context, arg, &context->evaldata.map1[MGL_MAP_V3], evalVert); THIS_VERTEX.object.x = evalVert[0]; THIS_VERTEX.object.y = evalVert[1]; THIS_VERTEX.object.z = evalVert[2]; THIS_VERTEX.object.w = 1.0; THIS_VERTEX.outcode = 0; THIS_VERTEX.inview = GL_FALSE; if (context->fog.CurrentFogSource == GL_FOG_COORD) { THIS_VERTEX.bf = context->current.CurrentFogDepth; } else { THIS_VERTEX.bf = evalVert[2]; } context->VertexBufferPointer ++; } } void cgl_GLEvalCoord1f(struct GLContextIFace *Self, GLfloat arg) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(EvalCoord1f(Self, arg)); PROFILE_ENTRY(FID_CGL_GL_EVAL_COORD_1F); eval_DoEvalCoord1f(context, arg); PROFILE_EXIT(FID_CGL_GL_EVAL_COORD_1F); } void cgl_GLMapGrid1f(struct GLContextIFace *Self, GLint n, GLfloat u1, GLfloat u2) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(MapGrid1f(Self, n, u1, u2)); GLFlagError(context, n <= 0, GL_INVALID_VALUE); context->evaluator.u1.start = u1; context->evaluator.u1.end = u2; context->evaluator.u1.num = n; } void cgl_GLEvalMesh1(struct GLContextIFace *Self, GLenum mode, GLint p1, GLint p2) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(EvalMesh1(Self, mode, p1, p2)); PROFILE_ENTRY(FID_CGL_GL_EVAL_MESH_1); int i; GLevalgrid *grid = &context->evaluator.u1; GLfloat du; if (grid->num == 0) { return; } du = (grid->end - grid->start) / (grid->num); switch (mode) { case GL_POINT: Self->GLBegin(GL_POINTS); break; case GL_LINE: Self->GLBegin(GL_LINE_STRIP); break; default: context->CurrentError = GL_INVALID_ENUM; return; } for (i = p1; i <= p2; i++) { GLfloat u; if (i == grid->num) { u = grid->end; } else { u = grid->start + i * du; } eval_DoEvalCoord1f(context, u); } Self->GLEnd(); PROFILE_EXIT(FID_CGL_GL_EVAL_MESH_1); } void cgl_GLEvalPoint1(struct GLContextIFace *Self, GLint p) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(EvalPoint1(Self, p)); PROFILE_ENTRY(FID_CGL_GL_EVAL_POINT_1); GLevalgrid *grid = &context->evaluator.u1; GLfloat du; if (grid->num == 0) { return; } if (p == grid->num) { du = grid->end; } else { du = (grid->end - grid->start) / (grid->num); du = grid->start + p * du; } eval_DoEvalCoord1f(context, du); PROFILE_EXIT(FID_CGL_GL_EVAL_POINT_1); } /* * 2-dimensional evaluators */ int eval_SetupMap2(GLeval2 *map, GLfloat u1, GLfloat u2, GLint uorder, GLfloat v1, GLfloat v2, GLfloat vorder) { map->uOrder = uorder; map->u1 = u1; map->u2 = u2; map->vOrder = vorder; map->v1 = v1; map->v2 = v2; /* Make sure data is large enough to take up all control points */ int needSize = map->k * map->uOrder * map->vOrder * sizeof(GLfloat); if (needSize > map->datasize) { FreeVecInternal(map->data); map->data = (GLfloat *)AllocVecInternal(needSize, MEMF_ANY); if (map->data) { map->datasize = needSize; } else { map->datasize = 0; } } return (map->data != 0); } void eval_ReadPoints2f(GLeval2 *map, GLint ustride, GLint vstride, const GLfloat *points) { int i, j, k; GLfloat *data = map->data; assert (map->datasize >= (map->k * map->uOrder * map->vOrder * sizeof(GLfloat))); for (i = 0; i < map->uOrder; i++) { const GLfloat *oldPoints = points; for (j = 0; j < map->vOrder; j++) { for (k = 0; k < map->k; k++) { *data++ = points[k]; } points += vstride; //data += map->k; } points = oldPoints + ustride; } } void eval_ReadPoints2d(GLeval2 *map, GLint ustride, GLint vstride, const GLdouble *points) { int i, j, k; GLfloat *data = map->data; assert (map->datasize >= (map->k * map->uOrder * map->vOrder * sizeof(GLfloat))); for (i = 0; i < map->uOrder; i++) { const GLdouble *oldPoints = points; for (j = 0; j < map->vOrder; j++) { for (k = 0; k < map->k; k++) { *data++ = (GLfloat)points[k]; } points += vstride; //data += map->k; } points = oldPoints + ustride; } } void cgl_GLMap2f( struct GLContextIFace *Self, GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points ) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(Map2f(Self, target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points)); PROFILE_ENTRY(FID_CGL_GL_MAP_2F); /* Check input parameters */ GLFlagError(context, u1 == u2, GL_INVALID_VALUE); GLFlagError(context, v1 == v2, GL_INVALID_VALUE); int k = eval_TargetToComponents(target); GLFlagError(context, ustride < k, GL_INVALID_VALUE); GLFlagError(context, vstride < k, GL_INVALID_VALUE); int map = eval_TargetToIndex(target); GLFlagError(context, map < 0, GL_INVALID_ENUM); if (!eval_SetupMap2(&context->evaldata.map2[map], u1, u2, uorder, v1, v2, vorder)) { context->CurrentError = GL_INVALID_VALUE; return; } eval_ReadPoints2f(&context->evaldata.map2[map], ustride, vstride, points); PROFILE_EXIT(FID_CGL_GL_MAP_2F); } void cgl_GLMap2d(struct GLContextIFace *Self, GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(Map2d(Self, target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points)); PROFILE_ENTRY(FID_CGL_GL_MAP_2D); /* Check input parameters */ GLFlagError(context, u1 == u2, GL_INVALID_VALUE); GLFlagError(context, v1 == v2, GL_INVALID_VALUE); int k = eval_TargetToComponents(target); GLFlagError(context, ustride < k, GL_INVALID_VALUE); GLFlagError(context, vstride < k, GL_INVALID_VALUE); int map = eval_TargetToIndex(target); GLFlagError(context, map < 0, GL_INVALID_ENUM); if (!eval_SetupMap2(&context->evaldata.map2[map], (GLfloat)u1, (GLfloat)u2, uorder, (GLfloat)v1, (GLfloat)v2, vorder) ) { context->CurrentError = GL_INVALID_VALUE; return; } eval_ReadPoints2d(&context->evaldata.map2[map], ustride, vstride, points); PROFILE_EXIT(FID_CGL_GL_MAP_2D); } void eval_PrecalcAndDeriv(GLevalpre *pre, GLint order, GLfloat u) { int i, j; /* Check if still valid */ if (pre->order == order && pre->u == u && pre->derivValid == GL_TRUE) return; pre->order = order; pre->u = u; pre->derivValid = GL_TRUE; GLfloat oneMinusU = 1.0 - u; /* Shortcut for order == 1 */ if (order == 1) { pre->factor[0] = 1.0; pre->deriv[0] = 0.0; return; } else if (order == 2) { pre->factor[0] = oneMinusU; pre->factor[1] = u; pre->deriv[0] = -1.0; pre->deriv[1] = 1.0; return; } pre->factor[0] = oneMinusU; pre->factor[1] = u; for (i = 2; i < order - 1; i++) { GLfloat old = pre->factor[0] * u; pre->factor[0] = oneMinusU * pre->factor[0]; for (j = 1; j < i; j++) { GLfloat t = old; old = pre->factor[j] * u; pre->factor[j] = t + oneMinusU * pre->factor[j]; } pre->factor[j] = old; } pre->deriv[0] = - pre->factor[0]; for (j = 1; j < order - 1; j++) { pre->deriv[j] = pre->factor[j-1] - pre->factor[j]; } pre->deriv[j] = pre->factor[j-1]; GLfloat old = pre->factor[0] * u; pre->factor[0] = oneMinusU * pre->factor[0]; for (j = 1; j < i; j++) { GLfloat t = old; old = pre->factor[j] * u; pre->factor[j] = t + oneMinusU * pre->factor[j]; } pre->factor[j] = old; } void eval_DoEval2(GLcontext context, GLfloat u, GLfloat v, GLeval2 *map, GLfloat *out) { /* This generates a k-dimensional output from the input vector using the * given map */ if (map->u2 == map->u1) { return; } if (map->v2 == map->v1) { return; } GLfloat utick = (u - map->u1) / (map->u2 - map->u1); GLfloat vtick = (v - map->v1) / (map->v2 - map->v1); eval_Precalc(&context->evaldata.u, map->uOrder, utick); eval_Precalc(&context->evaldata.v, map->vOrder, vtick); for (int k = 0; k < map->k; k++) { int i, j; GLfloat *outData = out + k; GLfloat *control = &map->data[k]; GLfloat p; *outData = 0; for (i = 0; i < map->uOrder; i++) { p = 0.0; for (j = 0; j < map->vOrder; j++) { p += context->evaldata.v.factor[j] * (*control); control += map->k; } *outData += context->evaldata.u.factor[i] * p; } } } void eval_DoEval2Deriv(GLcontext context, GLfloat u, GLfloat v, GLfloat *du, GLfloat *dv, GLeval2 *map, GLfloat *out) { /* This generates a k-dimensional output from the input vector using the * given map */ if (map->u2 == map->u1) { return; } if (map->v2 == map->v1) { return; } GLfloat utick = (u - map->u1) / (map->u2 - map->u1); GLfloat vtick = (v - map->v1) / (map->v2 - map->v1); eval_PrecalcAndDeriv(&context->evaldata.u, map->uOrder, utick); eval_PrecalcAndDeriv(&context->evaldata.v, map->vOrder, vtick); for (int k = 0; k < map->k; k++) { int i, j; GLfloat *control = map->data + k; GLfloat p; GLfloat pdv; out[k] = 0.0; du[k] = 0.0; dv[k] = 0.0; for (i = 0; i < map->uOrder; i++) { p = 0.0; pdv = 0.0; for (j = 0; j < map->vOrder; j++) { p += context->evaldata.v.factor[j] * (*control); pdv += context->evaldata.v.deriv[j] * (*control); control += map->k; } out[k] += context->evaldata.u.factor[i] * p; du[k] += context->evaldata.u.deriv[i] * p; dv[k] += context->evaldata.u.factor[i] * pdv; } } } void eval_FirstPartials(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]; } void eval_Normal2(GLfloat *n, GLfloat *pu, GLfloat *pv) { GLfloat len; 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]; len = n[0]*n[0] + n[1]*n[1] + n[2]*n[2]; if (len <= 0) { n[0] = 0.0; n[1] = 0.0; n[2] = 0.0; } else if (len != 1.0) { len = fast_reciprocal_sqrt(len); n[0] *= len; n[1] *= len; n[2] *= len; } } void eval_DoEvalCoord2f(GLcontext context, GLfloat u, GLfloat v, struct __EvalBuffer *state) { GLfloat evalColor[4]; GLfloat evalTexCoord[4]; GLfloat evalNormal[3]; GLfloat evalVert[4]; GLfloat du[4]; GLfloat dv[4]; if (state) { state->changed = 0; } if (context->enable.Map2[MGL_MAP_C4]) { eval_DoEval2(context, u, v, &context->evaldata.map2[MGL_MAP_C4], evalColor); THIS_VERTEX.r = evalColor[0]; THIS_VERTEX.g = evalColor[1]; THIS_VERTEX.b = evalColor[2]; THIS_VERTEX.a = evalColor[3]; if (state) { state->changed |= __CHANGED_COLOR; memcpy(state->evalColor, evalColor, 4*sizeof(GLfloat)); } #ifdef MGL_USE_LIGHTING if (context->enable.ColorMaterial) { light_UpdateColorMaterialColor(context, evalColor); } #endif } else { THIS_VERTEX.r = context->current.CurrentColor.r; THIS_VERTEX.g = context->current.CurrentColor.g; THIS_VERTEX.b = context->current.CurrentColor.b; THIS_VERTEX.a = context->current.CurrentColor.a; #ifdef MGL_USE_LIGHTING if (context->enable.ColorMaterial) { light_UpdateColorMaterial(context); } #endif } if (context->texture.MaxTextureUnit > -1) { if (context->enable.Map2[MGL_MAP_TC4] || context->enable.Map2[MGL_MAP_TC3] || context->enable.Map2[MGL_MAP_TC2] || context->enable.Map2[MGL_MAP_TC1] ) { if (context->enable.Map2[MGL_MAP_TC4]) { eval_DoEval2(context, u, v, &context->evaldata.map2[MGL_MAP_TC4], evalTexCoord); THIS_VERTEX.uvw[0].u = evalTexCoord[0] / evalTexCoord[3]; THIS_VERTEX.uvw[0].v = evalTexCoord[1] / evalTexCoord[3]; THIS_VERTEX.uvw[0].w = evalTexCoord[3]; THIS_VERTEX.rhw_valid[0] = GL_TRUE; if (state) { state->changed |= __CHANGED_TEXCOORD; state->tu = THIS_VERTEX.uvw[0].u; state->tv = THIS_VERTEX.uvw[0].v; state->tw = THIS_VERTEX.uvw[0].w; state->twvalid = GL_TRUE; } } else if (context->enable.Map2[MGL_MAP_TC3]) { eval_DoEval2(context, u, v, &context->evaldata.map2[MGL_MAP_TC3], evalTexCoord); THIS_VERTEX.uvw[0].u = evalTexCoord[0]; THIS_VERTEX.uvw[0].v = evalTexCoord[1]; THIS_VERTEX.uvw[0].w = 1.0; THIS_VERTEX.rhw_valid[0] = GL_FALSE; if (state) { state->changed |= __CHANGED_TEXCOORD; state->tu = THIS_VERTEX.uvw[0].u; state->tv = THIS_VERTEX.uvw[0].v; state->tw = THIS_VERTEX.uvw[0].w; state->twvalid = GL_FALSE; } } else if (context->enable.Map2[MGL_MAP_TC2]) { eval_DoEval2(context, u, v, &context->evaldata.map2[MGL_MAP_TC2], evalTexCoord); THIS_VERTEX.uvw[0].u = evalTexCoord[0]; THIS_VERTEX.uvw[0].v = evalTexCoord[1]; THIS_VERTEX.uvw[0].w = 1.0; THIS_VERTEX.rhw_valid[0] = GL_FALSE; if (state) { state->changed |= __CHANGED_TEXCOORD; state->tu = THIS_VERTEX.uvw[0].u; state->tv = THIS_VERTEX.uvw[0].v; state->tw = THIS_VERTEX.uvw[0].w; state->twvalid = GL_FALSE; } } else if (context->enable.Map2[MGL_MAP_TC1]) { eval_DoEval2(context, u, v, &context->evaldata.map2[MGL_MAP_TC1], evalTexCoord); THIS_VERTEX.uvw[0].u = evalTexCoord[0]; THIS_VERTEX.uvw[0].v = 0.0; THIS_VERTEX.uvw[0].w = 1.0; THIS_VERTEX.rhw_valid[0] = GL_FALSE; if (state) { state->changed |= __CHANGED_TEXCOORD; state->tu = THIS_VERTEX.uvw[0].u; state->tv = THIS_VERTEX.uvw[0].v; state->tw = THIS_VERTEX.uvw[0].w; state->twvalid = GL_FALSE; } } } else { int i; for (i = 0; i <= context->texture.MaxTextureUnit; i++) { if (context->enable.Texture2D[i] == GL_TRUE || context->enable.Texture1D[i]) { if (context->current.CurTexQValid[i] == GL_TRUE) { THIS_VERTEX.uvw[i].u = context->current.CurTexS[i] / context->current.CurTexQ[i]; THIS_VERTEX.uvw[i].v = context->current.CurTexT[i] / context->current.CurTexQ[i]; THIS_VERTEX.uvw[i].w = context->current.CurTexQ[i]; THIS_VERTEX.rhw_valid[i] = GL_TRUE; } else { THIS_VERTEX.uvw[i].u = context->current.CurTexS[i]; THIS_VERTEX.uvw[i].v = context->current.CurTexT[i]; THIS_VERTEX.uvw[i].w = 1.0; THIS_VERTEX.rhw_valid[i] = GL_FALSE; } if (i == 0 && state) { state->changed |= __CHANGED_TEXCOORD; state->tu = THIS_VERTEX.uvw[0].u; state->tv = THIS_VERTEX.uvw[0].v; state->tw = THIS_VERTEX.uvw[0].w; state->twvalid = THIS_VERTEX.rhw_valid[0]; } } } } } if (context->enable.AutoNormal) { /* If normals are generated automatically, the normal map is ignored * and generated normals are used */ if (context->enable.Map2[MGL_MAP_V4]) { eval_DoEval2Deriv(context, u, v, du, dv, &context->evaldata.map2[MGL_MAP_V4], evalVert); eval_FirstPartials(evalVert, du, dv); eval_Normal2(evalNormal, du, dv); THIS_VERTEX.Normal.x = evalNormal[0]; THIS_VERTEX.Normal.y = evalNormal[1]; THIS_VERTEX.Normal.z = evalNormal[2]; THIS_VERTEX.object.x = evalVert[0]; THIS_VERTEX.object.y = evalVert[1]; THIS_VERTEX.object.z = evalVert[2]; THIS_VERTEX.object.w = evalVert[3]; THIS_VERTEX.outcode = 0; THIS_VERTEX.inview = GL_FALSE; if (context->fog.CurrentFogSource == GL_FOG_COORD) { THIS_VERTEX.bf = context->current.CurrentFogDepth; } else { THIS_VERTEX.bf = evalVert[2]; } context->VertexBufferPointer ++; if (state) { state->changed |= __CHANGED_NORMAL|__CHANGED_VERTEX; memcpy(state->evalVert, evalVert, 4*sizeof(GLfloat)); memcpy(state->evalNormal, evalNormal, 3*sizeof(GLfloat)); } } else if (context->enable.Map2[MGL_MAP_V3]) { eval_DoEval2Deriv(context, u, v, du, dv, &context->evaldata.map2[MGL_MAP_V3], evalVert); eval_Normal2(evalNormal, du, dv); THIS_VERTEX.Normal.x = evalNormal[0]; THIS_VERTEX.Normal.y = evalNormal[1]; THIS_VERTEX.Normal.z = evalNormal[2]; THIS_VERTEX.object.x = evalVert[0]; THIS_VERTEX.object.y = evalVert[1]; THIS_VERTEX.object.z = evalVert[2]; THIS_VERTEX.object.w = 1.0; THIS_VERTEX.outcode = 0; THIS_VERTEX.inview = GL_FALSE; if (context->fog.CurrentFogSource == GL_FOG_COORD) { THIS_VERTEX.bf = context->current.CurrentFogDepth; } else { THIS_VERTEX.bf = evalVert[2]; } context->VertexBufferPointer ++; if (state) { state->changed |= __CHANGED_NORMAL|__CHANGED_VERTEX; memcpy(state->evalVert, evalVert, 3*sizeof(GLfloat)); state->evalVert[3] = 1.0; memcpy(state->evalNormal, evalNormal, 3*sizeof(GLfloat)); } } } else { if (context->enable.Map2[MGL_MAP_N3]) { eval_DoEval2(context, u, v, &context->evaldata.map2[MGL_MAP_N3], evalNormal); THIS_VERTEX.Normal.x = evalNormal[0]; THIS_VERTEX.Normal.y = evalNormal[1]; THIS_VERTEX.Normal.z = evalNormal[2]; if (state) { state->changed |= __CHANGED_NORMAL; memcpy(state->evalNormal, evalNormal, 3*sizeof(GLfloat)); } } else { THIS_VERTEX.Normal.x = context->current.CurrentNormal.x; THIS_VERTEX.Normal.y = context->current.CurrentNormal.y; THIS_VERTEX.Normal.z = context->current.CurrentNormal.z; } if (context->enable.Map2[MGL_MAP_V4]) { eval_DoEval2(context, u, v, &context->evaldata.map2[MGL_MAP_V4], evalVert); THIS_VERTEX.object.x = evalVert[0]; THIS_VERTEX.object.y = evalVert[1]; THIS_VERTEX.object.z = evalVert[2]; THIS_VERTEX.object.w = evalVert[3]; THIS_VERTEX.outcode = 0; THIS_VERTEX.inview = GL_FALSE; if (context->fog.CurrentFogSource == GL_FOG_COORD) { THIS_VERTEX.bf = context->current.CurrentFogDepth; } else { THIS_VERTEX.bf = evalVert[2]; } context->VertexBufferPointer ++; if (state) { state->changed |= __CHANGED_VERTEX; memcpy(state->evalVert, evalVert, 4*sizeof(GLfloat)); } } else if (context->enable.Map2[MGL_MAP_V3]) { eval_DoEval2(context, u, v, &context->evaldata.map2[MGL_MAP_V3], evalVert); THIS_VERTEX.object.x = evalVert[0]; THIS_VERTEX.object.y = evalVert[1]; THIS_VERTEX.object.z = evalVert[2]; THIS_VERTEX.object.w = 1.0; THIS_VERTEX.outcode = 0; THIS_VERTEX.inview = GL_FALSE; if (context->fog.CurrentFogSource == GL_FOG_COORD) { THIS_VERTEX.bf = context->current.CurrentFogDepth; } else { THIS_VERTEX.bf = evalVert[2]; } context->VertexBufferPointer ++; if (state) { state->changed |= __CHANGED_VERTEX; memcpy(state->evalVert, evalVert, 3*sizeof(GLfloat)); state->evalVert[3] = 1.0; } } } } void eval_DoBufferCoord2f(GLcontext context, struct __EvalBuffer *state) { if (state->changed & __CHANGED_COLOR) { THIS_VERTEX.r = state->evalColor[0]; THIS_VERTEX.g = state->evalColor[1]; THIS_VERTEX.b = state->evalColor[2]; THIS_VERTEX.a = state->evalColor[3]; #ifdef MGL_USE_LIGHTING if (context->enable.ColorMaterial) { light_UpdateColorMaterialColor(context, state->evalColor); } #endif } else { THIS_VERTEX.r = context->current.CurrentColor.r; THIS_VERTEX.g = context->current.CurrentColor.g; THIS_VERTEX.b = context->current.CurrentColor.b; THIS_VERTEX.a = context->current.CurrentColor.a; #ifdef MGL_USE_LIGHTING if (context->enable.ColorMaterial) { light_UpdateColorMaterial(context); } #endif } if (context->texture.MaxTextureUnit > -1) { if (state->changed & __CHANGED_TEXCOORD) { THIS_VERTEX.uvw[0].u = state->tu; THIS_VERTEX.uvw[0].v = state->tv; THIS_VERTEX.uvw[0].w = state->tw; THIS_VERTEX.rhw_valid[0] = state->twvalid; } else { int i; for (i = 0; i <= context->texture.MaxTextureUnit; i++) { if (context->enable.Texture2D[i] == GL_TRUE || context->enable.Texture1D[i] ) { if (context->current.CurTexQValid[i] == GL_TRUE) { THIS_VERTEX.uvw[i].u = context->current.CurTexS[i] / context->current.CurTexQ[i]; THIS_VERTEX.uvw[i].v = context->current.CurTexT[i] / context->current.CurTexQ[i]; THIS_VERTEX.uvw[i].w = context->current.CurTexQ[i]; THIS_VERTEX.rhw_valid[i] = GL_TRUE; } else { THIS_VERTEX.uvw[i].u = context->current.CurTexS[i]; THIS_VERTEX.uvw[i].v = context->current.CurTexT[i]; THIS_VERTEX.uvw[i].w = 1.0; THIS_VERTEX.rhw_valid[i] = GL_FALSE; } } } } } if (state->changed & __CHANGED_NORMAL) { THIS_VERTEX.Normal.x = state->evalNormal[0]; THIS_VERTEX.Normal.y = state->evalNormal[1]; THIS_VERTEX.Normal.z = state->evalNormal[2]; } else { THIS_VERTEX.Normal.x = context->current.CurrentNormal.x; THIS_VERTEX.Normal.y = context->current.CurrentNormal.y; THIS_VERTEX.Normal.z = context->current.CurrentNormal.z; } if (state->changed & __CHANGED_VERTEX) { THIS_VERTEX.object.x = state->evalVert[0]; THIS_VERTEX.object.y = state->evalVert[1]; THIS_VERTEX.object.z = state->evalVert[2]; THIS_VERTEX.object.w = state->evalVert[3]; THIS_VERTEX.outcode = 0; THIS_VERTEX.inview = GL_FALSE; if (context->fog.CurrentFogSource == GL_FOG_COORD) { THIS_VERTEX.bf = context->current.CurrentFogDepth; } else { THIS_VERTEX.bf = state->evalVert[2]; } context->VertexBufferPointer ++; } } void cgl_GLEvalCoord2f(struct GLContextIFace *Self, GLfloat u, GLfloat v) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(EvalCoord2f(Self, u, v)); PROFILE_ENTRY(FID_CGL_GL_EVAL_COORD_2F); eval_DoEvalCoord2f(context, u, v, NULL); PROFILE_EXIT(FID_CGL_GL_EVAL_COORD_2F); } void cgl_GLMapGrid2f(struct GLContextIFace *Self, GLint nu, GLfloat u1, GLfloat u2, GLint nv, GLfloat v1, GLfloat v2) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(MapGrid2f(Self, nu, u1, u2, nv, v1, v2)); GLFlagError(context, nu <= 0, GL_INVALID_VALUE); GLFlagError(context, nv <= 0, GL_INVALID_VALUE); context->evaluator.u2.start = u1; context->evaluator.u2.end = u2; context->evaluator.u2.num = nu; context->evaluator.v2.start = v1; context->evaluator.v2.end = v2; context->evaluator.v2.num = nv; } void eval_Mesh2Point(struct GLContextIFace *Self, GLint p1, GLint p2, GLint q1, GLint q2) { GLcontext context = GET_INSTANCE(Self); GLevalgrid *ugrid = &context->evaluator.u2; GLevalgrid *vgrid = &context->evaluator.v2; GLfloat dv; GLfloat du; if (ugrid->num == 0 || vgrid->num == 0) { return; } du = (ugrid->end - ugrid->start) / (ugrid->num); dv = (vgrid->end - vgrid->start) / (vgrid->num); int i, j; Self->GLBegin(GL_POINTS); for (i = p1; i <= p2; i++) { GLfloat u1 = ugrid->end; if (i != ugrid->num) { u1 = ugrid->start + i * du; } for (j = q1; j <= q2; j++) { GLfloat v1 = vgrid->end; if (j != vgrid->num) { v1 = vgrid->start + j * dv; } eval_DoEvalCoord2f(context, u1, v1, NULL); } } Self->GLEnd(); } /* About the state buffering: * The mesh will be composed of quad strips. These strips share a common edge * that would under normal circumstances be computed twice. Therefore, we buffer * the computed values for the shared edges. */ void eval_Mesh2Fill(struct GLContextIFace *Self, GLint lowU, GLint highU, GLint lowV, GLint highV) { GLcontext context = GET_INSTANCE(Self); GLevalgrid *ugrid = &context->evaluator.u2; GLevalgrid *vgrid = &context->evaluator.v2; GLfloat dv; GLfloat du; if (ugrid->num == 0 || vgrid->num == 0) { return; } du = (ugrid->end - ugrid->start) / (ugrid->num); dv = (vgrid->end - vgrid->start) / (vgrid->num); int i, j; struct __EvalBuffer *state = alloca((highV - lowV + 1) * sizeof (struct __EvalBuffer)); for (i = lowU; i < highU; i++) { Self->GLBegin(GL_QUAD_STRIP); GLfloat u1 = ugrid->end; if (i != ugrid->num) { u1 = ugrid->start + i * du; } GLfloat u2 = ugrid->end; if ((i+1) != ugrid->num) { u2 = ugrid->start + (i+1) * du; } for (j = highV; j >= lowV; j--) { GLfloat v1 = vgrid->end; if (j != vgrid->num) { v1 = vgrid->start + j * dv; } if (i != lowU) { eval_DoBufferCoord2f(context, state + (j - lowV)); } else { eval_DoEvalCoord2f(context, u1, v1, NULL); } eval_DoEvalCoord2f(context, u2, v1, state + (j - lowV)); } Self->GLEnd(); } } void eval_Mesh2Line(struct GLContextIFace *Self, GLint lowU, GLint highU, GLint lowV, GLint highV) { GLcontext context = GET_INSTANCE(Self); GLevalgrid *ugrid = &context->evaluator.u2; GLevalgrid *vgrid = &context->evaluator.v2; GLfloat dv; GLfloat du; uint32 row = 0; GLfloat u1, u2 = 0.0, v1, v2 ; if (ugrid->num == 0 || vgrid->num == 0) { return; } du = (ugrid->end - ugrid->start) / (ugrid->num); dv = (vgrid->end - vgrid->start) / (vgrid->num); int i, j; struct __EvalBuffer *state = alloca((highV - lowV + 2) * sizeof (struct __EvalBuffer)); for (i = lowU; i < highU; i++) { u1 = ugrid->end; if (i != ugrid->num) { u1 = ugrid->start + i * du; } u2 = ugrid->end; if ((i+1) != ugrid->num) { u2 = ugrid->start + (i+1) * du; } row = 0; for (j = lowV; j <= highV; j++) { v1 = vgrid->end; if (j != vgrid->num) { v1 = vgrid->start + j * dv; } v2 = vgrid->end; if (j+1 != vgrid->num) { v2 = vgrid->start + (j+1) * dv; } Self->GLBegin(GL_LINE_STRIP); if (j != highV) { if (i != lowU) { eval_DoBufferCoord2f(context, state + row + 1); } else { eval_DoEvalCoord2f(context, u1, v2, state + row + 1); } } if (i != lowU && j != lowV) { eval_DoBufferCoord2f(context, state + row); } else { eval_DoEvalCoord2f(context, u1, v1, NULL); } eval_DoEvalCoord2f(context, u2, v1, state + row); Self->GLEnd(); row++; } } Self->GLBegin(GL_LINE_STRIP); for (j = highV; j >= lowV; j--) { row--; v1 = vgrid->end; if (j != vgrid->num) { v1 = vgrid->start + j * dv; } if (row != 0) { eval_DoBufferCoord2f(context, state + row); } else { eval_DoEvalCoord2f(context, u2, v1, NULL); } } Self->GLEnd(); } void cgl_GLEvalMesh2(struct GLContextIFace *Self, GLenum mode, GLint p1, GLint p2, GLint q1, GLint q2) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(EvalMesh2(Self, mode, p1, p2, q1, q2)) PROFILE_ENTRY(FID_CGL_GL_EVAL_MESH_2); switch (mode) { case GL_POINT: eval_Mesh2Point(Self, p1, p2, q1, q2); break; case GL_LINE: eval_Mesh2Line(Self, p1, p2, q1, q2); break; case GL_FILL: eval_Mesh2Fill(Self, p1, p2, q1, q2); break; default: context->CurrentError = GL_INVALID_ENUM; return; } PROFILE_EXIT(FID_CGL_GL_EVAL_MESH_2); } void cgl_GLEvalPoint2(struct GLContextIFace *Self, GLint p, GLint q) { GLcontext context = GET_INSTANCE(Self); DL_CHECK(EvalPoint2(Self, p, q)) PROFILE_ENTRY(FID_CGL_GL_EVAL_POINT_2); GLevalgrid *ugrid = &context->evaluator.u2; GLevalgrid *vgrid = &context->evaluator.v2; GLfloat du; GLfloat dv; if (ugrid->num == 0 || vgrid->num == 0) { return; } if (p == ugrid->num) { du = ugrid->end; } else { du = (ugrid->end - ugrid->start) / (ugrid->num); du = ugrid->start + p * du; } if (q == vgrid->num) { dv = vgrid->end; } else { dv = (vgrid->end - vgrid->start) / (vgrid->num); dv = vgrid->start + q * dv; } eval_DoEvalCoord2f(context, du, dv, NULL); PROFILE_EXIT(FID_CGL_GL_EVAL_POINT_2); } /* * GetMap */ void cgl_GLGetMapfv(struct GLContextIFace *Self, GLenum map, GLenum value, GLfloat *data) { GLcontext context = GET_INSTANCE(Self); PROFILE_ENTRY(FID_CGL_GL_GET_MAP_FV); GLeval1 *map1 = &context->evaldata.map1[eval_TargetToIndex(map)]; GLeval2 *map2 = &context->evaldata.map2[eval_TargetToIndex(map)]; int i; switch (map) { case GL_MAP1_VERTEX_3: case GL_MAP1_VERTEX_4: case GL_MAP1_COLOR_4: 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: switch (value) { case GL_ORDER: *data ++ = map1->order; break; case GL_COEFF: for (i = 0; i < map1->order * map1->k; i++) { *data ++ = map1->data[i]; } break; case GL_DOMAIN: *data ++ = map1->u1; *data ++ = map1->u2; // ??? break; default: context->CurrentError = GL_INVALID_ENUM; return; } break; case GL_MAP2_VERTEX_3: case GL_MAP2_VERTEX_4: case GL_MAP2_COLOR_4: 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: switch (value) { case GL_ORDER: *data ++ = map2->uOrder; *data ++ = map2->vOrder; break; case GL_COEFF: for (i = 0; i < map2->uOrder * map2->vOrder * map2->k; i++) { *data ++ = map2->data[i]; } break; case GL_DOMAIN: *data ++ = map2->u1; *data ++ = map2->u2; *data ++ = map2->v1; *data ++ = map2->v2; // ??? break; default: context->CurrentError = GL_INVALID_ENUM; return; } break; default: context->CurrentError = GL_INVALID_ENUM; return; } PROFILE_EXIT(FID_CGL_GL_GET_MAP_FV); } void cgl_GLGetMapdv(struct GLContextIFace *Self, GLenum map, GLenum value, GLdouble *data) { GLcontext context = GET_INSTANCE(Self); PROFILE_ENTRY(FID_CGL_GL_GET_MAP_DV); GLeval1 *map1 = &context->evaldata.map1[eval_TargetToIndex(map)]; GLeval2 *map2 = &context->evaldata.map2[eval_TargetToIndex(map)]; int i; switch (map) { case GL_MAP1_VERTEX_3: case GL_MAP1_VERTEX_4: case GL_MAP1_COLOR_4: 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: switch (value) { case GL_ORDER: *data ++ = (GLdouble)map1->order; break; case GL_COEFF: for (i = 0; i < map1->order * map1->k; i++) { *data ++ = (GLdouble)map1->data[i]; } break; case GL_DOMAIN: *data ++ = (GLdouble)map1->u1; *data ++ = (GLdouble)map1->u2; // ??? break; default: context->CurrentError = GL_INVALID_ENUM; return; } break; case GL_MAP2_VERTEX_3: case GL_MAP2_VERTEX_4: case GL_MAP2_COLOR_4: 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: switch (value) { case GL_ORDER: *data ++ = (GLdouble)map2->uOrder; *data ++ = (GLdouble)map2->vOrder; break; case GL_COEFF: for (i = 0; i < map2->uOrder * map2->vOrder * map2->k; i++) *data ++ = (GLdouble)map2->data[i]; break; case GL_DOMAIN: *data ++ = (GLdouble)map2->u1; *data ++ = (GLdouble)map2->u2; *data ++ = (GLdouble)map2->v1; *data ++ = (GLdouble)map2->v2; // ??? break; default: context->CurrentError = GL_INVALID_ENUM; return; } break; default: context->CurrentError = GL_INVALID_ENUM; return; } PROFILE_EXIT(FID_CGL_GL_GET_MAP_DV); } void cgl_GLGetMapiv(struct GLContextIFace *Self, GLenum map, GLenum value, GLint *data) { GLcontext context = GET_INSTANCE(Self); PROFILE_ENTRY(FID_CGL_GL_GET_MAP_IV); GLeval1 *map1 = &context->evaldata.map1[eval_TargetToIndex(map)]; GLeval2 *map2 = &context->evaldata.map2[eval_TargetToIndex(map)]; int i; switch (map) { case GL_MAP1_VERTEX_3: case GL_MAP1_VERTEX_4: case GL_MAP1_COLOR_4: 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: switch (value) { case GL_ORDER: *data ++ = (GLint)map1->order; break; case GL_COEFF: for (i = 0; i < map1->order * map1->k; i++) { *data ++ = (GLint)map1->data[i]; } break; case GL_DOMAIN: *data ++ = (GLint)map1->u1; *data ++ = (GLint)map1->u2; // ??? break; default: context->CurrentError = GL_INVALID_ENUM; return; } break; case GL_MAP2_VERTEX_3: case GL_MAP2_VERTEX_4: case GL_MAP2_COLOR_4: 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: switch (value) { case GL_ORDER: *data ++ = (GLint)map2->uOrder; *data ++ = (GLint)map2->vOrder; break; case GL_COEFF: for (i = 0; i < map2->uOrder * map2->vOrder * map2->k; i++) { *data ++ = (GLint)map2->data[i]; } break; case GL_DOMAIN: *data ++ = (GLint)map2->u1; *data ++ = (GLint)map2->u2; *data ++ = (GLint)map2->v1; *data ++ = (GLint)map2->v2; // ??? break; default: context->CurrentError = GL_INVALID_ENUM; return; } break; default: context->CurrentError = GL_INVALID_ENUM; return; } PROFILE_EXIT(FID_CGL_GL_GET_MAP_IV); }