⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 insurfeval.cc

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 CC
📖 第 1 页 / 共 4 页
字号:
/*
** 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.
**
** $Date: 2006-03-11 18:07:02 -0600 (Sat, 11 Mar 2006) $ $Revision: 1.1 $
*/
/*
** $Header: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/glu32/libnurbs/interface/insurfeval.cc,v 1.1 2004/02/02 16:39:08 navaraf Exp $
*/

#include "gluos.h"
#include <stdlib.h>
#include <stdio.h>
#include <GL/gl.h>
#include <math.h>
#include <assert.h>

#include "glsurfeval.h"

//extern int surfcount;

//#define CRACK_TEST

#define AVOID_ZERO_NORMAL

#ifdef AVOID_ZERO_NORMAL
#define myabs(x)  ((x>0)? x: (-x))
#define MYZERO 0.000001
#define MYDELTA 0.001
#endif

//#define USE_LOD
#ifdef USE_LOD
//#define LOD_EVAL_COORD(u,v) inDoEvalCoord2EM(u,v)
#define LOD_EVAL_COORD(u,v) glEvalCoord2f(u,v)

static void LOD_interpolate(REAL A[2], REAL B[2], REAL C[2], int j, int k, int pow2_level,
			    REAL& u, REAL& v)
{
  REAL a,a1,b,b1;

  a = ((REAL) j) / ((REAL) pow2_level);
  a1 = 1-a;

  if(j != 0)
    {
      b = ((REAL) k) / ((REAL)j);
      b1 = 1-b;
    }
  REAL x,y,z;
  x = a1;
  if(j==0)
    {
      y=0; z=0;
    }
  else{
    y = b1*a;
    z = b *a;
  }

  u = x*A[0] + y*B[0] + z*C[0];
  v = x*A[1] + y*B[1] + z*C[1];
}

void OpenGLSurfaceEvaluator::LOD_triangle(REAL A[2], REAL B[2], REAL C[2], 
			 int level)     
{
  int k,j;
  int pow2_level;
  /*compute 2^level*/
  pow2_level = 1;

  for(j=0; j<level; j++)
    pow2_level *= 2;
  for(j=0; j<=pow2_level-1; j++)
    {
      REAL u,v;

/*      beginCallBack(GL_TRIANGLE_STRIP);*/
glBegin(GL_TRIANGLE_STRIP);
      LOD_interpolate(A,B,C, j+1, j+1, pow2_level, u,v);
#ifdef USE_LOD
      LOD_EVAL_COORD(u,v);
//      glEvalCoord2f(u,v);
#else
      inDoEvalCoord2EM(u,v);
#endif

      for(k=0; k<=j; k++)
	{
	  LOD_interpolate(A,B,C,j,j-k,pow2_level, u,v);
#ifdef USE_LOD
          LOD_EVAL_COORD(u,v);
//	  glEvalCoord2f(u,v);
#else
	  inDoEvalCoord2EM(u,v);
#endif

	  LOD_interpolate(A,B,C,j+1,j-k,pow2_level, u,v);

#ifdef USE_LOD
	  LOD_EVAL_COORD(u,v);
//	  glEvalCoord2f(u,v);
#else
	  inDoEvalCoord2EM(u,v);
#endif
	}
//      endCallBack();	
glEnd();
    }
}

void OpenGLSurfaceEvaluator::LOD_eval(int num_vert, REAL* verts, int type,
		     int level
		     )
{
  int i,k;
  switch(type){
  case GL_TRIANGLE_STRIP:
  case GL_QUAD_STRIP:
    for(i=2, k=4; i<=num_vert-2; i+=2, k+=4)
      {
	LOD_triangle(verts+k-4, verts+k-2, verts+k,
		     level
		     );
	LOD_triangle(verts+k-2, verts+k+2, verts+k,
		     level
		     );
      }
    if(num_vert % 2 ==1) 
      {
	LOD_triangle(verts+2*(num_vert-3), verts+2*(num_vert-2), verts+2*(num_vert-1),
		     level
		     );
      }
    break;      
  case GL_TRIANGLE_FAN:
    for(i=1, k=2; i<=num_vert-2; i++, k+=2)
      {
	LOD_triangle(verts,verts+k, verts+k+2,
		     level
		     );
      }
    break;
  
  default:
    fprintf(stderr, "typy not supported in LOD_\n");
  }
}
	

#endif //USE_LOD

//#define  GENERIC_TEST
#ifdef GENERIC_TEST
extern float xmin, xmax, ymin, ymax, zmin, zmax; /*bounding box*/
extern int temp_signal;

static void gTessVertexSphere(float u, float v, float temp_normal[3], float temp_vertex[3])
{
  float r=2.0;
  float Ox = 0.5*(xmin+xmax);
  float Oy = 0.5*(ymin+ymax);
  float Oz = 0.5*(zmin+zmax);
  float nx = cos(v) * sin(u);
  float ny = sin(v) * sin(u);
  float nz = cos(u);
  float x= Ox+r * nx;
  float y= Oy+r * ny;
  float z= Oz+r * nz;

  temp_normal[0] = nx;
  temp_normal[1] = ny;
  temp_normal[2] =  nz;
  temp_vertex[0] = x;
  temp_vertex[1] = y;
  temp_vertex[2] = z;

//  glNormal3f(nx,ny,nz);
//  glVertex3f(x,y,z);
}

