📄 insurfeval.cc
字号:
* n: return normal, of dimension 3
*/
void OpenGLSurfaceEvaluator::inComputeNormal2(REAL *pu, REAL *pv, REAL *n)
{
REAL mag;
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];
mag = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
if (mag > 0.0) {
n[0] /= mag;
n[1] /= mag;
n[2] /= mag;
}
}
/*Compute point and normal
*see the head of inDoDomain2WithDerivs
*for the meaning of the arguments
*/
void OpenGLSurfaceEvaluator::inDoEvalCoord2(REAL u, REAL v,
REAL *retPoint, REAL *retNormal)
{
REAL du[4];
REAL dv[4];
assert(global_ev_k>=3 && global_ev_k <= 4);
/*compute homegeneous point and partial derivatives*/
inDoDomain2WithDerivs(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv);
#ifdef AVOID_ZERO_NORMAL
if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
{
REAL tempdu[4];
REAL tempdata[4];
REAL u1 = global_ev_u1;
REAL u2 = global_ev_u2;
if(u-MYDELTA*(u2-u1) < u1)
u = u+ MYDELTA*(u2-u1);
else
u = u-MYDELTA*(u2-u1);
inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv);
}
if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
{
REAL tempdv[4];
REAL tempdata[4];
REAL v1 = global_ev_v1;
REAL v2 = global_ev_v2;
if(v-MYDELTA*(v2-v1) < v1)
v = v+ MYDELTA*(v2-v1);
else
v = v-MYDELTA*(v2-v1);
inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv);
}
#endif
/*compute normal*/
switch(global_ev_k){
case 3:
inComputeNormal2(du, dv, retNormal);
break;
case 4:
inComputeFirstPartials(retPoint, du, dv);
inComputeNormal2(du, dv, retNormal);
/*transform the homegeneous coordinate of retPoint into inhomogenous one*/
retPoint[0] /= retPoint[3];
retPoint[1] /= retPoint[3];
retPoint[2] /= retPoint[3];
break;
}
/*output this vertex*/
/* inMeshStreamInsert(global_ms, retPoint, retNormal);*/
glNormal3fv(retNormal);
glVertex3fv(retPoint);
#ifdef DEBUG
printf("vertex(%f,%f,%f)\n", retPoint[0],retPoint[1],retPoint[2]);
#endif
}
/*Compute point and normal
*see the head of inDoDomain2WithDerivs
*for the meaning of the arguments
*/
void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE_BU(REAL u, REAL v,
REAL *retPoint, REAL *retNormal)
{
REAL du[4];
REAL dv[4];
assert(global_ev_k>=3 && global_ev_k <= 4);
/*compute homegeneous point and partial derivatives*/
// inPreEvaluateBU(global_ev_k, global_ev_uorder, global_ev_vorder, (u-global_ev_u1)/(global_ev_u2-global_ev_u1), global_ev_ctlPoints);
inDoDomain2WithDerivsBU(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv);
#ifdef AVOID_ZERO_NORMAL
if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
{
REAL tempdu[4];
REAL tempdata[4];
REAL u1 = global_ev_u1;
REAL u2 = global_ev_u2;
if(u-MYDELTA*(u2-u1) < u1)
u = u+ MYDELTA*(u2-u1);
else
u = u-MYDELTA*(u2-u1);
inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv);
}
if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
{
REAL tempdv[4];
REAL tempdata[4];
REAL v1 = global_ev_v1;
REAL v2 = global_ev_v2;
if(v-MYDELTA*(v2-v1) < v1)
v = v+ MYDELTA*(v2-v1);
else
v = v-MYDELTA*(v2-v1);
inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv);
}
#endif
/*compute normal*/
switch(global_ev_k){
case 3:
inComputeNormal2(du, dv, retNormal);
break;
case 4:
inComputeFirstPartials(retPoint, du, dv);
inComputeNormal2(du, dv, retNormal);
/*transform the homegeneous coordinate of retPoint into inhomogenous one*/
retPoint[0] /= retPoint[3];
retPoint[1] /= retPoint[3];
retPoint[2] /= retPoint[3];
break;
}
}
/*Compute point and normal
*see the head of inDoDomain2WithDerivs
*for the meaning of the arguments
*/
void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE_BV(REAL u, REAL v,
REAL *retPoint, REAL *retNormal)
{
REAL du[4];
REAL dv[4];
assert(global_ev_k>=3 && global_ev_k <= 4);
/*compute homegeneous point and partial derivatives*/
// inPreEvaluateBV(global_ev_k, global_ev_uorder, global_ev_vorder, (v-global_ev_v1)/(global_ev_v2-global_ev_v1), global_ev_ctlPoints);
inDoDomain2WithDerivsBV(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv);
#ifdef AVOID_ZERO_NORMAL
if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
{
REAL tempdu[4];
REAL tempdata[4];
REAL u1 = global_ev_u1;
REAL u2 = global_ev_u2;
if(u-MYDELTA*(u2-u1) < u1)
u = u+ MYDELTA*(u2-u1);
else
u = u-MYDELTA*(u2-u1);
inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv);
}
if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
{
REAL tempdv[4];
REAL tempdata[4];
REAL v1 = global_ev_v1;
REAL v2 = global_ev_v2;
if(v-MYDELTA*(v2-v1) < v1)
v = v+ MYDELTA*(v2-v1);
else
v = v-MYDELTA*(v2-v1);
inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv);
}
#endif
/*compute normal*/
switch(global_ev_k){
case 3:
inComputeNormal2(du, dv, retNormal);
break;
case 4:
inComputeFirstPartials(retPoint, du, dv);
inComputeNormal2(du, dv, retNormal);
/*transform the homegeneous coordinate of retPoint into inhomogenous one*/
retPoint[0] /= retPoint[3];
retPoint[1] /= retPoint[3];
retPoint[2] /= retPoint[3];
break;
}
}
/*Compute point and normal
*see the head of inDoDomain2WithDerivs
*for the meaning of the arguments
*/
void OpenGLSurfaceEvaluator::inDoEvalCoord2NOGE(REAL u, REAL v,
REAL *retPoint, REAL *retNormal)
{
REAL du[4];
REAL dv[4];
assert(global_ev_k>=3 && global_ev_k <= 4);
/*compute homegeneous point and partial derivatives*/
inDoDomain2WithDerivs(global_ev_k, u, v, global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, retPoint, du, dv);
#ifdef AVOID_ZERO_NORMAL
if(myabs(dv[0]) <= MYZERO && myabs(dv[1]) <= MYZERO && myabs(dv[2]) <= MYZERO)
{
REAL tempdu[4];
REAL tempdata[4];
REAL u1 = global_ev_u1;
REAL u2 = global_ev_u2;
if(u-MYDELTA*(u2-u1) < u1)
u = u+ MYDELTA*(u2-u1);
else
u = u-MYDELTA*(u2-u1);
inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, tempdu, dv);
}
if(myabs(du[0]) <= MYZERO && myabs(du[1]) <= MYZERO && myabs(du[2]) <= MYZERO)
{
REAL tempdv[4];
REAL tempdata[4];
REAL v1 = global_ev_v1;
REAL v2 = global_ev_v2;
if(v-MYDELTA*(v2-v1) < v1)
v = v+ MYDELTA*(v2-v1);
else
v = v-MYDELTA*(v2-v1);
inDoDomain2WithDerivs(global_ev_k, u,v,global_ev_u1, global_ev_u2, global_ev_uorder, global_ev_v1, global_ev_v2, global_ev_vorder, global_ev_ctlPoints, tempdata, du, tempdv);
}
#endif
/*compute normal*/
switch(global_ev_k){
case 3:
inComputeNormal2(du, dv, retNormal);
break;
case 4:
inComputeFirstPartials(retPoint, du, dv);
inComputeNormal2(du, dv, retNormal);
/*transform the homegeneous coordinate of retPoint into inhomogenous one*/
retPoint[0] /= retPoint[3];
retPoint[1] /= retPoint[3];
retPoint[2] /= retPoint[3];
break;
}
// glNormal3fv(retNormal);
// glVertex3fv(retPoint);
}
void OpenGLSurfaceEvaluator::inPreEvaluateBV(int k, int uorder, int vorder, REAL vprime, REAL *baseData)
{
int j,row,col;
REAL p, pdv;
REAL *data;
if(global_vprime != vprime || global_vorder != vorder) {
inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
global_vprime = vprime;
global_vorder = vorder;
}
for(j=0; j<k; j++){
data = baseData+j;
for(row=0; row<uorder; row++){
p = global_vcoeff[0] * (*data);
pdv = global_vcoeffDeriv[0] * (*data);
data += k;
for(col = 1; col < vorder; col++){
p += global_vcoeff[col] * (*data);
pdv += global_vcoeffDeriv[col] * (*data);
data += k;
}
global_BV[row][j] = p;
global_PBV[row][j] = pdv;
}
}
}
void OpenGLSurfaceEvaluator::inPreEvaluateBU(int k, int uorder, int vorder, REAL uprime, REAL *baseData)
{
int j,row,col;
REAL p, pdu;
REAL *data;
if(global_uprime != uprime || global_uorder != uorder) {
inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
global_uprime = uprime;
global_uorder = uorder;
}
for(j=0; j<k; j++){
data = baseData+j;
for(col=0; col<vorder; col++){
data = baseData+j + k*col;
p = global_ucoeff[0] * (*data);
pdu = global_ucoeffDeriv[0] * (*data);
data += k*uorder;
for(row = 1; row < uorder; row++){
p += global_ucoeff[row] * (*data);
pdu += global_ucoeffDeriv[row] * (*data);
data += k * uorder;
}
global_BU[col][j] = p;
global_PBU[col][j] = pdu;
}
}
}
void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsBU(int k, REAL u, REAL v,
REAL u1, REAL u2, int uorder,
REAL v1, REAL v2, int vorder,
REAL *baseData,
REAL *retPoint, REAL* retdu, REAL *retdv)
{
int j, col;
REAL vprime;
if((u2 == u1) || (v2 == v1))
return;
vprime = (v - v1) / (v2 - v1);
if(global_vprime != vprime || global_vorder != vorder) {
inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
global_vprime = vprime;
global_vorder = vorder;
}
for(j=0; j<k; j++)
{
retPoint[j] = retdu[j] = retdv[j] = 0.0;
for (col = 0; col < vorder; col++) {
retPoint[j] += global_BU[col][j] * global_vcoeff[col];
retdu[j] += global_PBU[col][j] * global_vcoeff[col];
retdv[j] += global_BU[col][j] * global_vcoeffDeriv[col];
}
}
}
void OpenGLSurfaceEvaluator::inDoDomain2WithDerivsBV(int k, REAL u, REAL v,
REAL u1, REAL u2, int uorder,
REAL v1, REAL v2, int vorder,
REAL *baseData,
REAL *retPoint, REAL* retdu, REAL *retdv)
{
int j, row;
REAL uprime;
if((u2 == u1) || (v2 == v1))
return;
uprime = (u - u1) / (u2 - u1);
if(global_uprime != uprime || global_uorder != uorder) {
inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
global_uprime = uprime;
global_uorder = uorder;
}
for(j=0; j<k; j++)
{
retPoint[j] = retdu[j] = retdv[j] = 0.0;
for (row = 0; row < uorder; row++) {
retPoint[j] += global_BV[row][j] * global_ucoeff[row];
retdu[j] += global_BV[row][j] * global_ucoeffDeriv[row];
retdv[j] += global_PBV[row][j] * global_ucoeff[row];
}
}
}
/*
*given a Bezier surface, and parameter (u,v), compute the point in the object space,
*and the normal
*k: the dimension of the object space: usually 2,3,or 4.
*u,v: the paramter pair.
*u1,u2,uorder: the Bezier polynomial of u coord is defined on [u1,u2] with order uorder.
*v1,v2,vorder: the Bezier polynomial of v coord is defined on [v1,v2] with order vorder.
*baseData: contrl points. arranged as: (u,v,k).
*retPoint: the computed point (one point) with dimension k.
*retdu: the computed partial derivative with respect to u.
*retdv: the computed partial derivative with respect to v.
*/
void OpenGLSurfaceEvaluator::inDoDomain2WithDerivs(int k, REAL u, REAL v,
REAL u1, REAL u2, int uorder,
REAL v1, REAL v2, int vorder,
REAL *baseData,
REAL *retPoint, REAL *retdu, REAL *retdv)
{
int j, row, col;
REAL uprime;
REAL vprime;
REAL p;
REAL pdv;
REAL *data;
if((u2 == u1) || (v2 == v1))
return;
uprime = (u - u1) / (u2 - u1);
vprime = (v - v1) / (v2 - v1);
/* Compute coefficients for values and derivs */
/* Use already cached values if possible */
if(global_uprime != uprime || global_uorder != uorder) {
inPreEvaluateWithDeriv(uorder, uprime, global_ucoeff, global_ucoeffDeriv);
global_uorder = uorder;
global_uprime = uprime;
}
if (global_vprime != vprime ||
global_vorder != vorder) {
inPreEvaluateWithDeriv(vorder, vprime, global_vcoeff, global_vcoeffDeriv);
global_vorder = vorder;
global_vprime = vprime;
}
for (j = 0; j < k; j++) {
data=baseData+j;
retPoint[j] = retdu[j] = retdv[j] = 0.0;
for (row = 0; row < uorder; 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 = global_vcoeff[0] * (*data);
pdv = global_vcoeffDeriv[0] * (*data);
data += k;
for (col = 1; col < vorder; col++) {
/* Incrementally build up p, pdv value */
p += global_vcoeff[col] * (*data);
pdv += global_vcoeffDeriv[col] * (*data);
data += k;
}
/* Use p, pdv value to incrementally add up r, du, dv */
retPoint[j] += global_ucoeff[row] * p;
retdu[j] += global_ucoeffDeriv[row] * p;
retdv[j] += global_ucoeff[row] * pdv;
}
}
}
/*
*compute the Bezier polynomials C[n,j](v) for all j at v with
*return values stored in coeff[], where
* C[n,j](v) = (n,j) * v^j * (1-v)^(n-j),
* j=0,1,2,...,n.
*order : n+1
*vprime: v
*coeff : coeff[j]=C[n,j](v), this array store the returned values.
*The algorithm is a recursive scheme:
* C[0,0]=1;
* C[n,j](v) = (1-v)*C[n-1,j](v) + v*C[n-1,j-1](v), n>=1
*This code is copied from opengl/soft/so_eval.c:PreEvaluate
*/
void OpenGLSurfaceEvaluator::inPreEvaluate(int order, REAL vprime, REAL *coeff)
{
int i, j;
REAL oldval, temp;
REAL 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.
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -