2135 lines
64 KiB
C
2135 lines
64 KiB
C
/******************************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; i<order; i++)
|
|
{
|
|
for (j=0; j<k; j++)
|
|
{
|
|
data[j] = points[j];
|
|
}
|
|
points += stride;
|
|
data += k;
|
|
}
|
|
}
|
|
|
|
|
|
void APIPRIVATE __glFillMap1d(GLint k, GLint order, GLint stride,
|
|
const GLdouble *points, __GLfloat *data)
|
|
{
|
|
int i,j;
|
|
|
|
for (i=0; i<order; i++)
|
|
{
|
|
for (j=0; j<k; j++)
|
|
{
|
|
data[j] = points[j];
|
|
}
|
|
points += stride;
|
|
data += k;
|
|
}
|
|
}
|
|
|
|
void APIPRIVATE __glFillMap2f(GLint k, GLint majorOrder, GLint minorOrder,
|
|
GLint majorStride, GLint minorStride,
|
|
const GLfloat *points, __GLfloat *data)
|
|
{
|
|
int i,j,x;
|
|
|
|
#ifndef __GL_DOUBLE
|
|
/* Optimization always hit during display list execution */
|
|
if (k == minorStride && majorStride == k * minorOrder)
|
|
{
|
|
__GL_MEMCOPY(data, points,
|
|
__glMap2_size(k, majorOrder, minorOrder) * sizeof(__GLfloat));
|
|
return;
|
|
}
|
|
#endif
|
|
for (i=0; i<majorOrder; i++)
|
|
{
|
|
for (j=0; j<minorOrder; j++)
|
|
{
|
|
for (x=0; x<k; x++)
|
|
{
|
|
data[x] = points[x];
|
|
}
|
|
points += minorStride;
|
|
data += k;
|
|
}
|
|
points += majorStride - minorStride * minorOrder;
|
|
}
|
|
}
|
|
|
|
void APIPRIVATE __glFillMap2d(GLint k, GLint majorOrder, GLint minorOrder,
|
|
GLint majorStride, GLint minorStride,
|
|
const GLdouble *points, __GLfloat *data)
|
|
{
|
|
int i,j,x;
|
|
|
|
for (i=0; i<majorOrder; i++)
|
|
{
|
|
for (j=0; j<minorOrder; j++)
|
|
{
|
|
for (x=0; x<k; x++)
|
|
{
|
|
data[x] = points[x];
|
|
}
|
|
points += minorStride;
|
|
data += k;
|
|
}
|
|
points += majorStride - minorStride * minorOrder;
|
|
}
|
|
}
|
|
|
|
|
|
#define TYPE_COEFF_AND_DERIV 1
|
|
#define TYPE_COEFF 2
|
|
|
|
|
|
void DoDomain1(__GLevaluatorMachine *em, __GLfloat u, __GLevaluator1 *e,
|
|
__GLfloat *v, __GLfloat *baseData)
|
|
{
|
|
GLint j, row;
|
|
__GLfloat uprime;
|
|
__GLfloat *data;
|
|
GLint k;
|
|
|
|
#ifdef NT
|
|
ASSERTOPENGL(e->u2 != 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; j<order-1; j++)" loop, but it is always
|
|
** executed at least once, so this is more efficient.
|
|
*/
|
|
j=1;
|
|
do
|
|
{
|
|
coeffDeriv[j] = coeff[j-1] - coeff[j];
|
|
j++;
|
|
} while (j < order - 1);
|
|
coeffDeriv[j] = coeff[j-1];
|
|
|
|
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;
|
|
}
|
|
|
|
void DoDomain2(__GLevaluatorMachine *em, __GLfloat u, __GLfloat v,
|
|
__GLevaluator2 *e, __GLfloat *r, __GLfloat *baseData)
|
|
{
|
|
GLint j, row, col;
|
|
__GLfloat uprime;
|
|
__GLfloat vprime;
|
|
__GLfloat p;
|
|
__GLfloat *data;
|
|
GLint k;
|
|
|
|
#ifdef NT
|
|
ASSERTOPENGL((e->u2 != 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; i<nv; i++)
|
|
for(j=0; j<nu-1; j++) {
|
|
buff[k++] = i*nu+j;
|
|
buff[k++] = i*nu+j+1;
|
|
}
|
|
|
|
// Draw lines along V direction
|
|
start = 1 ;
|
|
if (sides & MV_LEFT)
|
|
start = 0;
|
|
for (i=start; i<nu; i++)
|
|
for (j=0; j<nv-1; j++) {
|
|
buff[k++] = j*nu+i;
|
|
buff[k++] = (j+1)*nu+i;
|
|
}
|
|
break ;
|
|
|
|
case GL_FILL :
|
|
for (i=0, k=0; i<nv-1; i++)
|
|
for (j=0; j<nu-1; j++) {
|
|
buff[k++] = i*nu+j;
|
|
buff[k++] = (i+1)*nu+j;
|
|
buff[k++] = (i+1)*nu+j+1;
|
|
buff[k++] = i*nu+j+1;
|
|
}
|
|
break ;
|
|
}
|
|
return k; //the total number of points
|
|
}
|
|
|
|
void FASTCALL PA_EvalMesh2Fast(__GLcontext *gc, GLint u1, GLint u2, GLint v1,
|
|
GLint v2, GLint meshSize, GLenum mode,
|
|
GLuint sides)
|
|
{
|
|
GLint i, j, k, nu, nv;
|
|
__GLcolor currentColor;
|
|
__GLcoord currentNormal, currentTexture;
|
|
GLboolean currentEdgeFlag;
|
|
MESHVERTEX *mv, mvBuf[MAX_U_SIZE*MAX_V_SIZE];
|
|
GLuint mflags = 0;
|
|
GLuint stride;
|
|
GLubyte *disBuf;
|
|
__GLvertexArray currentVertexInfo;
|
|
GLuint texSize = 0, start, totalPts;
|
|
GLubyte dBufSmall[4*MAX_U_SIZE*MAX_V_SIZE]; //small
|
|
__GLfloat u, v;
|
|
__GLfloat du, dv;
|
|
__GLevaluatorGrid *gu;
|
|
__GLevaluatorGrid *gv;
|
|
|
|
// Now build the mesh vertex array [0..u2-u1, 0..v2-v1]
|
|
|
|
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;
|
|
|
|
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;
|
|
}
|