static void gTessVertexCyl(float u, float v, float temp_normal[3], float temp_vertex[3])
{
   float r=2.0;
  float Ox = 0.5*(xmin+xmax);
  float Oy = 0.5*(ymin+ymax);
  float Oz = 0.5*(zmin+zmax);
  float nx = cos(v);
  float ny = sin(v);
  float nz = 0;
  float x= Ox+r * nx;
  float y= Oy+r * ny;
  float z= Oz - 2*u;

  temp_normal[0] = nx;
  temp_normal[1] = ny;
  temp_normal[2] =  nz;
  temp_vertex[0] = x;
  temp_vertex[1] = y;
  temp_vertex[2] = z;

/*  
  glNormal3f(nx,ny,nz);
  glVertex3f(x,y,z);
*/
}

#endif //GENERIC_TEST

void OpenGLSurfaceEvaluator::inBPMListEval(bezierPatchMesh* list)
{
  bezierPatchMesh* temp;
  for(temp = list; temp != NULL; temp = temp->next)
    {
      inBPMEval(temp);
    }
}

void OpenGLSurfaceEvaluator::inBPMEval(bezierPatchMesh* bpm)
{
  int i,j,k,l;
  float u,v;

  int ustride = bpm->bpatch->dimension * bpm->bpatch->vorder;
  int vstride = bpm->bpatch->dimension;
  inMap2f( 
	  (bpm->bpatch->dimension == 3)? GL_MAP2_VERTEX_3 : GL_MAP2_VERTEX_4,
	  bpm->bpatch->umin,
	  bpm->bpatch->umax,
	  ustride,
	  bpm->bpatch->uorder,
	  bpm->bpatch->vmin,
	  bpm->bpatch->vmax,
	  vstride,
	  bpm->bpatch->vorder,
	  bpm->bpatch->ctlpoints);
  
  bpm->vertex_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3+1); /*in case the origional dimenion is 4, then we need 4 space to pass to evaluator.*/
  assert(bpm->vertex_array);
  bpm->normal_array = (float*) malloc(sizeof(float)* (bpm->index_UVarray/2) * 3);
  assert(bpm->normal_array);
#ifdef CRACK_TEST
if(  global_ev_u1 ==2 &&   global_ev_u2 == 3
  && global_ev_v1 ==2 &&   global_ev_v2 == 3)
{
REAL vertex[4];
REAL normal[4];
#ifdef DEBUG
printf("***number 1\n");
#endif

beginCallBack(GL_QUAD_STRIP, NULL);
inEvalCoord2f(3.0, 3.0);
inEvalCoord2f(2.0, 3.0);
inEvalCoord2f(3.0, 2.7);
inEvalCoord2f(2.0, 2.7);
inEvalCoord2f(3.0, 2.0);
inEvalCoord2f(2.0, 2.0);
endCallBack(NULL);


beginCallBack(GL_TRIANGLE_STRIP, NULL);
inEvalCoord2f(2.0, 3.0);
inEvalCoord2f(2.0, 2.0);
inEvalCoord2f(2.0, 2.7);
endCallBack(NULL);

}

/*
if(  global_ev_u1 ==2 &&   global_ev_u2 == 3
  && global_ev_v1 ==1 &&   global_ev_v2 == 2)
{
#ifdef DEBUG
printf("***number 2\n");
#endif
beginCallBack(GL_QUAD_STRIP);
inEvalCoord2f(2.0, 2.0);
inEvalCoord2f(2.0, 1.0);
inEvalCoord2f(3.0, 2.0);
inEvalCoord2f(3.0, 1.0);
endCallBack();
}
*/
if(  global_ev_u1 ==1 &&   global_ev_u2 == 2
  && global_ev_v1 ==2 &&   global_ev_v2 == 3)
{
#ifdef DEBUG
printf("***number 3\n");
#endif
beginCallBack(GL_QUAD_STRIP, NULL);
inEvalCoord2f(2.0, 3.0);
inEvalCoord2f(1.0, 3.0);
inEvalCoord2f(2.0, 2.3);
inEvalCoord2f(1.0, 2.3);
inEvalCoord2f(2.0, 2.0);
inEvalCoord2f(1.0, 2.0);
endCallBack(NULL);

beginCallBack(GL_TRIANGLE_STRIP, NULL);
inEvalCoord2f(2.0, 2.3);
inEvalCoord2f(2.0, 2.0);
inEvalCoord2f(2.0, 3.0);
endCallBack(NULL);

}
return;
#endif

  k=0;
  l=0;

  for(i=0; i<bpm->index_length_array; i++)
    {
      beginCallBack(bpm->type_array[i], userData);
      for(j=0; j<bpm->length_array[i]; j++)
	{
	  u = bpm->UVarray[k];
	  v = bpm->UVarray[k+1];
	  inDoEvalCoord2NOGE(u,v,
			     bpm->vertex_array+l,
			     bpm->normal_array+l);

	  normalCallBack(bpm->normal_array+l, userData);
	  vertexCallBack(bpm->vertex_array+l, userData);

	  k += 2;
	  l += 3;
	}
      endCallBack(userData);
    }
}

