mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00

- Create a branch to do a proper merge of USB work from a trunk base instead of from cmake-bringup - In the future, DO NOT under any circumstances branch another branch. This leads to merge problems! svn path=/branches/usb-bringup-trunk/; revision=55018
1197 lines
28 KiB
C++
1197 lines
28 KiB
C++
/*
|
|
** 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.
|
|
*/
|
|
|
|
/*
|
|
* slicer.c++
|
|
*
|
|
* $Date$ $Revision: 1.1 $
|
|
* $Header: /cygdrive/c/RCVS/CVS/ReactOS/reactos/lib/glu32/libnurbs/internals/slicer.cc,v 1.1 2004/02/02 16:39:12 navaraf Exp $
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include "glimports.h"
|
|
#include "mystdio.h"
|
|
#include "myassert.h"
|
|
#include "bufpool.h"
|
|
#include "slicer.h"
|
|
#include "backend.h"
|
|
#include "arc.h"
|
|
#include "gridtrimvertex.h"
|
|
#include "simplemath.h"
|
|
#include "trimvertex.h"
|
|
#include "varray.h"
|
|
|
|
#include "polyUtil.h" //for area()
|
|
|
|
//static int count=0;
|
|
|
|
/*USE_OPTTT is initiated in trimvertex.h*/
|
|
|
|
#ifdef USE_OPTTT
|
|
#include <GL/gl.h>
|
|
#endif
|
|
|
|
//#define USE_READ_FLAG //whether to use new or old tesselator
|
|
//if defined, it reads "flagFile",
|
|
// if the number is 1, then use new tess
|
|
// otherwise, use the old tess.
|
|
//if not defined, then use new tess.
|
|
#ifdef USE_READ_FLAG
|
|
static Int read_flag(char* name);
|
|
Int newtess_flag = read_flag("flagFile");
|
|
#endif
|
|
|
|
//#define COUNT_TRIANGLES
|
|
#ifdef COUNT_TRIANGLES
|
|
Int num_triangles = 0;
|
|
Int num_quads = 0;
|
|
#endif
|
|
|
|
#define max(a,b) ((a>b)? a:b)
|
|
#define ZERO 0.00001 /*determing whether a loop is a rectngle or not*/
|
|
#define equalRect(a,b) ((glu_abs(a-b) <= ZERO)? 1:0) //only used in tessellating a rectangle
|
|
|
|
/******triangulate a monotone polygon**************/
|
|
#include "monoTriangulation.h"
|
|
|
|
inline int compInY(REAL a[2], REAL b[2])
|
|
{
|
|
if(a[1] < b[1])
|
|
return -1;
|
|
else if (a[1] > b[1])
|
|
return 1;
|
|
else if(a[0] > b[0])
|
|
return 1;
|
|
else return -1;
|
|
}
|
|
|
|
void monoTriangulationLoop(Arc_ptr loop, Backend& backend, primStream* pStream)
|
|
{
|
|
int i;
|
|
//find the top, bottom, increasing and decreasing chain
|
|
//then call monoTrianulation
|
|
Arc_ptr jarc, temp;
|
|
Arc_ptr top;
|
|
Arc_ptr bot;
|
|
top = bot = loop;
|
|
if(compInY(loop->tail(), loop->prev->tail()) < 0)
|
|
{
|
|
//first find bot
|
|
for(temp = loop->next; temp != loop; temp = temp->next)
|
|
{
|
|
if(compInY(temp->tail(), temp->prev->tail()) > 0)
|
|
break;
|
|
}
|
|
bot = temp->prev;
|
|
//then find top
|
|
for(temp=loop->prev; temp != loop; temp = temp->prev)
|
|
{
|
|
if(compInY(temp->tail(), temp->prev->tail()) > 0)
|
|
break;
|
|
}
|
|
top = temp;
|
|
}
|
|
else //loop > loop->prev
|
|
{
|
|
for(temp=loop->next; temp != loop; temp = temp->next)
|
|
{
|
|
if(compInY(temp->tail(), temp->prev->tail()) < 0)
|
|
break;
|
|
}
|
|
top = temp->prev;
|
|
for(temp=loop->prev; temp != loop; temp = temp->prev)
|
|
{
|
|
if(compInY(temp->tail(), temp->prev->tail()) < 0)
|
|
break;
|
|
}
|
|
bot = temp;
|
|
}
|
|
//creat increase and decrease chains
|
|
vertexArray inc_chain(50); //this is a dynamci array
|
|
for(i=1; i<=top->pwlArc->npts-2; i++)
|
|
{
|
|
//the first vertex is the top which doesn't below to inc_chain
|
|
inc_chain.appendVertex(top->pwlArc->pts[i].param);
|
|
}
|
|
for(jarc=top->next; jarc != bot; jarc = jarc->next)
|
|
{
|
|
for(i=0; i<=jarc->pwlArc->npts-2; i++)
|
|
{
|
|
inc_chain.appendVertex(jarc->pwlArc->pts[i].param);
|
|
}
|
|
|
|
}
|
|
vertexArray dec_chain(50);
|
|
for(jarc = top->prev; jarc != bot; jarc = jarc->prev)
|
|
{
|
|
for(i=jarc->pwlArc->npts-2; i>=0; i--)
|
|
{
|
|
dec_chain.appendVertex(jarc->pwlArc->pts[i].param);
|
|
}
|
|
}
|
|
for(i=bot->pwlArc->npts-2; i>=1; i--)
|
|
{
|
|
dec_chain.appendVertex(jarc->pwlArc->pts[i].param);
|
|
}
|
|
|
|
monoTriangulationRec(top->tail(), bot->tail(), &inc_chain, 0,
|
|
&dec_chain, 0, &backend);
|
|
|
|
}
|
|
|
|
/********tesselate a rectanlge (OPTIMIZATION**************/
|
|
static void triangulateRectGen(Arc_ptr loop, int n_ulines, int n_vlines, Backend& backend);
|
|
|
|
static Int is_rect(Arc_ptr loop)
|
|
{
|
|
Int nlines =1;
|
|
for(Arc_ptr jarc = loop->next; jarc != loop; jarc = jarc->next)
|
|
{
|
|
nlines++;
|
|
if(nlines == 5)
|
|
break;
|
|
}
|
|
if(nlines != 4)
|
|
return 0;
|
|
|
|
|
|
/*
|
|
printf("here1\n");
|
|
printf("loop->tail=(%f,%f)\n", loop->tail()[0], loop->tail()[1]);
|
|
printf("loop->head=(%f,%f)\n", loop->head()[0], loop->head()[1]);
|
|
printf("loop->next->tail=(%f,%f)\n", loop->next->tail()[0], loop->next->tail()[1]);
|
|
printf("loop->next->head=(%f,%f)\n", loop->next->head()[0], loop->next->head()[1]);
|
|
if(fglu_abs(loop->tail()[0] - loop->head()[0])<0.000001)
|
|
printf("equal 1\n");
|
|
if(loop->next->tail()[1] == loop->next->head()[1])
|
|
printf("equal 2\n");
|
|
*/
|
|
|
|
if( (glu_abs(loop->tail()[0] - loop->head()[0])<=ZERO) &&
|
|
(glu_abs(loop->next->tail()[1] - loop->next->head()[1])<=ZERO) &&
|
|
(glu_abs(loop->prev->tail()[1] - loop->prev->head()[1])<=ZERO) &&
|
|
(glu_abs(loop->prev->prev->tail()[0] - loop->prev->prev->head()[0])<=ZERO)
|
|
)
|
|
return 1;
|
|
else if
|
|
( (glu_abs(loop->tail()[1] - loop->head()[1]) <= ZERO) &&
|
|
(glu_abs(loop->next->tail()[0] - loop->next->head()[0]) <= ZERO) &&
|
|
(glu_abs(loop->prev->tail()[0] - loop->prev->head()[0]) <= ZERO) &&
|
|
(glu_abs(loop->prev->prev->tail()[1] - loop->prev->prev->head()[1]) <= ZERO)
|
|
)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
inline void OPT_OUTVERT(TrimVertex& vv, Backend& backend)
|
|
{
|
|
|
|
#ifdef USE_OPTTT
|
|
glNormal3fv(vv.cache_normal);
|
|
glVertex3fv(vv.cache_point);
|
|
#else
|
|
|
|
backend.tmeshvert(&vv);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
static void triangulateRectAux(PwlArc* top, PwlArc* bot, PwlArc* left, PwlArc* right, Backend& backend);
|
|
|
|
static void triangulateRect(Arc_ptr loop, Backend& backend, int TB_or_LR, int ulinear, int vlinear)
|
|
{
|
|
//we know the loop is a rectangle, but not sure which is top
|
|
Arc_ptr top, bot, left, right;
|
|
if(loop->tail()[1] == loop->head()[1])
|
|
{
|
|
if(loop->tail()[1] > loop->prev->prev->tail()[1])
|
|
{
|
|
|
|
top = loop;
|
|
}
|
|
else{
|
|
|
|
top = loop->prev->prev;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(loop->tail()[0] > loop->prev->prev->tail()[0])
|
|
{
|
|
//loop is the right arc
|
|
|
|
top = loop->next;
|
|
}
|
|
else
|
|
{
|
|
|
|
top = loop->prev;
|
|
}
|
|
}
|
|
left = top->next;
|
|
bot = left->next;
|
|
right= bot->next;
|
|
|
|
//if u, v are both nonlinear, then if the
|
|
//boundary is tessellated dense, we also
|
|
//sample the inside to get a better tesslletant.
|
|
if( (!ulinear) && (!vlinear))
|
|
{
|
|
int nu = top->pwlArc->npts;
|
|
if(nu < bot->pwlArc->npts)
|
|
nu = bot->pwlArc->npts;
|
|
int nv = left->pwlArc->npts;
|
|
if(nv < right->pwlArc->npts)
|
|
nv = right->pwlArc->npts;
|
|
/*
|
|
if(nu > 2 && nv > 2)
|
|
{
|
|
triangulateRectGen(top, nu-2, nv-2, backend);
|
|
return;
|
|
}
|
|
*/
|
|
}
|
|
|
|
if(TB_or_LR == 1)
|
|
triangulateRectAux(top->pwlArc, bot->pwlArc, left->pwlArc, right->pwlArc, backend);
|
|
else if(TB_or_LR == -1)
|
|
triangulateRectAux(left->pwlArc, right->pwlArc, bot->pwlArc, top->pwlArc, backend);
|
|
else
|
|
{
|
|
Int maxPointsTB = top->pwlArc->npts + bot->pwlArc->npts;
|
|
Int maxPointsLR = left->pwlArc->npts + right->pwlArc->npts;
|
|
|
|
if(maxPointsTB < maxPointsLR)
|
|
triangulateRectAux(left->pwlArc, right->pwlArc, bot->pwlArc, top->pwlArc, backend);
|
|
else
|
|
triangulateRectAux(top->pwlArc, bot->pwlArc, left->pwlArc, right->pwlArc, backend);
|
|
}
|
|
}
|
|
|
|
static void triangulateRectAux(PwlArc* top, PwlArc* bot, PwlArc* left, PwlArc* right, Backend& backend)
|
|
{ //if(maxPointsTB >= maxPointsLR)
|
|
{
|
|
|
|
Int d, topd_left, topd_right, botd_left, botd_right, i,j;
|
|
d = left->npts /2;
|
|
|
|
#ifdef USE_OPTTT
|
|
evalLineNOGE(top->pts, top->npts, backend);
|
|
evalLineNOGE(bot->pts, bot->npts, backend);
|
|
evalLineNOGE(left->pts, left->npts, backend);
|
|
evalLineNOGE(right->pts, right->npts, backend);
|
|
#endif
|
|
|
|
if(top->npts == 2) {
|
|
backend.bgntfan();
|
|
OPT_OUTVERT(top->pts[0], backend);//the root
|
|
for(i=0; i<left->npts; i++){
|
|
OPT_OUTVERT(left->pts[i], backend);
|
|
}
|
|
for(i=1; i<= bot->npts-2; i++){
|
|
OPT_OUTVERT(bot->pts[i], backend);
|
|
}
|
|
backend.endtfan();
|
|
|
|
backend.bgntfan();
|
|
OPT_OUTVERT(bot->pts[bot->npts-2], backend);
|
|
for(i=0; i<right->npts; i++){
|
|
OPT_OUTVERT(right->pts[i], backend);
|
|
}
|
|
backend.endtfan();
|
|
}
|
|
else if(bot->npts == 2) {
|
|
backend.bgntfan();
|
|
OPT_OUTVERT(bot->pts[0], backend);//the root
|
|
for(i=0; i<right->npts; i++){
|
|
OPT_OUTVERT(right->pts[i], backend);
|
|
}
|
|
for(i=1; i<= top->npts-2; i++){
|
|
OPT_OUTVERT(top->pts[i], backend);
|
|
}
|
|
backend.endtfan();
|
|
|
|
backend.bgntfan();
|
|
OPT_OUTVERT(top->pts[top->npts-2], backend);
|
|
for(i=0; i<left->npts; i++){
|
|
OPT_OUTVERT(left->pts[i], backend);
|
|
}
|
|
backend.endtfan();
|
|
}
|
|
else { //both top and bot have >=3 points
|
|
|
|
backend.bgntfan();
|
|
|
|
OPT_OUTVERT(top->pts[top->npts-2], backend);
|
|
|
|
for(i=0; i<=d; i++)
|
|
{
|
|
OPT_OUTVERT(left->pts[i], backend);
|
|
}
|
|
backend.endtfan();
|
|
|
|
backend.bgntfan();
|
|
|
|
OPT_OUTVERT(bot->pts[1], backend);
|
|
|
|
OPT_OUTVERT(top->pts[top->npts-2], backend);
|
|
|
|
for(i=d; i< left->npts; i++)
|
|
{
|
|
OPT_OUTVERT(left->pts[i], backend);
|
|
}
|
|
backend.endtfan();
|
|
|
|
d = right->npts/2;
|
|
//output only when d<right->npts-1 and
|
|
//
|
|
if(d<right->npts-1)
|
|
{
|
|
backend.bgntfan();
|
|
// backend.tmeshvert(& top->pts[1]);
|
|
OPT_OUTVERT(top->pts[1], backend);
|
|
for(i=d; i< right->npts; i++)
|
|
{
|
|
// backend.tmeshvert(& right->pts[i]);
|
|
|
|
OPT_OUTVERT(right->pts[i], backend);
|
|
|
|
}
|
|
backend.endtfan();
|
|
}
|
|
|
|
backend.bgntfan();
|
|
// backend.tmeshvert(& bot->pts[bot->npts-2]);
|
|
OPT_OUTVERT( bot->pts[bot->npts-2], backend);
|
|
for(i=0; i<=d; i++)
|
|
{
|
|
// backend.tmeshvert(& right->pts[i]);
|
|
OPT_OUTVERT(right->pts[i], backend);
|
|
|
|
}
|
|
|
|
// backend.tmeshvert(& top->pts[1]);
|
|
OPT_OUTVERT(top->pts[1], backend);
|
|
|
|
backend.endtfan();
|
|
|
|
|
|
topd_left = top->npts-2;
|
|
topd_right = 1; //topd_left>= topd_right
|
|
|
|
botd_left = 1;
|
|
botd_right = bot->npts-2; //botd_left<= bot_dright
|
|
|
|
|
|
if(top->npts < bot->npts)
|
|
{
|
|
int delta=bot->npts - top->npts;
|
|
int u = delta/2;
|
|
botd_left = 1+ u;
|
|
botd_right = bot->npts-2-( delta-u);
|
|
|
|
if(botd_left >1)
|
|
{
|
|
backend.bgntfan();
|
|
// backend.tmeshvert(& top->pts[top->npts-2]);
|
|
OPT_OUTVERT(top->pts[top->npts-2], backend);
|
|
for(i=1; i<= botd_left; i++)
|
|
{
|
|
// backend.tmeshvert(& bot->pts[i]);
|
|
OPT_OUTVERT(bot->pts[i] , backend);
|
|
}
|
|
backend.endtfan();
|
|
}
|
|
if(botd_right < bot->npts-2)
|
|
{
|
|
backend.bgntfan();
|
|
OPT_OUTVERT(top->pts[1], backend);
|
|
for(i=botd_right; i<= bot->npts-2; i++)
|
|
OPT_OUTVERT(bot->pts[i], backend);
|
|
backend.endtfan();
|
|
}
|
|
}
|
|
else if(top->npts> bot->npts)
|
|
{
|
|
int delta=top->npts-bot->npts;
|
|
int u = delta/2;
|
|
topd_left = top->npts-2 - u;
|
|
topd_right = 1+delta-u;
|
|
|
|
if(topd_left < top->npts-2)
|
|
{
|
|
backend.bgntfan();
|
|
// backend.tmeshvert(& bot->pts[1]);
|
|
OPT_OUTVERT(bot->pts[1], backend);
|
|
for(i=topd_left; i<= top->npts-2; i++)
|
|
{
|
|
// backend.tmeshvert(& top->pts[i]);
|
|
OPT_OUTVERT(top->pts[i], backend);
|
|
}
|
|
backend.endtfan();
|
|
}
|
|
if(topd_right > 1)
|
|
{
|
|
backend.bgntfan();
|
|
OPT_OUTVERT(bot->pts[bot->npts-2], backend);
|
|
for(i=1; i<= topd_right; i++)
|
|
OPT_OUTVERT(top->pts[i], backend);
|
|
backend.endtfan();
|
|
}
|
|
}
|
|
|
|
if(topd_left <= topd_right)
|
|
return;
|
|
|
|
backend.bgnqstrip();
|
|
for(j=botd_left, i=topd_left; i>=topd_right; i--,j++)
|
|
{
|
|
// backend.tmeshvert(& top->pts[i]);
|
|
// backend.tmeshvert(& bot->pts[j]);
|
|
OPT_OUTVERT(top->pts[i], backend);
|
|
OPT_OUTVERT(bot->pts[j], backend);
|
|
}
|
|
backend.endqstrip();
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void triangulateRectCenter(int n_ulines, REAL* u_val,
|
|
int n_vlines, REAL* v_val,
|
|
Backend& backend)
|
|
{
|
|
|
|
// XXX this code was patched by Diego Santa Cruz <Diego.SantaCruz@epfl.ch>
|
|
// to fix a problem in which glMapGrid2f() was called with bad parameters.
|
|
// This has beens submitted to SGI but not integrated as of May 1, 2001.
|
|
if(n_ulines>1 && n_vlines>1) {
|
|
backend.surfgrid(u_val[0], u_val[n_ulines-1], n_ulines-1,
|
|
v_val[n_vlines-1], v_val[0], n_vlines-1);
|
|
backend.surfmesh(0,0,n_ulines-1,n_vlines-1);
|
|
}
|
|
|
|
return;
|
|
|
|
/*
|
|
for(i=0; i<n_vlines-1; i++)
|
|
{
|
|
|
|
backend.bgnqstrip();
|
|
for(j=0; j<n_ulines; j++)
|
|
{
|
|
trimVert.param[0] = u_val[j];
|
|
trimVert.param[1] = v_val[i+1];
|
|
backend.tmeshvert(& trimVert);
|
|
|
|
trimVert.param[1] = v_val[i];
|
|
backend.tmeshvert(& trimVert);
|
|
}
|
|
backend.endqstrip();
|
|
|
|
}
|
|
*/
|
|
}
|
|
|
|
//it works for top, bot, left ad right, you need ot select correct arguments
|
|
static void triangulateRectTopGen(Arc_ptr arc, int n_ulines, REAL* u_val, Real v, int dir, int is_u, Backend& backend)
|
|
{
|
|
|
|
if(is_u)
|
|
{
|
|
int i,k;
|
|
REAL* upper_val = (REAL*) malloc(sizeof(REAL) * arc->pwlArc->npts);
|
|
assert(upper_val);
|
|
if(dir)
|
|
{
|
|
for(k=0,i=arc->pwlArc->npts-1; i>=0; i--,k++)
|
|
{
|
|
upper_val[k] = arc->pwlArc->pts[i].param[0];
|
|
}
|
|
backend.evalUStrip(arc->pwlArc->npts, arc->pwlArc->pts[0].param[1],
|
|
upper_val,
|
|
n_ulines, v, u_val);
|
|
}
|
|
else
|
|
{
|
|
for(k=0,i=0; i<arc->pwlArc->npts; i++,k++)
|
|
{
|
|
upper_val[k] = arc->pwlArc->pts[i].param[0];
|
|
|
|
}
|
|
|
|
backend.evalUStrip(
|
|
n_ulines, v, u_val,
|
|
arc->pwlArc->npts, arc->pwlArc->pts[0].param[1], upper_val
|
|
);
|
|
}
|
|
|
|
free(upper_val);
|
|
return;
|
|
}
|
|
else //is_v
|
|
{
|
|
int i,k;
|
|
REAL* left_val = (REAL*) malloc(sizeof(REAL) * arc->pwlArc->npts);
|
|
assert(left_val);
|
|
if(dir)
|
|
{
|
|
for(k=0,i=arc->pwlArc->npts-1; i>=0; i--,k++)
|
|
{
|
|
left_val[k] = arc->pwlArc->pts[i].param[1];
|
|
}
|
|
backend.evalVStrip(arc->pwlArc->npts, arc->pwlArc->pts[0].param[0],
|
|
left_val,
|
|
n_ulines, v, u_val);
|
|
}
|
|
else
|
|
{
|
|
for(k=0,i=0; i<arc->pwlArc->npts; i++,k++)
|
|
{
|
|
left_val[k] = arc->pwlArc->pts[i].param[1];
|
|
}
|
|
backend.evalVStrip(
|
|
n_ulines, v, u_val,
|
|
arc->pwlArc->npts, arc->pwlArc->pts[0].param[0], left_val
|
|
);
|
|
}
|
|
free(left_val);
|
|
return;
|
|
}
|
|
|
|
//the following is a different version of the above code. If you comment
|
|
//the above code, the following code will still work. The reason to leave
|
|
//the folliwng code here is purely for testing purpose.
|
|
/*
|
|
int i,j;
|
|
PwlArc* parc = arc->pwlArc;
|
|
int d1 = parc->npts-1;
|
|
int d2 = 0;
|
|
TrimVertex trimVert;
|
|
trimVert.nuid = 0;//????
|
|
REAL* temp_u_val = u_val;
|
|
if(dir ==0) //have to reverse u_val
|
|
{
|
|
temp_u_val = (REAL*) malloc(sizeof(REAL) * n_ulines);
|
|
assert(temp_u_val);
|
|
for(i=0; i<n_ulines; i++)
|
|
temp_u_val[i] = u_val[n_ulines-1-i];
|
|
}
|
|
u_val = temp_u_val;
|
|
|
|
if(parc->npts > n_ulines)
|
|
{
|
|
d1 = n_ulines-1;
|
|
|
|
backend.bgntfan();
|
|
if(is_u){
|
|
trimVert.param[0] = u_val[0];
|
|
trimVert.param[1] = v;
|
|
}
|
|
else
|
|
{
|
|
trimVert.param[1] = u_val[0];
|
|
trimVert.param[0] = v;
|
|
}
|
|
|
|
backend.tmeshvert(& trimVert);
|
|
for(i=d1; i< parc->npts; i++)
|
|
backend.tmeshvert(& parc->pts[i]);
|
|
backend.endtfan();
|
|
|
|
|
|
}
|
|
else if(parc->npts < n_ulines)
|
|
{
|
|
d2 = n_ulines-parc->npts;
|
|
|
|
|
|
backend.bgntfan();
|
|
backend.tmeshvert(& parc->pts[parc->npts-1]);
|
|
for(i=0; i<= d2; i++)
|
|
{
|
|
if(is_u){
|
|
trimVert.param[0] = u_val[i];
|
|
trimVert.param[1] = v;
|
|
}
|
|
else
|
|
{
|
|
trimVert.param[1] = u_val[i];
|
|
trimVert.param[0] = v;
|
|
}
|
|
backend.tmeshvert(&trimVert);
|
|
}
|
|
backend.endtfan();
|
|
|
|
}
|
|
if(d1>0){
|
|
|
|
|
|
backend.bgnqstrip();
|
|
for(i=d1, j=d2; i>=0; i--, j++)
|
|
{
|
|
backend.tmeshvert(& parc->pts[i]);
|
|
|
|
if(is_u){
|
|
trimVert.param[0] = u_val[j];
|
|
trimVert.param[1] = v;
|
|
}
|
|
else{
|
|
trimVert.param[1] = u_val[j];
|
|
trimVert.param[0] = v;
|
|
}
|
|
backend.tmeshvert(&trimVert);
|
|
|
|
|
|
|
|
}
|
|
backend.endqstrip();
|
|
|
|
|
|
}
|
|
if(dir == 0) //temp_u_val was mallocated
|
|
free(temp_u_val);
|
|
*/
|
|
}
|
|
|
|
//n_ulines is the number of ulines inside, and n_vlines is the number of vlines
|
|
//inside, different from meanings elsewhere!!!
|
|
static void triangulateRectGen(Arc_ptr loop, int n_ulines, int n_vlines, Backend& backend)
|
|
{
|
|
|
|
int i;
|
|
//we know the loop is a rectangle, but not sure which is top
|
|
Arc_ptr top, bot, left, right;
|
|
|
|
if(equalRect(loop->tail()[1] , loop->head()[1]))
|
|
{
|
|
|
|
if(loop->tail()[1] > loop->prev->prev->tail()[1])
|
|
{
|
|
|
|
top = loop;
|
|
}
|
|
else{
|
|
|
|
top = loop->prev->prev;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(loop->tail()[0] > loop->prev->prev->tail()[0])
|
|
{
|
|
//loop is the right arc
|
|
|
|
top = loop->next;
|
|
}
|
|
else
|
|
{
|
|
|
|
top = loop->prev;
|
|
}
|
|
}
|
|
|
|
left = top->next;
|
|
bot = left->next;
|
|
right= bot->next;
|
|
|
|
#ifdef COUNT_TRIANGLES
|
|
num_triangles += loop->pwlArc->npts +
|
|
left->pwlArc->npts +
|
|
bot->pwlArc->npts +
|
|
right->pwlArc->npts
|
|
+ 2*n_ulines + 2*n_vlines
|
|
-8;
|
|
num_quads += (n_ulines-1)*(n_vlines-1);
|
|
#endif
|
|
/*
|
|
backend.surfgrid(left->tail()[0], right->tail()[0], n_ulines+1,
|
|
top->tail()[1], bot->tail()[1], n_vlines+1);
|
|
// if(n_ulines>1 && n_vlines>1)
|
|
backend.surfmesh(0,0,n_ulines+1,n_vlines+1);
|
|
return;
|
|
*/
|
|
REAL* u_val=(REAL*) malloc(sizeof(REAL)*n_ulines);
|
|
assert(u_val);
|
|
REAL* v_val=(REAL*)malloc(sizeof(REAL) * n_vlines);
|
|
assert(v_val);
|
|
REAL u_stepsize = (right->tail()[0] - left->tail()[0])/( (REAL) n_ulines+1);
|
|
REAL v_stepsize = (top->tail()[1] - bot->tail()[1])/( (REAL) n_vlines+1);
|
|
Real temp=left->tail()[0]+u_stepsize;
|
|
for(i=0; i<n_ulines; i++)
|
|
{
|
|
u_val[i] = temp;
|
|
temp += u_stepsize;
|
|
}
|
|
temp = bot->tail()[1] + v_stepsize;
|
|
for(i=0; i<n_vlines; i++)
|
|
{
|
|
v_val[i] = temp;
|
|
temp += v_stepsize;
|
|
}
|
|
|
|
triangulateRectTopGen(top, n_ulines, u_val, v_val[n_vlines-1], 1,1, backend);
|
|
triangulateRectTopGen(bot, n_ulines, u_val, v_val[0], 0, 1, backend);
|
|
triangulateRectTopGen(left, n_vlines, v_val, u_val[0], 1, 0, backend);
|
|
triangulateRectTopGen(right, n_vlines, v_val, u_val[n_ulines-1], 0,0, backend);
|
|
|
|
|
|
|
|
|
|
//triangulate the center
|
|
triangulateRectCenter(n_ulines, u_val, n_vlines, v_val, backend);
|
|
|
|
free(u_val);
|
|
free(v_val);
|
|
|
|
}
|
|
|
|
/***********nextgen tess****************/
|
|
#include "sampleMonoPoly.h"
|
|
directedLine* arcToDLine(Arc_ptr arc)
|
|
{
|
|
int i;
|
|
Real vert[2];
|
|
directedLine* ret;
|
|
sampledLine* sline = new sampledLine(arc->pwlArc->npts);
|
|
for(i=0; i<arc->pwlArc->npts; i++)
|
|
{
|
|
vert[0] = arc->pwlArc->pts[i].param[0];
|
|
vert[1] = arc->pwlArc->pts[i].param[1];
|
|
sline->setPoint(i, vert);
|
|
}
|
|
ret = new directedLine(INCREASING, sline);
|
|
return ret;
|
|
}
|
|
|
|
/*an pwlArc may not be a straight line*/
|
|
directedLine* arcToMultDLines(directedLine* original, Arc_ptr arc)
|
|
{
|
|
directedLine* ret = original;
|
|
int is_linear = 0;
|
|
if(arc->pwlArc->npts == 2 )
|
|
is_linear = 1;
|
|
else if(area(arc->pwlArc->pts[0].param, arc->pwlArc->pts[1].param, arc->pwlArc->pts[arc->pwlArc->npts-1].param) == 0.0)
|
|
is_linear = 1;
|
|
|
|
if(is_linear)
|
|
{
|
|
directedLine *dline = arcToDLine(arc);
|
|
if(ret == NULL)
|
|
ret = dline;
|
|
else
|
|
ret->insert(dline);
|
|
return ret;
|
|
}
|
|
else /*not linear*/
|
|
{
|
|
for(Int i=0; i<arc->pwlArc->npts-1; i++)
|
|
{
|
|
Real vert[2][2];
|
|
vert[0][0] = arc->pwlArc->pts[i].param[0];
|
|
vert[0][1] = arc->pwlArc->pts[i].param[1];
|
|
vert[1][0] = arc->pwlArc->pts[i+1].param[0];
|
|
vert[1][1] = arc->pwlArc->pts[i+1].param[1];
|
|
|
|
sampledLine *sline = new sampledLine(2, vert);
|
|
directedLine *dline = new directedLine(INCREASING, sline);
|
|
if(ret == NULL)
|
|
ret = dline;
|
|
else
|
|
ret->insert(dline);
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
directedLine* arcLoopToDLineLoop(Arc_ptr loop)
|
|
{
|
|
directedLine* ret;
|
|
|
|
if(loop == NULL)
|
|
return NULL;
|
|
ret = arcToMultDLines(NULL, loop);
|
|
//ret->printSingle();
|
|
for(Arc_ptr temp = loop->next; temp != loop; temp = temp->next){
|
|
ret = arcToMultDLines(ret, temp);
|
|
//ret->printSingle();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
void Slicer::evalRBArray(rectBlockArray* rbArray, gridWrap* grid)
|
|
{
|
|
TrimVertex *trimVert = (TrimVertex*)malloc(sizeof(TrimVertex));
|
|
trimVert -> nuid = 0;//????
|
|
|
|
Real* u_values = grid->get_u_values();
|
|
Real* v_values = grid->get_v_values();
|
|
|
|
Int i,j,k,l;
|
|
|
|
for(l=0; l<rbArray->get_n_elements(); l++)
|
|
{
|
|
rectBlock* block = rbArray->get_element(l);
|
|
for(k=0, i=block->get_upGridLineIndex(); i>block->get_lowGridLineIndex(); i--, k++)
|
|
{
|
|
|
|
backend.bgnqstrip();
|
|
for(j=block->get_leftIndices()[k+1]; j<= block->get_rightIndices()[k+1]; j++)
|
|
{
|
|
trimVert->param[0] = u_values[j];
|
|
trimVert->param[1] = v_values[i];
|
|
backend.tmeshvert(trimVert);
|
|
|
|
trimVert->param[1] = v_values[i-1];
|
|
backend.tmeshvert(trimVert);
|
|
|
|
}
|
|
backend.endqstrip();
|
|
|
|
}
|
|
}
|
|
|
|
free(trimVert);
|
|
}
|
|
*/
|
|
|
|
void Slicer::evalRBArray(rectBlockArray* rbArray, gridWrap* grid)
|
|
{
|
|
Int i,j,k;
|
|
|
|
Int n_vlines=grid->get_n_vlines();
|
|
//the reason to switch the position of v_max and v_min is because of the
|
|
//the orientation problem. glEvalMesh generates quad_strip clockwise, but
|
|
//we need counter-clockwise.
|
|
backend.surfgrid(grid->get_u_min(), grid->get_u_max(), grid->get_n_ulines()-1,
|
|
grid->get_v_max(), grid->get_v_min(), n_vlines-1);
|
|
|
|
|
|
for(j=0; j<rbArray->get_n_elements(); j++)
|
|
{
|
|
rectBlock* block = rbArray->get_element(j);
|
|
Int low = block->get_lowGridLineIndex();
|
|
Int high = block->get_upGridLineIndex();
|
|
|
|
for(k=0, i=high; i>low; i--, k++)
|
|
{
|
|
backend.surfmesh(block->get_leftIndices()[k+1], n_vlines-1-i, block->get_rightIndices()[k+1]-block->get_leftIndices()[k+1], 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Slicer::evalStream(primStream* pStream)
|
|
{
|
|
Int i,j,k;
|
|
k=0;
|
|
/* TrimVertex X;*/
|
|
TrimVertex *trimVert =/*&X*/ (TrimVertex*)malloc(sizeof(TrimVertex));
|
|
trimVert -> nuid = 0;//???
|
|
Real* vertices = pStream->get_vertices(); //for efficiency
|
|
for(i=0; i<pStream->get_n_prims(); i++)
|
|
{
|
|
|
|
//ith primitive has #vertices = lengths[i], type=types[i]
|
|
switch(pStream->get_type(i)){
|
|
case PRIMITIVE_STREAM_FAN:
|
|
|
|
backend.bgntfan();
|
|
|
|
for(j=0; j<pStream->get_length(i); j++)
|
|
{
|
|
trimVert->param[0] = vertices[k];
|
|
trimVert->param[1] = vertices[k+1];
|
|
backend.tmeshvert(trimVert);
|
|
|
|
// backend.tmeshvert(vertices[k], vertices[k+1]);
|
|
k += 2;
|
|
}
|
|
backend.endtfan();
|
|
break;
|
|
|
|
default:
|
|
fprintf(stderr, "evalStream: not implemented yet\n");
|
|
exit(1);
|
|
|
|
}
|
|
}
|
|
free(trimVert);
|
|
}
|
|
|
|
|
|
|
|
|
|
void Slicer::slice_new(Arc_ptr loop)
|
|
{
|
|
//count++;
|
|
//if(count == 78) count=1;
|
|
//printf("count=%i\n", count);
|
|
//if( ! (4<= count && count <=4)) return;
|
|
|
|
|
|
Int num_ulines;
|
|
Int num_vlines;
|
|
Real uMin, uMax, vMin, vMax;
|
|
Real mydu, mydv;
|
|
uMin = uMax = loop->tail()[0];
|
|
vMin = vMax = loop->tail()[1];
|
|
mydu = (du>0)? du: -du;
|
|
mydv = (dv>0)? dv: -dv;
|
|
|
|
for(Arc_ptr jarc=loop->next; jarc != loop; jarc = jarc->next)
|
|
{
|
|
|
|
if(jarc->tail()[0] < uMin)
|
|
uMin = jarc->tail()[0];
|
|
if(jarc->tail()[0] > uMax)
|
|
uMax = jarc->tail()[0];
|
|
if(jarc->tail()[1] < vMin)
|
|
vMin = jarc->tail()[1];
|
|
if(jarc->tail()[1] > vMax)
|
|
vMax = jarc->tail()[1];
|
|
}
|
|
|
|
if (uMax == uMin)
|
|
return; // prevent divide-by-zero. Jon Perry. 17 June 2002
|
|
|
|
if(mydu > uMax - uMin)
|
|
num_ulines = 2;
|
|
else
|
|
{
|
|
num_ulines = 3 + (Int) ((uMax-uMin)/mydu);
|
|
}
|
|
if(mydv>=vMax-vMin)
|
|
num_vlines = 2;
|
|
else
|
|
{
|
|
num_vlines = 2+(Int)((vMax-vMin)/mydv);
|
|
}
|
|
|
|
Int isRect = is_rect(loop);
|
|
|
|
if(isRect && (num_ulines<=2 || num_vlines<=2))
|
|
{
|
|
if(vlinear)
|
|
triangulateRect(loop, backend, 1, ulinear, vlinear);
|
|
else if(ulinear)
|
|
triangulateRect(loop, backend, -1, ulinear, vlinear);
|
|
else
|
|
triangulateRect(loop, backend, 0, ulinear, vlinear);
|
|
}
|
|
|
|
else if(isRect)
|
|
{
|
|
triangulateRectGen(loop, num_ulines-2, num_vlines-2, backend);
|
|
}
|
|
else if( (num_ulines<=2 || num_vlines <=2) && ulinear)
|
|
{
|
|
monoTriangulationFunBackend(loop, compV2InY, &backend);
|
|
}
|
|
else if( (!ulinear) && (!vlinear) && (num_ulines == 2) && (num_vlines > 2))
|
|
{
|
|
monoTriangulationFunBackend(loop, compV2InY, &backend);
|
|
}
|
|
else
|
|
{
|
|
directedLine* poly = arcLoopToDLineLoop(loop);
|
|
|
|
gridWrap grid(num_ulines, num_vlines, uMin, uMax, vMin, vMax);
|
|
primStream pStream(20, 20);
|
|
rectBlockArray rbArray(20);
|
|
|
|
sampleMonoPoly(poly, &grid, ulinear, vlinear, &pStream, &rbArray);
|
|
|
|
evalStream(&pStream);
|
|
|
|
evalRBArray(&rbArray, &grid);
|
|
|
|
#ifdef COUNT_TRIANGLES
|
|
num_triangles += pStream.num_triangles();
|
|
num_quads += rbArray.num_quads();
|
|
#endif
|
|
poly->deleteSinglePolygonWithSline();
|
|
}
|
|
|
|
#ifdef COUNT_TRIANGLES
|
|
printf("num_triangles=%i\n", num_triangles);
|
|
printf("num_quads = %i\n", num_quads);
|
|
#endif
|
|
}
|
|
|
|
void Slicer::slice(Arc_ptr loop)
|
|
{
|
|
#ifdef USE_READ_FLAG
|
|
if(read_flag("flagFile"))
|
|
slice_new(loop);
|
|
else
|
|
slice_old(loop);
|
|
|
|
#else
|
|
slice_new(loop);
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
Slicer::Slicer( Backend &b )
|
|
: CoveAndTiler( b ), Mesher( b ), backend( b )
|
|
{
|
|
ulinear = 0;
|
|
vlinear = 0;
|
|
}
|
|
|
|
Slicer::~Slicer()
|
|
{
|
|
}
|
|
|
|
void
|
|
Slicer::setisolines( int x )
|
|
{
|
|
isolines = x;
|
|
}
|
|
|
|
void
|
|
Slicer::setstriptessellation( REAL x, REAL y )
|
|
{
|
|
assert(x > 0 && y > 0);
|
|
du = x;
|
|
dv = y;
|
|
setDu( du );
|
|
}
|
|
|
|
void
|
|
Slicer::slice_old( Arc_ptr loop )
|
|
{
|
|
loop->markverts();
|
|
|
|
Arc_ptr extrema[4];
|
|
loop->getextrema( extrema );
|
|
|
|
unsigned int npts = loop->numpts();
|
|
TrimRegion::init( npts, extrema[0] );
|
|
|
|
Mesher::init( npts );
|
|
|
|
long ulines = uarray.init( du, extrema[1], extrema[3] );
|
|
//printf("ulines = %i\n", ulines);
|
|
Varray varray;
|
|
long vlines = varray.init( dv, extrema[0], extrema[2] );
|
|
//printf("vlines = %i\n", vlines);
|
|
long botv = 0;
|
|
long topv;
|
|
TrimRegion::init( varray.varray[botv] );
|
|
getGridExtent( &extrema[0]->pwlArc->pts[0], &extrema[0]->pwlArc->pts[0] );
|
|
|
|
for( long quad=0; quad<varray.numquads; quad++ ) {
|
|
backend.surfgrid( uarray.uarray[0],
|
|
uarray.uarray[ulines-1],
|
|
ulines-1,
|
|
varray.vval[quad],
|
|
varray.vval[quad+1],
|
|
varray.voffset[quad+1] - varray.voffset[quad] );
|
|
|
|
for( long i=varray.voffset[quad]+1; i <= varray.voffset[quad+1]; i++ ) {
|
|
topv = botv++;
|
|
advance( topv - varray.voffset[quad],
|
|
botv - varray.voffset[quad],
|
|
varray.varray[botv] );
|
|
if( i == vlines )
|
|
getPts( extrema[2] );
|
|
else
|
|
getPts( backend );
|
|
getGridExtent();
|
|
if( isolines ) {
|
|
outline();
|
|
} else {
|
|
if( canTile() )
|
|
coveAndTile();
|
|
else
|
|
mesh();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
Slicer::outline( void )
|
|
{
|
|
GridTrimVertex upper, lower;
|
|
Hull::init( );
|
|
|
|
backend.bgnoutline();
|
|
while( (nextupper( &upper )) ) {
|
|
if( upper.isGridVert() )
|
|
backend.linevert( upper.g );
|
|
else
|
|
backend.linevert( upper.t );
|
|
}
|
|
backend.endoutline();
|
|
|
|
backend.bgnoutline();
|
|
while( (nextlower( &lower )) ) {
|
|
if( lower.isGridVert() )
|
|
backend.linevert( lower.g );
|
|
else
|
|
backend.linevert( lower.t );
|
|
}
|
|
backend.endoutline();
|
|
}
|
|
|
|
|
|
void
|
|
Slicer::outline( Arc_ptr jarc )
|
|
{
|
|
jarc->markverts();
|
|
|
|
if( jarc->pwlArc->npts >= 2 ) {
|
|
backend.bgnoutline();
|
|
for( int j = jarc->pwlArc->npts-1; j >= 0; j-- )
|
|
backend.linevert( &(jarc->pwlArc->pts[j]) );
|
|
backend.endoutline();
|
|
}
|
|
}
|
|
|
|
|