void OpenGLSurfaceEvaluator::inEvalPoint2(int i, int j)
{
  REAL du, dv;
  REAL point[4];
  REAL normal[3];
  REAL u,v;
  du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
  dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;
  u = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
  v = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv);
  inDoEvalCoord2(u,v,point,normal);
}

void OpenGLSurfaceEvaluator::inEvalCoord2f(REAL u, REAL v)
{

  REAL point[4];
  REAL normal[3];
  inDoEvalCoord2(u,v,point, normal);
}



/*define a grid. store the values into the global variabls:
 * global_grid_*
 *These values will be used later by evaluating functions
 */
void OpenGLSurfaceEvaluator::inMapGrid2f(int nu, REAL u0, REAL u1,
		 int nv, REAL v0, REAL v1)
{
 global_grid_u0 = u0;
 global_grid_u1 = u1;
 global_grid_nu = nu;
 global_grid_v0 = v0;
 global_grid_v1 = v1;
 global_grid_nv = nv;
}

void OpenGLSurfaceEvaluator::inEvalMesh2(int lowU, int lowV, int highU, int highV)
{
  REAL du, dv;
  int i,j;
  REAL point[4];
  REAL normal[3];
  if(global_grid_nu == 0 || global_grid_nv == 0)
    return; /*no points need to be output*/
  du = (global_grid_u1 - global_grid_u0) / (REAL)global_grid_nu;
  dv = (global_grid_v1 - global_grid_v0) / (REAL)global_grid_nv;  
  
  if(global_grid_nu >= global_grid_nv){
    for(i=lowU; i<highU; i++){
      REAL u1 = (i==global_grid_nu)? global_grid_u1:(global_grid_u0 + i*du);
      REAL u2 = ((i+1) == global_grid_nu)? global_grid_u1: (global_grid_u0+(i+1)*du);
      
      bgnqstrip();
      for(j=highV; j>=lowV; j--){
	REAL v1 = (j == global_grid_nv)? global_grid_v1: (global_grid_v0 +j*dv);
	
	inDoEvalCoord2(u1, v1, point, normal);
	inDoEvalCoord2(u2, v1, point, normal);
      }
      endqstrip();
    }
  }
  
  else{
    for(i=lowV; i<highV; i++){
      REAL v1 = (i==global_grid_nv)? global_grid_v1:(global_grid_v0 + i*dv);
      REAL v2 = ((i+1) == global_grid_nv)? global_grid_v1: (global_grid_v0+(i+1)*dv);
      
      bgnqstrip();
      for(j=highU; j>=lowU; j--){
	REAL u1 = (j == global_grid_nu)? global_grid_u1: (global_grid_u0 +j*du);	
	inDoEvalCoord2(u1, v2, point, normal);
	inDoEvalCoord2(u1, v1, point, normal);
      }
      endqstrip();
    }
  }
    
}

void OpenGLSurfaceEvaluator::inMap2f(int k,
	     REAL ulower,
	     REAL uupper,
	     int ustride,
	     int uorder,
	     REAL vlower,
	     REAL vupper,
	     int vstride,
	     int vorder,
	     REAL *ctlPoints)
{
  int i,j,x;
  REAL *data = global_ev_ctlPoints;
  


  if(k == GL_MAP2_VERTEX_3) k=3;
  else if (k==GL_MAP2_VERTEX_4) k =4;
  else {
    printf("error in inMap2f, maptype=%i is wrong, k,map is not updated\n", k);
    return;
  }
  
  global_ev_k = k;
  global_ev_u1 = ulower;
  global_ev_u2 = uupper;
  global_ev_ustride = ustride;
  global_ev_uorder = uorder;
  global_ev_v1 = vlower;
  global_ev_v2 = vupper;
  global_ev_vstride = vstride;
  global_ev_vorder = vorder;

  /*copy the contrl points from ctlPoints to global_ev_ctlPoints*/
  for (i=0; i<uorder; i++) {
    for (j=0; j<vorder; j++) {
      for (x=0; x<k; x++) {
	data[x] = ctlPoints[x];
      }
      ctlPoints += vstride;
      data += k;
    }
    ctlPoints += ustride - vstride * vorder;
  }

}


/*
 *given a point p with homegeneous coordiante (x,y,z,w), 
 *let pu(x,y,z,w) be its partial derivative vector with
 *respect to u
 *and pv(x,y,z,w) be its partial derivative vector with repect to v.
 *This function returns the partial derivative vectors of the
 *inhomegensous coordinates, i.e., 
 * (x/w, y/w, z/w) with respect to u and v.
 */
void OpenGLSurfaceEvaluator::inComputeFirstPartials(REAL *p, REAL *pu, REAL *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];
}

/*compute the cross product of pu and pv and normalize.
 *the normal is returned in retNormal
 * pu: dimension 3
 * pv: dimension 3

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -