void EngineTessellator::Run(double windingRule, bool ccw)
{
	//make sure the last polygon is inserted
	if (current.size())
	{
		polygons.push_back(current);
		current.clear();
	}

	tessellate_t* t=new tessellate_t;
	t->ccw = ccw;
	t->tess = gluNewTess();
	DebugAssert(t->tess);

	gluTessCallback( t->tess, GLU_TESS_ERROR       ,(void (CALLBACK*)())callback_error);
	gluTessCallback( t->tess, GLU_TESS_VERTEX_DATA ,(void (CALLBACK*)())callback_vertex);
	gluTessCallback( t->tess, GLU_TESS_BEGIN_DATA  ,(void (CALLBACK*)())callback_begin);
	gluTessCallback( t->tess, GLU_TESS_END_DATA    ,(void (CALLBACK*)())callback_end);
	gluTessCallback( t->tess, GLU_TESS_COMBINE_DATA,(void (CALLBACK*)())callback_combine);
	gluTessProperty( t->tess, GLU_TESS_WINDING_RULE, windingRule );
	gluTessProperty( t->tess, GLU_TESS_BOUNDARY_ONLY,GL_FALSE); 

	for (polygon_set_t::const_iterator IT=polygons.begin();IT!=polygons.end();IT++)
	{
		const polygon_t& polygon=*IT;

		gluTessBeginPolygon(t->tess,t);
		for (polygon_t::const_iterator JT=polygon.begin();JT!=polygon.end();JT++)
		{
			const contour_t& contour=*JT;
			gluTessBeginContour(t->tess);
			for (int V=0;V<(int)contour.size();V++)
			{
				double* v=new double[3];
				t->to_dealloc.push_back(v);
				v[0]=contour[V].x;
				v[1]=contour[V].y;
				v[2]=contour[V].z;
				gluTessVertex(t->tess,v,v);
			}
			gluTessEndContour(t->tess);
		}
		gluTessEndPolygon(t->tess);
	}

	this->m_raw_triangles=std::vector<Vec3f>();
	for (int I=0;I<(int)t->result.size();I+=3)
	{
		Vec3f& v0=t->result[I+0];this->m_raw_triangles.push_back(Vec3f(v0.x,v0.y,v0.z));
		Vec3f& v1=t->result[I+1];this->m_raw_triangles.push_back(Vec3f(v1.x,v1.y,v1.z));
		Vec3f& v2=t->result[I+2];this->m_raw_triangles.push_back(Vec3f(v2.x,v2.y,v2.z));	
	}

	//the projection matrix
	Mat4f T=Mat4f::getProjectionMatrix(t->result);
	Mat4f Ti=T.invert();

	this->m_matrix=Mat4f(Ti);

	//the graph
	m_g.reset(new Graph(2));

	for (int I=0;I<(int)t->result.size();I+=3)
	{
		Vec3f _v0=T * t->result[I+0];
		Vec3f _v1=T * t->result[I+1];
		Vec3f _v2=T * t->result[I+2];

		//after the projection they should have one less coordinate (which should be v.z)
		Vecf v0=Vecf(1.0f,_v0.x,_v0.y);
		Vecf v1=Vecf(1.0f,_v1.x,_v1.y);
		Vecf v2=Vecf(1.0f,_v2.x,_v2.y);

		//*** vertices *** 
		unsigned int N0=m_g->findVertex(v0); 
		unsigned int N1=m_g->findVertex(v1); 
		unsigned int N2=m_g->findVertex(v2);

		if (!N0) N0=m_g->addVertex(v0);
		if (!N1) N1=m_g->addVertex(v1);
		if (!N2) N2=m_g->addVertex(v2);

		//***  edges *** 
		unsigned int E01=0,E12=0,E20=0;

		E01=m_g->findFirstCommonNode(N0,N1,Graph::DIRECTION_UP);
		E12=m_g->findFirstCommonNode(N1,N2,Graph::DIRECTION_UP);
		E20=m_g->findFirstCommonNode(N2,N0,Graph::DIRECTION_UP);

		if (!E01) {E01=m_g->addEdge(N0,N1);memcpy(m_g->getGeometry(E01,true),m_g->getFittingPlane(E01).mem,sizeof(float)*3);}
		if (!E12) {E12=m_g->addEdge(N1,N2);memcpy(m_g->getGeometry(E12,true),m_g->getFittingPlane(E12).mem,sizeof(float)*3);}
		if (!E20) {E20=m_g->addEdge(N2,N0);memcpy(m_g->getGeometry(E20,true),m_g->getFittingPlane(E20).mem,sizeof(float)*3);}

		//***  triangle *** 
		unsigned int T=0;

		if (!T) {T=m_g->findFirstCommonNode(E01,E12,Graph::DIRECTION_UP);DebugAssert(!T || m_g->findArch(E20,T,Graph::DIRECTION_UP)!=0);}
		if (!T) {T=m_g->findFirstCommonNode(E12,E20,Graph::DIRECTION_UP);DebugAssert(!T || m_g->findArch(E01,T,Graph::DIRECTION_UP)!=0);}
		if (!T) {T=m_g->findFirstCommonNode(E20,E01,Graph::DIRECTION_UP);DebugAssert(!T || m_g->findArch(E12,T,Graph::DIRECTION_UP)!=0);}

		//if the triangle does not exists
		if (!T)
		{
			unsigned int T=m_g->addNode(2);
			m_g->addArch(E01,T);
			m_g->addArch(E12,T);
			m_g->addArch(E20,T);
			m_g->addArch(T,N0);//double connectivity
			m_g->addArch(T,N1);
			m_g->addArch(T,N2);
		}
	}

	//deallocate tessellator
	gluDeleteTess(t->tess);
	for (int i=0;i<(int)t->to_dealloc.size();i++)  delete [] t->to_dealloc[i];
	delete t;

}
Example #2
0
void GLAPIENTRY
gluEndPolygon( GLUtesselator *tess )
{
  gluTessEndContour( tess );
  gluTessEndPolygon( tess );
}
void ProtoTessellator::endPolygon() {
	gluTessEndPolygon(tesselator);


}
Example #4
0
void init (void) 
{
   int i;
   GLUtesselator *tobj;
   GLdouble rect[4][3] = {50.0, 50.0, 0.0,
                          200.0, 50.0, 0.0,
                          200.0, 200.0, 0.0,
                          50.0, 200.0, 0.0};
   GLdouble tri[3][3] = {75.0, 75.0, 0.0,
                         125.0, 175.0, 0.0,
                         175.0, 75.0, 0.0};
   GLdouble star[5][6] = {250.0, 50.0, 0.0, 1.0, 0.0, 1.0,
                          325.0, 200.0, 0.0, 1.0, 1.0, 0.0,
                          400.0, 50.0, 0.0, 0.0, 1.0, 1.0,
                          250.0, 150.0, 0.0, 1.0, 0.0, 0.0,
                          400.0, 150.0, 0.0, 0.0, 1.0, 0.0};

   glClearColor(0.0, 0.0, 0.0, 0.0);


   startList = glGenLists(2);

   tobj = gluNewTess();
   gluTessCallback(tobj, GLU_TESS_VERTEX, 
                   glVertex3dv);
   gluTessCallback(tobj, GLU_TESS_BEGIN, 
                   beginCallback);
   gluTessCallback(tobj, GLU_TESS_END, 
                   endCallback);
   gluTessCallback(tobj, GLU_TESS_ERROR, 
                   errorCallback);

   /*  rectangle with triangular hole inside  */
   glNewList(startList, GL_COMPILE);
   glShadeModel(GL_FLAT);    
printf("a");
   gluTessBeginPolygon(tobj, NULL);
printf("b");
      gluTessBeginContour(tobj);
printf("c");
         gluTessVertex(tobj, rect[0], rect[0]);
         gluTessVertex(tobj, rect[1], rect[1]);
         gluTessVertex(tobj, rect[2], rect[2]);
         gluTessVertex(tobj, rect[3], rect[3]);
      gluTessEndContour(tobj);
printf(" d");
      gluTessBeginContour(tobj);
printf("e");
         gluTessVertex(tobj, tri[0], tri[0]);
         gluTessVertex(tobj, tri[1], tri[1]);
         gluTessVertex(tobj, tri[2], tri[2]);
printf("f");
      gluTessEndContour(tobj);
printf("g");
   gluTessEndPolygon(tobj);
printf(" h");
   glEndList();

   gluTessCallback(tobj, GLU_TESS_VERTEX, 
                   vertexCallback);
   gluTessCallback(tobj, GLU_TESS_BEGIN, 
                   beginCallback);
   gluTessCallback(tobj, GLU_TESS_END, 
                   endCallback);
   gluTessCallback(tobj, GLU_TESS_ERROR, 
                   errorCallback);
   gluTessCallback(tobj, GLU_TESS_COMBINE, 
                   combineCallback);

   /*  smooth shaded, self-intersecting star  */
   glNewList(startList + 1, GL_COMPILE);
   glShadeModel(GL_SMOOTH);    
   gluTessProperty(tobj, GLU_TESS_WINDING_RULE,
                   GLU_TESS_WINDING_POSITIVE);
   gluTessBeginPolygon(tobj, NULL);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, star[0], star[0]);
         gluTessVertex(tobj, star[1], star[1]);
         gluTessVertex(tobj, star[2], star[2]);
         gluTessVertex(tobj, star[3], star[3]);
         gluTessVertex(tobj, star[4], star[4]);
      gluTessEndContour(tobj);
   gluTessEndPolygon(tobj);


	glPushMatrix();
		glTranslatef(-100.0, 200.0, 0.0);
		glBegin(GL_POLYGON);
		for (i=0; i<5; i++) {
			glColor3f(star[i][3], star[i][4], star[i][5]);
			glVertex3f(star[i][0], star[i][1], star[i][2]);
		}
		glEnd();
		glColor3f(1,1,1);
		glBegin(GL_LINE_STRIP);
			glVertex3f(100, 100, 0);
			glVertex3f(100, -100, 0);
			glVertex3f(-100, 0, 0);
			glVertex3f(100, 0, 0);
		glEnd();
	glPopMatrix();


   glEndList();
   gluDeleteTess(tobj);
}
PsychError SCREENFillPoly(void)  
{	
	PsychColorType				color;
	PsychWindowRecordType		*windowRecord;
	double						whiteValue;
	int							i, mSize, nSize, pSize;
	psych_bool					isArgThere;
	double						*pointList;
	double						isConvex;
	int							j,k;
	int							flag;
	double						z;
	
	combinerCacheSlot = 0;
	combinerCacheSize = 0;
	combinerCache = NULL;
	
	//all sub functions should have these two lines
	PsychPushHelp(useString, synopsisString,seeAlsoString);
	if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};
	
	//check for superfluous arguments
	PsychErrorExit(PsychCapNumInputArgs(4));   //The maximum number of inputs
	PsychErrorExit(PsychCapNumOutputArgs(0));  //The maximum number of outputs
	
	//get the window record from the window record argument and get info from the window record
	PsychAllocInWindowRecordArg(1, kPsychArgRequired, &windowRecord);
	
	//Get the color argument or use the default, then coerce to the form determened by the window depth.  
	isArgThere=PsychCopyInColorArg(2, FALSE, &color);
	if(!isArgThere){
		whiteValue=PsychGetWhiteValueFromWindow(windowRecord);
		PsychLoadColorStruct(&color, kPsychIndexColor, whiteValue ); //index mode will coerce to any other.
	}
 	PsychCoerceColorMode( &color);
	
	//get the list of pairs and validate.  
	PsychAllocInDoubleMatArg(3, kPsychArgRequired, &mSize, &nSize, &pSize, &pointList);
	if(nSize!=2) PsychErrorExitMsg(PsychError_user, "Width of pointList must be 2");
	if(mSize<3)  PsychErrorExitMsg(PsychError_user, "Polygons must consist of at least 3 points; M dimension of pointList was < 3!");
	if(pSize>1)  PsychErrorExitMsg(PsychError_user, "pointList must be a 2D matrix, not a 3D matrix!");
	
	isConvex = -1;
	PsychCopyInDoubleArg(4, kPsychArgOptional, &isConvex);
	
    // On non-OpenGL1/2 we always force isConvex to zero, so the GLU tesselator is
    // always used. This because the tesselator only emits GL_TRIANGLES and GL_TRIANGLE_STRIP
    // and GL_TRIANGLE_FANS primitives which are supported on all current OpenGL API's, whereas
    // or "classic" fast-path needs GL_POLYGONS, which are only supported on classic OpenGL1/2:
    if (!PsychIsGLClassic(windowRecord)) isConvex = 0;

	// Enable this windowRecords framebuffer as current drawingtarget:
	PsychSetDrawingTarget(windowRecord);
	
	// Set default drawshader:
	PsychSetShader(windowRecord, -1);
	
	PsychUpdateAlphaBlendingFactorLazily(windowRecord);		 
	PsychSetGLColor(&color, windowRecord);
	
	///////// Test for convexity ////////
	// This algorithm checks, if the polygon is definitely convex, or not.
	// We take the slow-path, if polygon is non-convex or if we can't prove
	// that it is convex.
	//
	// Algorithm adapted from: http://astronomy.swin.edu.au/~pbourke/geometry/clockwise/
	// Which was written by Paul Bourke, 1998.
	//
	// -> This webpage explains the mathematical principle behind the test and provides
	// a C-Source file which has been adapted for use here.
	//	
	if (isConvex == -1) {
		flag = 0;
		for (i=0; i < mSize; i++) {
			j = (i + 1) % mSize;
			k = (i + 2) % mSize;
			z  = (pointList[j] - pointList[i]) * (pointList[k+mSize] - pointList[j+mSize]);
			z -= (pointList[j+mSize] - pointList[i+mSize]) * (pointList[k] - pointList[j]);
			
			if (z < 0) {
				flag |= 1;
			}
			else if (z > 0) {
				flag |= 2;
			}
			
			if (flag == 3) {
				// This is definitely a CONCAVE polygon --> not Convex --> Take slow but safe path.
				break;
			}
		}
		
		if (flag!=0 && flag!=3) {
			// This is a convex polygon --> Take fast path.
			isConvex = 1;
		}
		else {
			// This is a complex polygon --> can't determine if it is convex or not --> Take slow but safe path.
			isConvex = 0;
		}
	}
			
	////// Switch between fast path and slow path, depending on convexity of polygon:
	if (isConvex > 0) {
		// Convex, non-self-intersecting polygon - Take the fast-path:
		glBegin(GL_POLYGON);
		for(i=0;i<mSize;i++) glVertex2d((GLdouble)pointList[i], (GLdouble)pointList[i+mSize]);
		glEnd();
	}
	else {
		// Possibly concave and/or self-intersecting polygon - At least we couldn't prove it is convex.
		// Take the slow, but safe, path using GLU-Tesselators to break it up into a couple of convex, simple
		// polygons:
		
		// Create and initialize a new GLU-Tesselator object, if needed:
		if (NULL == tess) {
			// Create tesselator:
			tess = gluNewTess();
			if (NULL == tess) PsychErrorExitMsg(PsychError_outofMemory, "Out of memory condition in Screen('FillPoly')! Not enough space.");

			// Assign our callback-functions:
			gluTessCallback(tess, GLU_TESS_BEGIN, GLUTESSCBCASTER PsychtcbBegin);
			gluTessCallback(tess, GLU_TESS_VERTEX, GLUTESSCBCASTER PsychtcbVertex);
			gluTessCallback(tess, GLU_TESS_END, GLUTESSCBCASTER PsychtcbEnd);
			gluTessCallback(tess, GLU_TESS_COMBINE, GLUTESSCBCASTER PsychtcbCombine);

			// Define all tesselated polygons to lie in the x-y plane:
			gluTessNormal(tess, 0, 0, 1);
		}

		// We need to hold the values in a temporary array:
		if (tempvsize < mSize) {
			tempvsize = ((mSize / 1000) + 1) * 1000;
			tempv = (double*) realloc((void*) tempv, sizeof(double) * 3 * tempvsize);
			if (NULL == tempv) PsychErrorExitMsg(PsychError_outofMemory, "Out of memory condition in Screen('FillPoly')! Not enough space.");
		}

		// Now submit our Polygon for tesselation:
		gluTessBeginPolygon(tess, NULL);
		gluTessBeginContour(tess);

		for(i=0; i < mSize; i++) {
			tempv[i*3]=(GLdouble) pointList[i];
			tempv[i*3+1]=(GLdouble) pointList[i+mSize];
			tempv[i*3+2]=0;
			gluTessVertex(tess, (GLdouble*) &(tempv[i*3]), (void*) &(tempv[i*3]));
		}
		
		// Process, finalize and render it by calling our callback-functions:
		gluTessEndContour(tess);
		gluTessEndPolygon (tess);
		
		// Done with drawing the filled polygon. (Slow-Path)
	}
	
	// Mark end of drawing op. This is needed for single buffered drawing:
	PsychFlushGL(windowRecord);
	
	// printf("CombinerCalls %i out of %i allocated.\n", combinerCacheSlot, combinerCacheSize);

	return(PsychError_none);
}
void XMGPolygon::SetCoordArray ( const XMGVector2X* src_arr_coord, XMGTexUnit unit, GLuint src_idx_shape, GLuint src_idx_facet )
{
	XMGPolygonImpl*	impl = (XMGPolygonImpl *) m_impl;
	XMGRenderImpl*  impl_parent = (XMGRenderImpl *) XMGRender::m_impl;

	XMGTess*		data;

	XMGShape*		shape;
	XMGFacet*		facet;

	GLuint			idx_tess;
	GLuint			idx_shape;
	GLuint			idx_facet;
	GLuint			idx_vertex;

	GLuint			num_shape;
	GLuint			num_facet;
	GLuint			num_vertex;

	GLuint			off_src;

	XMGVector2F*	farr_coord;
	XMGVector2X*	xarr_coord;

	XMGRender::SetCoordArray ( src_arr_coord, unit, src_idx_shape, src_idx_facet );	

	if ( impl_parent->m_has_face[ 0 ] == XMG_FALSE && impl_parent->m_has_face[ 1 ] )
	{
		return;
	}

	if ( src_idx_facet != XMG_FACET_ALL )
	{
		shape = impl_parent->m_vec_shape[ src_idx_facet ];
		facet = shape->m_vec_facet[ src_idx_facet ];
		if ( facet->m_vec_contour.size ( ) == 0 )
		{
			return;
		}
	}

	off_src = 0;
	for ( impl_parent->RangeArray ( src_idx_shape, impl_parent->m_vec_shape.size ( ), idx_shape, num_shape ); idx_shape < num_shape; idx_shape++ )
	{
		shape = impl_parent->m_vec_shape[ idx_shape ];
		
		for ( impl_parent->RangeArray ( src_idx_facet, shape->m_vec_facet.size ( ), idx_facet, num_facet ); idx_facet < num_facet; idx_facet++ )
		{
			facet = shape->m_vec_facet[ idx_facet ];

			if ( idx_facet < 2 )
			{
				switch ( impl_parent->m_geo_type )
				{
					case XMG_GEO_CONE	:
					case XMG_GEO_CWALL	:	idx_tess = 1;			break;
					default				:	idx_tess = idx_facet;	break;
				}

				if ( impl->m_tess[ idx_tess ] )
				{
					data = impl->m_data[ idx_tess ][ idx_shape ];
					data->Init ( XMG_TESS_COORD );

					gluTessBeginPolygon ( impl->m_tess[ idx_tess ], (GLvoid *) data );
					gluTessBeginContour ( impl->m_tess[ idx_tess ] );	

					for ( idx_vertex = 0, num_vertex = shape->m_num_basic; idx_vertex < num_vertex; idx_vertex++ )
					{
						data->m_arr_vertex[ idx_vertex * 8 + 6 ] = XMG_X2F ( src_arr_coord[ off_src + idx_vertex ].m_x );
						data->m_arr_vertex[ idx_vertex * 8 + 7 ] = XMG_X2F ( src_arr_coord[ off_src + idx_vertex ].m_y );

						if ( shape->m_idx_hole != 0 && shape->m_idx_hole == idx_vertex )
						{
							gluNextContour ( impl->m_tess[ idx_tess ], GLU_INTERIOR );
						}

						gluTessVertex ( impl->m_tess[ idx_tess ], &data->m_arr_vertex[ idx_vertex * 8 ], &data->m_arr_vertex[ idx_vertex * 8 ] );
					}

					gluTessEndContour ( impl->m_tess[ idx_tess ] );
					gluTessEndPolygon ( impl->m_tess[ idx_tess ] );

					if ( impl_parent->m_type_coords[ unit ] == XMG_TYPE_FLOAT )
					{
						XMGAssert ( farr_coord = (XMGVector2F *) kdMalloc ( sizeof ( XMGVector2F ) * facet->m_num_ext ) );

						for ( idx_vertex = 0, num_vertex = facet->m_num_ext; idx_vertex < num_vertex; idx_vertex++ )
						{
							farr_coord[ idx_vertex ] = data->m_vec_coord[ idx_vertex ];
						}

						impl_parent->SetBuffer ( impl_parent->m_id_coords[ unit ], farr_coord, sizeof ( XMGVector2F ) * facet->m_off_ext, sizeof ( XMGVector2F ) * facet->m_num_ext );
						kdFree ( farr_coord );
					}
					else
					{
						XMGAssert ( xarr_coord = (XMGVector2X *) kdMalloc ( sizeof ( XMGVector2X ) * facet->m_num_ext ) );

						for ( idx_vertex = 0, num_vertex = facet->m_num_ext; idx_vertex < num_vertex; idx_vertex++ )
						{
							xarr_coord[ idx_vertex ] = data->m_vec_coord[ idx_vertex ];
						}

						impl_parent->SetBuffer ( impl_parent->m_id_coords[ unit ], xarr_coord, sizeof ( XMGVector2X ) * facet->m_off_ext, sizeof ( XMGVector2X ) * facet->m_num_ext );
						kdFree ( xarr_coord );
					}
				}			
			}

			off_src += facet->m_num_vertex;
		}
	}
}
Example #7
0
void tesselateComplexPolygon(Array<Vector3>& input, Array<Triangle>& output) {
    // Use the GLU triangulator to do the hard work.

    static GLUtriangulatorObj* tobj = NULL;

    if (tobj == NULL) {
        tobj = gluNewTess();
#if defined(G3D_OSX) 
        #define CAST(x) reinterpret_cast<void (*)(...)>(x)
#elif defined(G3D_LINUX)
        #define CAST(x) reinterpret_cast<void (*)()>(x)
#else
        #define CAST(x) reinterpret_cast<void (__stdcall *)(void)>(x) 
#endif
	gluTessCallback(tobj, GLU_TESS_BEGIN_DATA,    CAST(_tesselateBegin));
        gluTessCallback(tobj, GLU_TESS_VERTEX_DATA,   CAST(_tesselateVertex));
        gluTessCallback(tobj, GLU_TESS_END_DATA,      CAST(_tesselateEnd));
        gluTessCallback(tobj, GLU_TESS_COMBINE_DATA,  CAST(_tesselateCombine));
        gluTessCallback(tobj, GLU_TESS_ERROR,         CAST(_tesselateError));
        gluTessProperty(tobj, GLU_TESS_BOUNDARY_ONLY, GL_FALSE);
        gluTessProperty(tobj, GLU_TESS_WINDING_RULE,  GLU_TESS_WINDING_ODD);
        #undef CAST
    }

    double v[3];
    int i;
    TessData data;

    gluTessBeginPolygon(tobj, &data);
        gluTessBeginContour(tobj);
            for (i = 0; i < input.size(); ++i) {
                // Expand the input to double precision
                v[0] = input[i].x;
                v[1] = input[i].y;
                v[2] = input[i].z;
                gluTessVertex(tobj, v, &(input[i]));
            }
        gluTessEndContour(tobj);
    gluTessEndPolygon(tobj);


    for (int p = 0; p < data.primitive.size(); ++p) {
        const TessData::Primitive& primitive = data.primitive[p];

        // Turn the tesselated primitive into triangles
        switch (primitive.primitiveType) {
        case GL_TRIANGLES:
            // This is easy, just walk through them in order.
            for (i = 0; i < primitive.vertex.size(); i += 3) {
                output.append(Triangle(primitive.vertex[i], primitive.vertex[i + 1], primitive.vertex[i + 2]));
            }
            break;

        case GL_TRIANGLE_FAN:
            {
                // Make a triangle between every pair of vertices and the 1st vertex
                for (i = 1; i < primitive.vertex.size() - 1; ++i) {
                    output.append(Triangle(primitive.vertex[0], primitive.vertex[i], primitive.vertex[i + 1]));
                }
            }
            break;

        case GL_TRIANGLE_STRIP:
            for (i = 0; i < primitive.vertex.size() - 3; i += 2) {
                output.append(Triangle(primitive.vertex[i], primitive.vertex[i + 1], primitive.vertex[i + 2]));
                output.append(Triangle(primitive.vertex[i + 2], primitive.vertex[i + 1], primitive.vertex[i + 3]));
            }
            if (i < primitive.vertex.size() - 2) {
                output.append(Triangle(primitive.vertex[i], primitive.vertex[i + 1], primitive.vertex[i + 2]));
            }
            break;

        default:
            //debugAssertM(false, GLenumToString(primitive.primitiveType));
            // Ignore other primitives
            ;
        }
    }
}
/*
 * endPolygon
 */
void TessellatePolygon::endPolygon(void) {
    gluTessEndPolygon(tessellationObject);
} // end endPolygon()
/* draw all solid polygons found in aPolysList
 * aZpos = z position in board internal units
 * aThickness = thickness in board internal units
 * If aThickness = 0, a polygon area is drawn in a XY plane at Z position = aZpos.
 * If aThickness > 0, a solid object is drawn.
 *  The top side is located at aZpos + aThickness / 2
 *  The bottom side is located at aZpos - aThickness / 2
 */
void Draw3D_SolidHorizontalPolyPolygons( const CPOLYGONS_LIST& aPolysList,
        int aZpos, int aThickness, double aBiuTo3DUnits,
        bool aUseTextures )
{
    // for Tess callback functions:
    s_biuTo3Dunits = aBiuTo3DUnits;
    s_useTextures = aUseTextures;

    GLUtesselator* tess = gluNewTess();

    gluTessCallback( tess, GLU_TESS_BEGIN, ( void (CALLBACK*) () )tessBeginCB );
    gluTessCallback( tess, GLU_TESS_END, ( void (CALLBACK*) () )tessEndCB );
    gluTessCallback( tess, GLU_TESS_ERROR, ( void (CALLBACK*) () )tessErrorCB );
    gluTessCallback( tess, GLU_TESS_VERTEX, ( void (CALLBACK*) () )tessCPolyPt2Vertex );

    GLdouble    v_data[3];
    double      zpos = ( aZpos + (aThickness / 2.0) ) * aBiuTo3DUnits;
    s_currentZpos = zpos;     // for Tess callback functions
    v_data[2] = aZpos + (aThickness / 2.0);

    // Set normal toward positive Z axis, for a solid object on the top side
    if( aThickness )
        SetNormalZpos();

    // gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);

    // Draw solid areas contained in this list
    CPOLYGONS_LIST polylist = aPolysList;    // temporary copy for gluTessVertex

    int startContour;

    for( int side = 0; side < 2; side++ )
    {
        startContour = 1;

        for( unsigned ii = 0; ii < polylist.GetCornersCount(); ii++ )
        {
            if( startContour == 1 )
            {
                gluTessBeginPolygon( tess, NULL );
                gluTessBeginContour( tess );
                startContour = 0;
            }

            // https://www.opengl.org/sdk/docs/man2/xhtml/gluTessNormal.xml
            gluTessNormal( tess, 0.0, 0.0, 0.0 );


            v_data[0]   = polylist.GetX( ii ) * aBiuTo3DUnits;
            v_data[1]   = -polylist.GetY( ii ) * aBiuTo3DUnits;
            // gluTessVertex store pointers on data, not data, so do not store
            // different corners values in a temporary variable
            // but send pointer on each CPolyPt value in polylist
            // before calling gluDeleteTess
            gluTessVertex( tess, v_data, &polylist[ii] );


            if( polylist.IsEndContour( ii ) )
            {
                gluTessEndContour( tess );
                gluTessEndPolygon( tess );
                startContour = 1;
            }
        }

        if( aThickness == 0 )
            break;

        // Prepare the bottom side of solid areas
        zpos = ( aZpos - (aThickness / 2.0) ) * aBiuTo3DUnits;
        s_currentZpos = zpos;     // for Tess callback functions
        v_data[2] = zpos;
        // Set normal toward negative Z axis, for a solid object on bottom side
        SetNormalZneg();
    }

    if( startContour == 0 )
    {
        gluTessEndContour( tess );
        gluTessEndPolygon( tess );
    }

    gluDeleteTess( tess );

    if( aThickness == 0 )
    {
        return;
    }

    // Build the 3D data : vertical side
    Draw3D_VerticalPolygonalCylinder( polylist, aThickness, aZpos - (aThickness / 2.0), false, aBiuTo3DUnits );
}
Example #10
0
void Tessel::EndPolygon()
{
	gluTessEndContour(obj);
	gluTessEndPolygon(obj);
}
void DVRClipper::clipSlice(      DVRVolume      *volume,
                                 DVRSlice       &unclippedSlice, 
                           const Vec3f          &slicingNormal, 
                                 Real32          dist2RefPlane,
                                 DVRRenderSlice &clippedSlice)
{
    const Vec3f &texScale     = unclippedSlice.getTextureScale    ();
    const Vec3f &texTranslate = unclippedSlice.getTextureTranslate();

    // get clip objects
    DVRClipObjectsPtr clipObjects = DVRVOLUME_PARAMETER(volume, 
                                                        DVRClipObjects);

    // nothing to clip with?
    if(clipObjects == NullFC)
    {
        DVRRenderSlicePrimitive *newPrimitive =  new DVRRenderSlicePrimitive();

        newPrimitive->type = GL_TRIANGLE_FAN;

        for(UInt32 i = 0; i < unclippedSlice.getVertexCount(); i++)
        {
            UInt32 idx = (6+numAddPerVertexAttr)*i;
            sliceVertexData[idx    ] = 
                unclippedSlice.getVertex(i).getValues()[0];

            sliceVertexData[idx + 1] = 
                unclippedSlice.getVertex(i).getValues()[1];

            sliceVertexData[idx + 2] =
                unclippedSlice.getVertex(i).getValues()[2];


            // set (standard) texture coordinates
            sliceVertexData[idx + 3] = 
                texScale[0] * 
                unclippedSlice.getVertex(i).getValues()[0] + 
                texTranslate[0];

            sliceVertexData[idx + 4] = 
                texScale[1] * 
                unclippedSlice.getVertex(i).getValues()[1] + 
                texTranslate[1];

            sliceVertexData[idx + 5] = 
                texScale[2] * 
                unclippedSlice.getVertex(i).getValues()[2] + 
                texTranslate[2];      

            newPrimitive->vertices.push_back(&sliceVertexData[idx]);
        }

        clippedSlice.push_back(newPrimitive);
        
        return;
    }

    if(!hasTesselatorSupport)
        return;

    // render colored contours only (usefull for debugging)
    if(clipObjects->getDoContours())
    {
        glDisable(GL_TEXTURE   );
        glDisable(GL_LIGHTING  );

        glBegin  (GL_LINE_STRIP);  
        {
            int col = 0;
            
            for(UInt32 i = 0; i < unclippedSlice.getVertexCount(); i++)
            {      
                glColor3f(col % 3 == 0 ? 1.0f : 0.0f, 
                          col % 3 == 1 ? 1.0f : 0.0f, 
                          col % 3 == 2 ? 1.0f : 0.0f);
                
                col++;
                
                glVertex3fv(unclippedSlice.getVertex(i).getValues());
            }
        }
        glEnd();
   
        bool clipAwayOutside = 
            clipObjects->getClipMode() == DVRClipObjects::Difference;
    
        for(UInt32 i = 0; i < clipObjects->count(); i++)
        {
            // get i-th clip object
            DVRClipGeometryPtr clipObject = clipObjects->get(i);
      
            // compute the contours of the triangles intersecting the 
            // current slice

            const DVRTriangleList &contours = 
                clipObject->getContours(dist2RefPlane,
                                        !clipAwayOutside,
                                        slicingNormal);     
      
            if(!contours.empty())
            {
                DVRTriangle *current;
                DVRTriangle *contourStart;
	
                // iterate over all contours
                DVRTriangleList::const_iterator contoursIt;

                for(contoursIt  = contours.begin(); 
                    contoursIt != contours.end  (); 
                    contoursIt++)
                { 
                    contourStart = current = *contoursIt;	 
	  
                    glBegin(GL_LINE_STRIP);	  
                    {
                        int col = 0;
                        
                        // iterate over all triangles in the current contour
                        do
                        {	    	   
                            glColor3f(col % 3 == 0 ? 1.0f : 0.0f, 
                                      col % 3 == 1 ? 1.0f : 0.0f, 
                                      col % 3 == 2 ? 1.0f : 0.0f);

                            col++;

                            glVertex3dv(current->cutPoint);

                            current = current->contourNeighbour;

                        } while(current!= contourStart);
                    }
                    glEnd();
                }
            }
        }
        
        glEnable(GL_TEXTURE );
        glEnable(GL_LIGHTING);
        
    }
    else
    {
        // tesselate and render the clipped slices

        // set the slice normal for tesselation
        gluTessNormal(myTess, 
                      slicingNormal[0], 
                      slicingNormal[1], 
                      slicingNormal[2]);    
        
        clippedSlice.clear();
        
        gluTessBeginPolygon(myTess, &clippedSlice);
    
        // set the slice's base contour
        gluTessBeginContour(myTess);
        
        for(UInt32 i = 0; i < unclippedSlice.getVertexCount(); i++)
        {       
            UInt32 idx = (6 + numAddPerVertexAttr) * i;

            sliceVertexData[idx    ] = 
                unclippedSlice.getVertex(i).getValues()[0];

            sliceVertexData[idx + 1] = 
                unclippedSlice.getVertex(i).getValues()[1];

            sliceVertexData[idx + 2] = 
                unclippedSlice.getVertex(i).getValues()[2];

            // set (standard) texture coordinates
            sliceVertexData[idx + 3] = 
                texScale[0] *
                unclippedSlice.getVertex(i).getValues()[0] + 
                texTranslate[0];

            sliceVertexData[idx + 4] = 
                texScale[1] * 
                unclippedSlice.getVertex(i).getValues()[1] + 
                texTranslate[1];

            sliceVertexData[idx + 5] = 
                texScale[2] * 
                unclippedSlice.getVertex(i).getValues()[2] +
                texTranslate[2];

            gluTessVertex(myTess, 
                          &sliceVertexData[idx], 
                          &sliceVertexData[idx]);
        }
        
        gluTessEndContour(myTess);
        
        // set contours of clip objects
        if(clipObjects->getClipMode() != DVRClipObjects::Off)
        {
            // get clip mode
            bool clipAwayOutside = 
                clipObjects->getClipMode() == DVRClipObjects::Difference;
      
            // add the contours of the intersections of the clip geometries 
            // with the slice
            for(UInt32 i = 0; i < clipObjects->count(); i++)
            {
                // get i-th clip object
                DVRClipGeometryPtr clipObject = clipObjects->get(i);
	
                // compute the contours of the triangles intersecting 
                // the current slice

                const DVRTriangleList &contours = 
                    clipObject->getContours( dist2RefPlane,
                                            !clipAwayOutside,
                                             slicingNormal);       
	
                if(!contours.empty())
                {
                    DVRTriangle *current;
                    DVRTriangle *contourStart;
	  
                    // iterate over all contours
                    DVRTriangleList::const_iterator contoursIt;

                    for(contoursIt  = contours.begin(); 
                        contoursIt != contours.end  (); 
                        contoursIt++)
                    { 
                        contourStart = current = *contoursIt;
	    	    
                        // start new contour
                        gluTessBeginContour(myTess);
	    
                        // iterate over all triangles in the current contour
                        do
                        {	    
                            // set (standard) texture coordinates
                            current->cutPoint[3] = 
                                texScale[0] * 
                                current->cutPoint[0] + 
                                texTranslate[0];

                            current->cutPoint[4] = 
                                texScale[1] * 
                                current->cutPoint[1] + 
                                texTranslate[1];

                            current->cutPoint[5] = 
                                texScale[2] * 
                                current->cutPoint[2] + 
                                texTranslate[2];

                            if(!current->cutPoint)
                                std::cerr << "WTF: cutPoint is NULL"
                                          << std::endl;

                            gluTessVertex(myTess, 
                                          current->cutPoint, 
                                          current->cutPoint);

                            current = current->contourNeighbour;

                        } while(current != contourStart);
	    
                        gluTessEndContour(myTess);
                    }
                }
            }
        }
        
        gluTessEndPolygon(myTess);
    }
}
Example #12
0
void Tesselator::compute()
{
    gluTessEndPolygon( _tobj );
}
Example #13
0
int erl_tess_impl(char* buff, ErlDrvPort port, ErlDrvTermData caller)
{
  ErlDrvBinary* bin;
  int i;
  GLdouble* new_vertices;
  int *vertices;
  int num_vertices;
  GLdouble *n;
  int n_pos, AP, res;
  
  num_vertices = * (int *) buff; buff += 8; /* Align */
  n = (double *) buff; buff += 8*3;

  bin = driver_alloc_binary(num_vertices*6*sizeof(GLdouble));  
  new_vertices = tess_coords = (double *) bin->orig_bytes;
  memcpy(tess_coords,buff,num_vertices*3*sizeof(GLdouble));
  tess_alloc_vertex = tess_coords + num_vertices*3;

#if 0
  fprintf(stderr, "n=%d\r\n", num_vertices);
#endif 
  vertices = (int *) driver_alloc(sizeof(int) * 16*num_vertices);
  
  tess_vertices = vertices;
  
  gluTessNormal(tess, n[0], n[1], n[2]);
  gluTessBeginPolygon(tess, 0);
  gluTessBeginContour(tess);
  for (i = 0; i < num_vertices; i++) {
    gluTessVertex(tess, tess_coords+3*i, tess_coords+3*i);
  }
  gluTessEndContour(tess);
  gluTessEndPolygon(tess);
    
  n_pos = (tess_vertices - vertices); 
  
  AP = 0; ErlDrvTermData *rt;
  rt = (ErlDrvTermData *) driver_alloc(sizeof(ErlDrvTermData) * (13+n_pos*2));
  rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_egl_result_");

  for(i=0; i < n_pos; i++) {
    rt[AP++] = ERL_DRV_INT; rt[AP++] = (int) vertices[i];
  };
  rt[AP++] = ERL_DRV_NIL; rt[AP++] = ERL_DRV_LIST; rt[AP++] = n_pos+1;

  rt[AP++] = ERL_DRV_BINARY; rt[AP++] = (ErlDrvTermData) bin; 
  rt[AP++] = (tess_alloc_vertex-new_vertices)*sizeof(GLdouble); rt[AP++] = 0;
  
  rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Return tuple {list, Bin}
  rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Result tuple
  
  res = driver_send_term(port,caller,rt,AP);
  /* fprintf(stderr, "List %d: %d %d %d \r\n",  */
  /* 	  res, */
  /* 	  n_pos,  */
  /* 	  (tess_alloc_vertex-new_vertices)*sizeof(GLdouble),  */
  /* 	  num_vertices*6*sizeof(GLdouble)); */
  driver_free_binary(bin);
  driver_free(vertices);
  driver_free(rt);
  return 0;
}
Example #14
0
void __stdcall
gluEndPolygon( GLUtesselator *tess )
{
  gluTessEndContour( tess );
  gluTessEndPolygon( tess );
}
Example #15
0
File: tess.c Project: ened/glues
void init_scene(int width, int height)
{
   GLubyte* tex;

   GLUtesselator* tobj;
   GLfloat rect[4][3]={
                         {50.0f,  50.0f,  0.0f},
                         {200.0f, 50.0f,  0.0f},
                         {200.0f, 200.0f, 0.0f},
                         {50.0f,  200.0f, 0.0f}
                      };
   GLfloat tri[3][3]={
                        {75.0f,  75.0f,  0.0f},
                        {125.0f, 175.0f, 0.0f},
                        {175.0f, 75.0f,  0.0f}
                     };
   GLfloat star[5][6]={
                         {250.0f, 50.0f,  0.0f, 1.0f, 0.0f, 1.0f},
                         {325.0f, 200.0f, 0.0f, 1.0f, 1.0f, 0.0f},
                         {400.0f, 50.0f,  0.0f, 0.0f, 1.0f, 1.0f},
                         {250.0f, 150.0f, 0.0f, 1.0f, 0.0f, 0.0f},
                         {400.0f, 150.0f, 0.0f, 0.0f, 1.0f, 0.0f}
                      };
   GLfloat triangle[9][8]={
                             {450.0f, 50.0f,  0.0f, 1.0f,  0.0f,  0.0f,  0.0f,  0.0f},
                             {525.0f, 200.0f, 0.0f, 1.0f,  1.0f,  1.0f,  0.5f,  1.0f},
                             {600.0f, 50.0f,  0.0f, 0.0f,  0.0f,  1.0f,  1.0f,  0.0f},
                             {500.0f, 50.0f,  0.0f, 0.666f, 0.000f, 0.333f, 0.333f, 0.000f},
                             {550.0f, 150.0f, 0.0f, 0.666f, 0.666f, 1.000f, 0.666f, 0.666f},
                             {500.0f, 150.0f, 0.0f, 1.000f, 0.666f, 0.666f, 0.333f, 0.666f},
                             {550.0f, 50.0f,  0.0f, 0.333f, 0.000f, 0.666f, 0.666f, 0.000f},
                             {575.0f, 100.0f, 0.0f, 0.333f, 0.333f, 1.000f, 0.825f, 0.333f},
                             {475.0f, 100.0f, 0.0f, 1.000f, 0.333f, 0.333f, 0.175f, 0.333f}
                          };

   glViewport(0, 0, (GLsizei)width, (GLsizei)height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluOrtho2D(0.0f, (GLfloat)width, 0.0f, (GLfloat)height);

   glClearColor(0.0, 0.0, 0.0, 0.0);

   /* Create new triangulator */
   tobj=gluNewTess();

   /* Set triangulator's callbacks */
   gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, (GLvoid (*)())&vertexCallback);
   gluTessCallback(tobj, GLU_TESS_BEGIN_DATA, (GLvoid (*)())&beginCallback);
   gluTessCallback(tobj, GLU_TESS_END_DATA, (GLvoid (*)())&endCallback);
   gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid (*)())&errorCallback);

   /* reset object */
   object1.sequences=0;

   /* rectangle with triangular hole inside */
   gluTessBeginPolygon(tobj, (void*)&object1);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, rect[0], rect[0]);
         gluTessVertex(tobj, rect[1], rect[1]);
         gluTessVertex(tobj, rect[2], rect[2]);
         gluTessVertex(tobj, rect[3], rect[3]);
      gluTessEndContour(tobj);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, tri[0], tri[0]);
         gluTessVertex(tobj, tri[1], tri[1]);
         gluTessVertex(tobj, tri[2], tri[2]);
      gluTessEndContour(tobj);
   gluTessEndPolygon(tobj);

   /* Set triangulator's callbacks */
   gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, (GLvoid (*)())&vertexColorCallback);
   gluTessCallback(tobj, GLU_TESS_BEGIN_DATA, (GLvoid (*)())&beginCallback);
   gluTessCallback(tobj, GLU_TESS_END_DATA, (GLvoid (*)())&endCallback);
   gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid (*)())&errorCallback);
   gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid (*)())&combineColorCallback);

   /* reset object */
   object2.sequences=0;

   /*  self-intersecting star  */
   gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE);
   gluTessBeginPolygon(tobj, (void*)&object2);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, star[0], star[0]);
         gluTessVertex(tobj, star[1], star[1]);
         gluTessVertex(tobj, star[2], star[2]);
         gluTessVertex(tobj, star[3], star[3]);
         gluTessVertex(tobj, star[4], star[4]);
      gluTessEndContour(tobj);
   gluTessEndPolygon(tobj);

   /* Set triangulator's callbacks */
   gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, (GLvoid (*)())&vertexTexColorCallback);
   gluTessCallback(tobj, GLU_TESS_BEGIN_DATA, (GLvoid (*)())&beginCallback);
   gluTessCallback(tobj, GLU_TESS_END_DATA, (GLvoid (*)())&endCallback);
   gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid (*)())&errorCallback);
   gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid (*)())&combineTexColorCallback);

   /* reset object */
   object3.sequences=0;

   /*  self-intersecting star  */
   gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE);
   gluTessBeginPolygon(tobj, (void*)&object3);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, triangle[0], triangle[0]);
         gluTessVertex(tobj, triangle[1], triangle[1]);
         gluTessVertex(tobj, triangle[2], triangle[2]);
      gluTessEndContour(tobj);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, triangle[3], triangle[3]);
         gluTessVertex(tobj, triangle[4], triangle[4]);
         gluTessVertex(tobj, triangle[5], triangle[5]);
         gluTessVertex(tobj, triangle[6], triangle[6]);
         gluTessVertex(tobj, triangle[7], triangle[7]);
         gluTessVertex(tobj, triangle[8], triangle[8]);
      gluTessEndContour(tobj);
   gluTessEndPolygon(tobj);

   /* Destroy triangulator object */
   gluDeleteTess(tobj);

   /* enable filtering */
   glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

   tex=make_texture(256, 256);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 256, 256, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, tex);
   free(tex);
}
Example #16
0
/* convert a PolyList into a linked list of PolyListNodes, subdivide
 * non-flat or concave polgons
 */
static PolyListNode *
PolyListToLinkedPoyList(Transform T, Transform Tdual, Transform TxT,
			const void **tagged_app,
			PolyListNode **plistp,
			PolyList *pl, struct obstack *scratch)
{
  PolyListNode *plist = NULL;
  int pnr;
  
  if (!plistp) {
    plistp = &plist;
  }

  PolyListComputeNormals(pl, PL_HASVN|PL_HASPN|PL_HASPFL);
  for (pnr = 0; pnr < pl->n_polys; pnr++) {
    PolyListNode *new_pn;
    Poly *poly;

    if (pl->p[pnr].flags & POLY_NOPOLY) {
      /* degenerated, just skip it */
      continue;
    }

    poly = &pl->p[pnr];
    poly->flags |= pl->geomflags;

    if (T && T != TM_IDENTITY) {
      poly = transform_poly(T, Tdual, TxT, poly, scratch);
    }

    switch (pl->p[pnr].n_vertices) {
    case 3: /* ok */
      new_pn = new_poly_list_node(tagged_app, scratch);
      new_pn->poly = poly;
      ListPush(*plistp, new_pn);
      break;
#if !HAVE_LIBGLU
    case 4: /* supported */
      if (pl->p[pnr].flags & (POLY_NONFLAT|POLY_CONCAVE)) {
	/* split this polygon along a diagonal, if the polygon is
	 * concave: split across the unique concave vertex.
	 */
	int concave;

	if (pl->p[pnr].flags & POLY_CONCAVE) {
	  Point3 nu;

	  /* We need to determine the concave vertex */
	  PolyNormal(poly, &nu, pl->geomflags & VERT_4D, false, NULL,
		     &concave);
	} else {
	  concave= 0;
	}
	split_quad_poly(concave, poly, plistp, tagged_app, scratch);
      } else {
	new_pn = new_poly_list_node(tagged_app, scratch);
	new_pn->poly = poly;
	ListPush(*plistp, new_pn);
      }
      break;
    default:
      if (pl->p[pnr].flags & (POLY_NONFLAT|POLY_CONCAVE)) {
	static int was_here;
	
	if (!was_here ) {
	  GeomError(1, "Non-flat or concave polygons not supported yet.\n");
	  was_here = 1;
	}
      }
      new_pn = new_poly_list_node(tagged_app, scratch);
      new_pn->poly = poly;
      ListPush(*plistp, new_pn);
      break;
#else
    case 4:
      /* if we want to be able to render polygons with
       * self-intersections "correctly", then we always have to use
       * the GLU tesselater for polygons with more than 4 vertices and
       * for non-convex quadrilaterals. We can handle non-flat
       * quadrilaterals ourselves.
       */
      if ((pl->p[pnr].flags & (POLY_NONFLAT|POLY_CONCAVE)) == POLY_NONFLAT) {
	/* Split this polygon along a diagonal. Leave concave
	 * quadrilaterals to the GLU tesselator; they could have
	 * self-intersections.
	 */
	split_quad_poly(0, poly, plistp, tagged_app, scratch);
      } else if ((pl->p[pnr].flags & POLY_CONCAVE) == 0) {
	new_pn = new_poly_list_node(tagged_app, scratch);
	new_pn->poly = poly;
	ListPush(*plistp, new_pn);
      }
      break;
      /* otherwise fall into the > 4 vertices case and leave
       * everything to the GLU tesselator.
       */
    default: {
      /* We use the GLU tesselator here, if available. It is not
       * necessary to reinvent the wheel; also, the OpenGL MG backend
       * also uses the tesselator (so we will get comparable shapes
       * w/o translucency).
       */
      static GLUtesselator *glutess;
      struct tess_data tessdata[1];
      VARARRAY2(dv, GLdouble, poly->n_vertices, 3);
      Vertex **vp;
      int i;
      
      if (glutess == NULL) {
	glutess = gluNewTess();
	gluTessProperty(glutess,
			GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
	gluTessCallback(glutess, GLU_TESS_BEGIN_DATA,
			(GLvoid (*)())tess_begin_data);
	gluTessCallback(glutess, GLU_TESS_VERTEX_DATA,
			(GLvoid (*)())tess_vertex_data);
	gluTessCallback(glutess, GLU_TESS_COMBINE_DATA,
			(GLvoid (*)())tess_combine_data);
      }

      tessdata->trickyp    = poly;
      tessdata->polyflags  = poly->flags;
      tessdata->pn         = &poly->pn;
      tessdata->scratch    = scratch;
      tessdata->plistp     = plistp;
      tessdata->tagged_app = tagged_app;

      /* tell GLU what we think is a good approximation for the normal */
      gluTessNormal(glutess, poly->pn.x, poly->pn.y, poly->pn.z);

      /* rest is done in the callback functions */
      gluTessBeginPolygon(glutess, tessdata);
      gluTessBeginContour(glutess);
      for (i = 0, vp = poly->v; i < poly->n_vertices; i++, vp++) {
	HPt3Coord w = (*vp)->pt.w ? (*vp)->pt.w : 1e20;

	if (w == 1.0) {
	  dv[i][0] = (*vp)->pt.x;
	  dv[i][1] = (*vp)->pt.y;
	  dv[i][2] = (*vp)->pt.z;
	} else {
	  dv[i][0] = (*vp)->pt.x / w;
	  dv[i][1] = (*vp)->pt.y / w;
	  dv[i][2] = (*vp)->pt.z / w;
	}
	gluTessVertex(glutess, dv[i], *vp);
      }
      gluTessEndContour(glutess);
      gluTessEndPolygon(glutess);
      break; /* out of switch */
    } /* default */
#endif
    } /* switch */
  } /* for */
  return *plistp;
}
void XMGPolygon::SetVertexArray ( const XMGVector3X* src_arr_vertex, const GLuint* arr_idx_hole )
{
	XMGPolygonImpl*	impl = (XMGPolygonImpl *) m_impl;
	XMGRenderImpl*  impl_parent = (XMGRenderImpl *) XMGRender::m_impl;

	XMGTess*		data[2];
	XMGShape*		shape;
	XMGFacet*		facet;
	XMGContour*		contour;

	GLuint			idx_tess;
	GLuint			idx_shape;
	GLuint			idx_facet;
	GLuint			idx_vertex;
	GLuint			idx_vec;
	
	GLuint			num_shape;
	GLuint			num_vertex;
	GLuint			num_vec;

	GLuint			off_vertex;
	GLuint			off_ext;

	XMGVector3X		src_vertex;
	XMGVector3X*	arr_vertex;

	off_vertex = 0;
	off_ext = impl_parent->m_num_vertex;
	impl_parent->m_ext_vertex = 0;
	for ( idx_shape = 0, num_shape = impl_parent->m_vec_shape.size ( ); idx_shape < num_shape; idx_shape++ )
	{
		shape = impl_parent->m_vec_shape[ idx_shape ];
		shape->m_idx_hole = arr_idx_hole ? arr_idx_hole[ idx_shape ] : XMG_HOLE_NULL;

		// Set tess vertices
		if ( impl->m_tess[ 0 ] || impl->m_tess[ 1 ] )
		{
			for ( idx_tess = 0; idx_tess < 2; idx_tess++ )
			{
				if ( impl->m_tess[ idx_tess ] )
				{
					data[ idx_tess ] = impl->m_data[ idx_tess ][ idx_shape ];
					data[ idx_tess ]->Init ( XMG_TESS_VERTEX );

					gluTessBeginPolygon ( impl->m_tess[ idx_tess ], (GLvoid *) data[ idx_tess ] );
					gluTessBeginContour ( impl->m_tess[ idx_tess ] );	
				}
			}

			for ( idx_vertex = 0, num_vertex = shape->m_num_basic; idx_vertex < num_vertex; idx_vertex++ )
			{
				for ( idx_tess = 0; idx_tess < 2; idx_tess++ )
				{
					if ( idx_tess == 0 )
					{
						if ( impl->m_tess[ idx_tess ] )
						{
							src_vertex = src_arr_vertex[ off_vertex + idx_vertex ];
						}
						else
						{
							continue;
						}
					}
					else if ( idx_tess == 1 )
					{
						if ( impl->m_tess[ idx_tess ] )
						{
							switch ( impl_parent->m_geo_type )
							{
								case XMG_GEO_SOLID :

									src_vertex = src_arr_vertex[ off_vertex + num_vertex + idx_vertex ];

									break;

								case XMG_GEO_BSOLID :

									if ( shape->m_idx_hole )
									{
										src_vertex = src_arr_vertex[ idx_vertex < shape->m_idx_hole ? shape->m_idx_hole - idx_vertex - 1 : num_vertex + shape->m_idx_hole - idx_vertex - 1 ];
									}
									else
									{				
										src_vertex = src_arr_vertex[ num_vertex - idx_vertex - 1 ];
									}

									src_vertex.m_z = 0;

									break;
							}							
						}
						else
						{
							continue;
						}
					}

					data[ idx_tess ]->m_arr_vertex[ idx_vertex * 8 + 0 ] = XMG_X2F ( src_vertex.m_x );
					data[ idx_tess ]->m_arr_vertex[ idx_vertex * 8 + 1 ] = XMG_X2F ( src_vertex.m_y );
					data[ idx_tess ]->m_arr_vertex[ idx_vertex * 8 + 2 ] = XMG_X2F ( src_vertex.m_z );	

					if ( shape->m_idx_hole != 0 && shape->m_idx_hole == idx_vertex )
					{
						gluNextContour ( impl->m_tess[ idx_tess ], GLU_INTERIOR );
					}

					gluTessVertex ( impl->m_tess[ idx_tess ], &data[ idx_tess ]->m_arr_vertex[ idx_vertex * 8 ], &data[ idx_tess ]->m_arr_vertex[ idx_vertex * 8 ] );
				}				
			}

			idx_facet = 0;
			for ( idx_tess = 0; idx_tess < 2; idx_tess++ )
			{
				if ( impl->m_tess[ idx_tess ] )
				{
					gluTessEndContour ( impl->m_tess[ idx_tess ] );	
					gluTessEndPolygon ( impl->m_tess[ idx_tess ] );	

					// Set contours with original
					facet = shape->m_vec_facet[ idx_facet ];
					facet->ClearContour ( );

					if ( shape->m_idx_hole == XMG_HOLE_NULL )
					{
						XMGAssert ( contour = new XMGContour ( ) );

						contour->m_draw_limit = XMG_LIMIT_LINE;
						contour->m_off_vertex = facet->m_off_vertex;
						contour->m_num_vertex = facet->m_num_vertex;

						facet->m_vec_contour.push_back ( contour );
					}
					else
					{
						XMGAssert ( contour = new XMGContour ( ) );

						contour->m_draw_limit = XMG_LIMIT_LINE;
						contour->m_off_vertex = facet->m_off_vertex;
						contour->m_num_vertex = shape->m_idx_hole;						
						
						facet->m_vec_contour.push_back ( contour );

						XMGAssert ( contour = new XMGContour ( ) );

						contour->m_draw_limit = XMG_LIMIT_LINE;
						contour->m_off_vertex = facet->m_off_vertex + shape->m_idx_hole;
						contour->m_num_vertex = facet->m_num_vertex - shape->m_idx_hole;
						
						facet->m_vec_contour.push_back ( contour );
					}
					
					// Set contours with tessed
					facet->m_off_ext = off_ext;
					for ( idx_vec = 0, num_vec = data[ idx_tess ]->m_vec_num_vertex.size ( ); idx_vec < num_vec; idx_vec++ )
					{
						XMGAssert ( contour = new XMGContour ( ) );
						
						contour->m_draw_limit = XMG_LIMIT_TRI;
						contour->m_disp_mode  = data[ idx_tess ]->m_vec_mode[ idx_vec ];
						contour->m_off_vertex = off_ext;
						contour->m_num_vertex = data[ idx_tess ]->m_vec_num_vertex[ idx_vec ];	

						facet->m_vec_contour.push_back ( contour );
						off_ext += contour->m_num_vertex;
					}
					
					idx_facet++;
					facet->m_num_ext = data[ idx_tess ]->m_vec_vertex.size ( );
					impl_parent->m_ext_vertex += facet->m_num_ext;
				}
			}
		}

		off_vertex += shape->m_num_input;
	}

	XMGRender::SetVertexArray ( src_arr_vertex, XMG_SHAPE_ALL );

	if ( impl->m_tess[ 0 ] || impl->m_tess[ 1 ] )
	{
		off_vertex = 0;
		num_vertex = impl_parent->m_ext_vertex;
		XMGAssert ( arr_vertex = (XMGVector3X *) kdMalloc ( sizeof ( XMGVector3X ) * num_vertex ) );

		for ( idx_shape = 0, num_shape = impl_parent->m_vec_shape.size ( ); idx_shape < num_shape; idx_shape++ )
		{
			for ( idx_tess = 0; idx_tess < 2; idx_tess++ )
			{
				if ( impl->m_tess[ idx_tess ] )
				{
					data[ idx_tess ] = impl->m_data[ idx_tess ][ idx_shape ];
					for ( idx_vertex = 0, num_vertex = data[ idx_tess ]->m_vec_vertex.size ( ); idx_vertex < num_vertex; idx_vertex++ )
					{
						arr_vertex[ off_vertex ] = data[ idx_tess ]->m_vec_vertex[ idx_vertex ];
						off_vertex++;
					}
					data[ idx_tess ]->ClearVector ( );
				}
			}
		}

		impl_parent->SetBuffer ( impl_parent->m_id_vertex, arr_vertex, sizeof ( XMGVector3X ) * impl_parent->m_num_vertex, sizeof ( XMGVector3X ) * impl_parent->m_ext_vertex );
		kdFree ( arr_vertex );
	}
}
/**
  Convert to TriMesh
 */
void PolyhedronGeom::convert(GeomObject* target)
{
  TriMeshGeom* tm = dynamic_cast<TriMeshGeom*>(target);
  vec3d* vertsptr = verts.dataPtr();
  // Index of the corresponding facevarying (or facevertex) variable
  int facevarindex = 0;
  int i, j;

  // Check if the target geom is really a TriMesh
  if (tm==0)
  {
    throw ENotImplementedError("Conversion not supported by the PolyhedronGeom");
  }

  // No tesselation object allocated yet? Then do so once and for all...
  if (tess==0)
  {
    tess = gluNewTess();
    if (tess==0)
      return;
  }

  PolyTriangulation polyTriangulation(*this);

  // Remove any existing variable in the trimesh...
  tm->deleteAllVariables();

  dataMemManager.setDataSize(3*sizeof(GLdouble)+2*sizeof(int));

  gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (TessCallback)(&onTessBegin_triangulation));
  gluTessCallback(tess, GLU_TESS_END_DATA, (TessCallback)(&onTessEnd_triangulation));
  gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (TessCallback)(&onTessVertex_triangulation));
    
  gluTessProperty(tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE);
  gluTessProperty(tess, GLU_TESS_TOLERANCE, 0);
  gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);

  // Iterate over all polygons...
  for(i=0; i<getNumPolys(); i++)
  {
    dataMemManager.reset();

    gluTessBeginPolygon(tess, &polyTriangulation);
    // Iterate over all loops of polygon i...
    for(j=0; j<getNumLoops(i); j++)
    {
      gluTessBeginContour(tess);
      LoopIterator it = loopBegin(i, j);
      LoopIterator itend = loopEnd(i, j);
      vec3d* v;
      for( ; it!=itend; it++)
      {
	int vidx = (*it);
	v = vertsptr + vidx;
	GLdouble* loc = (GLdouble*)dataMemManager.newDataPtr();
	loc[0] = v->x;
	loc[1] = v->y;
	loc[2] = v->z;
	int* data = (int*)(loc+3);
	data[0] = vidx;  // Vertex index
	data[1] = facevarindex;  // facevarying variable index
	gluTessVertex(tess, loc, data);
	facevarindex++;
      }
      gluTessEndContour(tess);
    }
    gluTessEndPolygon(tess);
    polyTriangulation.polyFinished();
  }

  polyTriangulation.initTriMesh(*tm);

}
Example #19
0
void Boundary::render(bool invert) {
  // Calculate the geometry of the border
  calculate();

  //glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE);

  // Render the border
  glBegin(GL_QUADS);
  for (int i = 0; i < outerEdges.size(); i++) {
    Edge out = outerEdges[i];
    Edge in = innerEdges[i];

    if (!invert) {
      glColor4f(0.0, 0.0, 0.0, 0.0);
    } else {
      glColor4f(1.0, 1.0, 1.0, 1.0);
    }
    glVertex3f(out.a.x, out.a.y, 0.0);
    glVertex3f(out.b.x, out.b.y, 0.0);
    
    if (!invert) {
      glColor4f(1.0, 1.0, 1.0, 1.0);
    } else {
      glColor4f(0.0, 0.0, 0.0, 0.0);
    }
    glVertex3f(in.b.x, in.b.y, 0.0);
    glVertex3f(in.a.x, in.a.y, 0.0);
  }
  glEnd();
  
  // Fill the border
  if (!invert) {
    glColor3f(1.0, 1.0, 1.0);
  } else {
    glColor3f(0.0, 0.0, 0.0);
  }

  GLUtesselator *tess = gluNewTess();

  gluTessCallback(tess, GLU_TESS_BEGIN, (GLvoid (*) ()) &glBegin);
  gluTessCallback(tess, GLU_TESS_END, (GLvoid (*) ()) &glEnd);
  gluTessCallback(tess, GLU_TESS_VERTEX, (GLvoid (*) ()) &glVertex3dv); 
  
  gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);   
  gluTessNormal(tess, 0, 0, 1);

  gluTessBeginPolygon(tess, NULL);
  gluTessBeginContour(tess);

  GLdouble *vertices = new GLdouble[innerEdges.size() * 3];
  for (int i = 0; i < innerEdges.size(); i++) {
    vertices[(i * 3) + 0] = innerEdges[i].a.x;
    vertices[(i * 3) + 1] = innerEdges[i].a.y;
    vertices[(i * 3) + 2] = 0.0;

    gluTessVertex(tess, vertices + (i * 3), vertices + (i * 3));
  }

  gluTessEndContour(tess);
  gluTessEndPolygon(tess);

  delete [] vertices;
  gluDeleteTess(tess);
}
/**
  Draw the polyhedron.
 */
void PolyhedronGeom::drawGL()
{
  // No tesselation object allocated yet? Then do so once and for all...
  if (tess==0)
  {
    tess = gluNewTess();
    if (tess==0)
      return;
  }

  // Set flag to 0 (i.e. no variables are present so far)
  tess_data_flag = 0;
  PrimVarAccess<vec3d> normals(*this, std::string("N"), NORMAL, 1, std::string("Nfaces"));
  PrimVarAccess<double> texcoords(*this, std::string("st"), FLOAT, 2, std::string("stfaces"));
  PrimVarAccess<vec3d> colors(*this, std::string("Cs"), COLOR, 1, std::string("Csfaces"));
  vec3d* N;
  vec3d* Cs;
  GLfloat glcol[4] = {0,0,0,1};
  double* st;
  vec3d* vertsptr = verts.dataPtr();
  int i,j;
  int nfloats=3;

  // Check which variables has to be passed to the vertex callback
  // (this is the case when mode is > 2)
  if (normals.mode>2)
  {
    tess_data_flag |= 0x01;
    nfloats += 3;
  }
  if (texcoords.mode>2)
  {
    tess_data_flag |= 0x02;
    nfloats += 2;
  }
  if (colors.mode>2)
  {
    tess_data_flag |= 0x04;
    nfloats += 3;
  }

  dataMemManager.setDataSize(nfloats*sizeof(GLdouble));

  gluTessCallback(tess, GLU_TESS_BEGIN, (TessCallback)(&onTessBegin));
  gluTessCallback(tess, GLU_TESS_END, (TessCallback)(&onTessEnd));
  gluTessCallback(tess, GLU_TESS_VERTEX, (TessCallback)(&onTessVertex));
    
  gluTessProperty(tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE);
  gluTessProperty(tess, GLU_TESS_TOLERANCE, 0);
  gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);

  // Iterate over all polygons...
  for(i=0; i<getNumPolys(); i++)
  {
    dataMemManager.reset();

    // No normals? Then a face normal has to be calculated...
    if (normals.mode==0)
    {
      vec3d Ng;
      computeNormal(i, Ng);
      glNormal3d(Ng.x, Ng.y, Ng.z);      
    }

    // Process uniform variables...
    if (normals.onFace(N))
      glNormal3d(N->x, N->y, N->z);
    if (texcoords.onFace(st))
      glTexCoord2dv(st);
    if (colors.onFace(Cs))
    {
      glcol[0] = GLfloat(Cs->x);
      glcol[1] = GLfloat(Cs->y);
      glcol[2] = GLfloat(Cs->z);
      glMaterialfv(GL_FRONT, GL_DIFFUSE, glcol);
    }

    gluTessBeginPolygon(tess, 0);
    // Iterate over all loops of polygon i...
    for(j=0; j<getNumLoops(i); j++)
    {
      gluTessBeginContour(tess);
      LoopIterator it = loopBegin(i, j);
      LoopIterator itend = loopEnd(i, j);
      vec3d* v;
      for( ; it!=itend; it++)
      {
	int vidx = (*it);
	v = vertsptr + vidx;
	GLdouble* data = (GLdouble*)dataMemManager.newDataPtr();
	GLdouble* p = data+3;
	data[0] = v->x;
	data[1] = v->y;
	data[2] = v->z;
	if (normals.onVertex(vidx, N))
	{
	  p[0] = N->x;
	  p[1] = N->y;
	  p[2] = N->z;
	  p += 3;
	}
	if (texcoords.onVertex(vidx, st))
	{
	  p[0] = st[0];
	  p[1] = st[1];
	  p += 2;
	}
	if (colors.onVertex(vidx, Cs))
	{
	  p[0] = Cs->x;
	  p[1] = Cs->y;
	  p[2] = Cs->z;
	}
	gluTessVertex(tess, data, data);
      }
      gluTessEndContour(tess);
    }
    gluTessEndPolygon(tess);
  }

  /*  for(i=0; i<getNumPolys(); i++)
  {
    for(j=0; j<getNumLoops(i); j++)
    {
      LoopIterator it = loopBegin(i, j);
      LoopIterator itend = loopEnd(i, j);
      vec3d* v;
      glBegin(GL_LINE_LOOP);
      for( ; it!=itend; it++)
      {
	v = vertsptr + (*it);
	glVertex3d(v->x, v->y, v->z);
      }
      glEnd();
    }
    }*/
}
Example #21
0
void FTVectoriser::MakeMesh(FTGL_DOUBLE zNormal, int outsetType, float outsetSize)
{
    if(mesh)
    {
        delete mesh;
    }

    mesh = new FTMesh;

    GLUtesselator* tobj = gluNewTess();

    gluTessCallback(tobj, GLU_TESS_BEGIN_DATA,     (GLUTesselatorFunction)ftglBegin);
    gluTessCallback(tobj, GLU_TESS_VERTEX_DATA,    (GLUTesselatorFunction)ftglVertex);
    gluTessCallback(tobj, GLU_TESS_COMBINE_DATA,   (GLUTesselatorFunction)ftglCombine);
    gluTessCallback(tobj, GLU_TESS_END_DATA,       (GLUTesselatorFunction)ftglEnd);
    gluTessCallback(tobj, GLU_TESS_ERROR_DATA,     (GLUTesselatorFunction)ftglError);

    if(contourFlag & ft_outline_even_odd_fill) // ft_outline_reverse_fill
    {
        gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
    }
    else
    {
        gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
    }


    gluTessProperty(tobj, GLU_TESS_TOLERANCE, 0);
    gluTessNormal(tobj, 0.0f, 0.0f, zNormal);
    gluTessBeginPolygon(tobj, mesh);

        for(size_t c = 0; c < ContourCount(); ++c)
        {
            /* Build the */
            switch(outsetType)
            {
                case 1 : contourList[c]->buildFrontOutset(outsetSize); break;
                case 2 : contourList[c]->buildBackOutset(outsetSize); break;
            }
            const FTContour* contour = contourList[c];


            gluTessBeginContour(tobj);
                for(size_t p = 0; p < contour->PointCount(); ++p)
                {
                    const FTGL_DOUBLE* d;
                    switch(outsetType)
                    {
                        case 1: d = contour->FrontPoint(p); break;
                        case 2: d = contour->BackPoint(p); break;
                        case 0: default: d = contour->Point(p); break;
                    }
                    // XXX: gluTessVertex doesn't modify the data but does not
                    // specify "const" in its prototype, so we cannot cast to
                    // a const type.
                    gluTessVertex(tobj, (GLdouble *)d, (GLvoid *)d);
                }

            gluTessEndContour(tobj);
        }
    gluTessEndPolygon(tobj);

    gluDeleteTess(tobj);
}
void Playback3D::do_mask_sync(Playback3DCommand *command)
{
#ifdef HAVE_GL
	command->canvas->lock_canvas("Playback3D::do_mask_sync");
	if(command->canvas->get_canvas())
	{
		BC_WindowBase *window = command->canvas->get_canvas();
		window->lock_window("Playback3D::do_mask_sync");
		window->enable_opengl();
		
		switch(command->frame->get_opengl_state())
		{
			case VFrame::RAM:
// Time to upload to the texture
				command->frame->to_texture();
				break;

			case VFrame::SCREEN:
// Read back from PBuffer
// Bind context to pbuffer
				command->frame->enable_opengl();
				command->frame->screen_to_texture();
				break;
		}



// Create PBuffer and draw the mask on it
		command->frame->enable_opengl();

// Initialize coordinate system
		int w = command->frame->get_w();
		int h = command->frame->get_h();
		command->frame->init_screen();
		int value = command->keyframe_set->get_value(command->start_position_project,
			PLAY_FORWARD);
		float feather = command->keyframe_set->get_feather(command->start_position_project,
			PLAY_FORWARD);

// Clear screen
		glDisable(GL_TEXTURE_2D);
		if(command->default_auto->mode == MASK_MULTIPLY_ALPHA)
		{
			glClearColor(0.0, 0.0, 0.0, 0.0);
			glColor4f((float)value / 100, 
				(float)value / 100, 
				(float)value / 100, 
				1.0);
		}
		else
		{
			glClearColor(1.0, 1.0, 1.0, 1.0);
			glColor4f((float)1.0 - (float)value / 100, 
				(float)1.0 - (float)value / 100, 
				(float)1.0 - (float)value / 100, 
				1.0);
		}
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		
// Draw mask with scaling to simulate feathering
		GLUtesselator *tesselator = gluNewTess();
		gluTessProperty(tesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
		gluTessCallback(tesselator, GLU_TESS_VERTEX, (GLvoid (*) ( )) &glVertex3dv);
		gluTessCallback(tesselator, GLU_TESS_BEGIN, (GLvoid (*) ( )) &glBegin);
		gluTessCallback(tesselator, GLU_TESS_END, (GLvoid (*) ( )) &glEnd);
		gluTessCallback(tesselator, GLU_TESS_COMBINE, (GLvoid (*) ( ))&combine_callback);


// Draw every submask as a new polygon
		int total_submasks = command->keyframe_set->total_submasks(
			command->start_position_project, 
			PLAY_FORWARD);
		float scale = feather + 1;
 		int display_list = glGenLists(1);
 		glNewList(display_list, GL_COMPILE);
		for(int k = 0; k < total_submasks; k++)
		{
			gluTessBeginPolygon(tesselator, NULL);
			gluTessBeginContour(tesselator);
			ArrayList<MaskPoint*> *points = new ArrayList<MaskPoint*>;
			command->keyframe_set->get_points(points, 
				k, 
				command->start_position_project, 
				PLAY_FORWARD);

			int first_point = 0;
// Need to tabulate every vertex in persistent memory because
// gluTessVertex doesn't copy them.
			ArrayList<GLdouble*> coords;
			for(int i = 0; i < points->total; i++)
			{
				MaskPoint *point1 = points->values[i];
				MaskPoint *point2 = (i >= points->total - 1) ? 
					points->values[0] : 
					points->values[i + 1];


// This is very slow.
				float x, y;
				int segments = (int)(sqrt(SQR(point1->x - point2->x) + SQR(point1->y - point2->y)));
				if(point1->control_x2 == 0 &&
					point1->control_y2 == 0 &&
					point2->control_x1 == 0 &&
					point2->control_y1 == 0)
					segments = 1;

				float x0 = point1->x;
				float y0 = point1->y;
				float x1 = point1->x + point1->control_x2;
				float y1 = point1->y + point1->control_y2;
				float x2 = point2->x + point2->control_x1;
				float y2 = point2->y + point2->control_y1;
				float x3 = point2->x;
				float y3 = point2->y;

				for(int j = 0; j <= segments; j++)
				{
					float t = (float)j / segments;
					float tpow2 = t * t;
					float tpow3 = t * t * t;
					float invt = 1 - t;
					float invtpow2 = invt * invt;
					float invtpow3 = invt * invt * invt;

					x = (        invtpow3 * x0
						+ 3 * t     * invtpow2 * x1
						+ 3 * tpow2 * invt     * x2 
						+     tpow3            * x3);
					y = (        invtpow3 * y0 
						+ 3 * t     * invtpow2 * y1
						+ 3 * tpow2 * invt     * y2 
						+     tpow3            * y3);


					if(j > 0 || first_point)
					{
						GLdouble *coord = new GLdouble[3];
						coord[0] = x / scale;
						coord[1] = -h + y / scale;
						coord[2] = 0;
						coords.append(coord);
						first_point = 0;
					}
				}
			}

// Now that we know the total vertices, send them to GLU
			for(int i = 0; i < coords.total; i++)
				gluTessVertex(tesselator, coords.values[i], coords.values[i]);

			gluTessEndContour(tesselator);
			gluTessEndPolygon(tesselator);
			points->remove_all_objects();
			delete points;
			coords.remove_all_objects();
		}
		glEndList();
 		glCallList(display_list);
 		glDeleteLists(display_list, 1);

		glColor4f(1, 1, 1, 1);


// Read mask into temporary texture.
// For feathering, just read the part of the screen after the downscaling.


		float w_scaled = w / scale;
		float h_scaled = h / scale;
// Don't vary the texture size according to scaling because that 
// would waste memory.
// This enables and binds the temporary texture.
		glActiveTexture(GL_TEXTURE1);
		BC_Texture::new_texture(&temp_texture,
			w, 
			h, 
			command->frame->get_color_model());
		temp_texture->bind(1);
		glReadBuffer(GL_BACK);

// Need to add extra size to fill in the bottom right
		glCopyTexSubImage2D(GL_TEXTURE_2D,
			0,
			0,
			0,
			0,
			0,
			(int)MIN(w_scaled + 2, w),
			(int)MIN(h_scaled + 2, h));

		command->frame->bind_texture(0);


// For feathered masks, use a shader to multiply.
// For unfeathered masks, we could use a stencil buffer 
// for further optimization but we also need a YUV algorithm.
		unsigned int frag_shader = 0;
		switch(temp_texture->get_texture_components())
		{
			case 3: 
				if(command->frame->get_color_model() == BC_YUV888)
					frag_shader = VFrame::make_shader(0,
						multiply_yuvmask3_frag,
						0);
				else
					frag_shader = VFrame::make_shader(0,
						multiply_mask3_frag,
						0);
				break;
			case 4: 
				frag_shader = VFrame::make_shader(0,
					multiply_mask4_frag,
					0);
				break;
		}

		if(frag_shader)
		{
			int variable;
			glUseProgram(frag_shader);
			if((variable = glGetUniformLocation(frag_shader, "tex")) >= 0)
				glUniform1i(variable, 0);
			if((variable = glGetUniformLocation(frag_shader, "tex1")) >= 0)
				glUniform1i(variable, 1);
			if((variable = glGetUniformLocation(frag_shader, "scale")) >= 0)
				glUniform1f(variable, scale);
		}



// Write texture to PBuffer with multiply and scaling for feather.

		
		command->frame->draw_texture(0, 0, w, h, 0, 0, w, h);
		command->frame->set_opengl_state(VFrame::SCREEN);


// Disable temp texture
		glUseProgram(0);

		glActiveTexture(GL_TEXTURE1);
		glDisable(GL_TEXTURE_2D);
		delete temp_texture;
		temp_texture = 0;

		glActiveTexture(GL_TEXTURE0);
		glDisable(GL_TEXTURE_2D);

// Default drawable
		window->enable_opengl();
		window->unlock_window();
	}
	command->canvas->unlock_canvas();
#endif
}
//----------------------------------------------------------
ofVboMesh ofTessellator::tessellate( const ofPolyline& polyline, bool bIs2D ){

	mutex.lock();
	
	clear();
	resultMesh = ofVboMesh();
//	resultMesh.clear();
	
	// now get the tesselator object up and ready:
	GLUtesselator * ofShapeTobj = gluNewTess();
	
#if defined( TARGET_OSX)
#ifndef MAC_OS_X_VERSION_10_5
#define OF_NEED_GLU_FIX
#endif
#endif
	
	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	// MAC - XCODE USERS PLEASE NOTE - some machines will not be able to compile the code below
	// if this happens uncomment the "OF_NEED_GLU_FIX" line below and it
	// should compile also please post to the forums with the error message, you OS X version,
	// Xcode verison and the CPU type - PPC or Intel. Thanks!
	// (note: this is known problem based on different version of glu.h, we are working on a fix)
	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	
	//#define OF_NEED_GLU_FIX
	
#ifdef OF_NEED_GLU_FIX
#define OF_GLU_CALLBACK_HACK (void(CALLBACK*)(...))
#else
#define OF_GLU_CALLBACK_HACK (void(CALLBACK*)())
#endif
	gluTessCallback( ofShapeTobj, GLU_TESS_BEGIN, OF_GLU_CALLBACK_HACK &ofTessellator::begin);
	gluTessCallback( ofShapeTobj, GLU_TESS_VERTEX, OF_GLU_CALLBACK_HACK &ofTessellator::vertex);
	gluTessCallback( ofShapeTobj, GLU_TESS_COMBINE, OF_GLU_CALLBACK_HACK &ofTessellator::combine);
	gluTessCallback( ofShapeTobj, GLU_TESS_END, OF_GLU_CALLBACK_HACK &ofTessellator::end);
	gluTessCallback( ofShapeTobj, GLU_TESS_ERROR, OF_GLU_CALLBACK_HACK &ofTessellator::error);
	
	gluTessProperty( ofShapeTobj, GLU_TESS_WINDING_RULE, ofGetStyle().polyMode);
	if (!ofGetStyle().bFill){
		gluTessProperty( ofShapeTobj, GLU_TESS_BOUNDARY_ONLY, true);
	} else {
		gluTessProperty( ofShapeTobj, GLU_TESS_BOUNDARY_ONLY, false);
	}
	gluTessProperty( ofShapeTobj, GLU_TESS_TOLERANCE, 0);
	
	/* ------------------------------------------
	 for 2d, this next call (normal) likely helps speed up ....
	 quote : The computation of the normal represents about 10% of
	 the computation time. For example, if all polygons lie in
	 the x-y plane, you can provide the normal by using the
	 -------------------------------------------  */
	if( bIs2D) 
		gluTessNormal(ofShapeTobj, 0.0, 0.0, 1.0);

	gluTessBeginPolygon( ofShapeTobj, NULL);
	
	for ( int i=0; i<polyline.size(); i++ ) {
		double* point = new double[3];
		point[0] = polyline[i].x;
		point[1] = polyline[i].y;
		point[2] = polyline[i].z;
		ofShapePolyVertexs.push_back(point);
	}

	gluTessBeginContour( ofShapeTobj );
	
	for (int i=0; i<(int)ofShapePolyVertexs.size(); i++) {
		gluTessVertex( ofShapeTobj, ofShapePolyVertexs[i], ofShapePolyVertexs[i]);
	}
	
	gluTessEndContour( ofShapeTobj );

	
	
	// no matter what we did / do, we need to delete the tesselator object
	gluTessEndPolygon( ofShapeTobj);
	gluDeleteTess( ofShapeTobj);
	ofShapeTobj = NULL;
	
   	// now clear the vertices on the dynamically allocated data
   	clear();

	mutex.unlock();
	
	return resultMesh;
	
}
Example #24
0
static void
_cogl_path_build_fill_attribute_buffer (CoglPath *path)
{
  CoglPathTesselator tess;
  unsigned int path_start = 0;
  CoglPathData *data = path->data;
  int i;

  /* If we've already got a vbo then we don't need to do anything */
  if (data->fill_attribute_buffer)
    return;

  tess.primitive_type = FALSE;

  /* Generate a vertex for each point on the path */
  tess.vertices = g_array_new (FALSE, FALSE, sizeof (CoglPathTesselatorVertex));
  g_array_set_size (tess.vertices, data->path_nodes->len);
  for (i = 0; i < data->path_nodes->len; i++)
    {
      CoglPathNode *node =
        &g_array_index (data->path_nodes, CoglPathNode, i);
      CoglPathTesselatorVertex *vertex =
        &g_array_index (tess.vertices, CoglPathTesselatorVertex, i);

      vertex->x = node->x;
      vertex->y = node->y;

      /* Add texture coordinates so that a texture would be drawn to
         fit the bounding box of the path and then cropped by the
         path */
      if (data->path_nodes_min.x == data->path_nodes_max.x)
        vertex->s = 0.0f;
      else
        vertex->s = ((node->x - data->path_nodes_min.x)
                     / (data->path_nodes_max.x - data->path_nodes_min.x));
      if (data->path_nodes_min.y == data->path_nodes_max.y)
        vertex->t = 0.0f;
      else
        vertex->t = ((node->y - data->path_nodes_min.y)
                     / (data->path_nodes_max.y - data->path_nodes_min.y));
    }

  tess.indices_type =
    _cogl_path_tesselator_get_indices_type_for_size (data->path_nodes->len);
  _cogl_path_tesselator_allocate_indices_array (&tess);

  tess.glu_tess = gluNewTess ();

  if (data->fill_rule == COGL_PATH_FILL_RULE_EVEN_ODD)
    gluTessProperty (tess.glu_tess, GLU_TESS_WINDING_RULE,
                     GLU_TESS_WINDING_ODD);
  else
    gluTessProperty (tess.glu_tess, GLU_TESS_WINDING_RULE,
                     GLU_TESS_WINDING_NONZERO);

  /* All vertices are on the xy-plane */
  gluTessNormal (tess.glu_tess, 0.0, 0.0, 1.0);

  gluTessCallback (tess.glu_tess, GLU_TESS_BEGIN_DATA,
                   _cogl_path_tesselator_begin);
  gluTessCallback (tess.glu_tess, GLU_TESS_VERTEX_DATA,
                   _cogl_path_tesselator_vertex);
  gluTessCallback (tess.glu_tess, GLU_TESS_END_DATA,
                   _cogl_path_tesselator_end);
  gluTessCallback (tess.glu_tess, GLU_TESS_COMBINE_DATA,
                   _cogl_path_tesselator_combine);

  gluTessBeginPolygon (tess.glu_tess, &tess);

  while (path_start < data->path_nodes->len)
    {
      CoglPathNode *node =
        &g_array_index (data->path_nodes, CoglPathNode, path_start);

      gluTessBeginContour (tess.glu_tess);

      for (i = 0; i < node->path_size; i++)
        {
          double vertex[3] = { node[i].x, node[i].y, 0.0 };
          gluTessVertex (tess.glu_tess, vertex,
                         GINT_TO_POINTER (i + path_start));
        }

      gluTessEndContour (tess.glu_tess);

      path_start += node->path_size;
    }

  gluTessEndPolygon (tess.glu_tess);

  gluDeleteTess (tess.glu_tess);

  data->fill_attribute_buffer =
    cogl_attribute_buffer_new (data->context,
                               sizeof (CoglPathTesselatorVertex) *
                               tess.vertices->len,
                               tess.vertices->data);
  g_array_free (tess.vertices, TRUE);

  data->fill_attributes[0] =
    cogl_attribute_new (data->fill_attribute_buffer,
                        "cogl_position_in",
                        sizeof (CoglPathTesselatorVertex),
                        G_STRUCT_OFFSET (CoglPathTesselatorVertex, x),
                        2, /* n_components */
                        COGL_ATTRIBUTE_TYPE_FLOAT);
  data->fill_attributes[1] =
    cogl_attribute_new (data->fill_attribute_buffer,
                        "cogl_tex_coord0_in",
                        sizeof (CoglPathTesselatorVertex),
                        G_STRUCT_OFFSET (CoglPathTesselatorVertex, s),
                        2, /* n_components */
                        COGL_ATTRIBUTE_TYPE_FLOAT);

  data->fill_vbo_indices = cogl_indices_new (data->context,
                                             tess.indices_type,
                                             tess.indices->data,
                                             tess.indices->len);
  data->fill_vbo_n_indices = tess.indices->len;
  g_array_free (tess.indices, TRUE);
}
Example #25
0
void CMFCTessView::OnDraw(CDC* pDC)
{
	CMFCTessDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

	//some per-drawing init stuff
	glLoadIdentity();

	//setup drawing dimensions, etc
	CPoint vptorg = m_pDC->GetViewportOrg() ; //note m_pDC, NOT pDC
	CRect rect ;
	GetWindowRect( &rect ) ;
	int dx = rect.Width() ;
	int dy = rect.Height() ;
	glViewport( 0, 0, dx, dy );

	glMatrixMode( GL_MODELVIEW );
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	
	// create bitmaps for the device context font's first 256 glyphs 
	HDC hdc = m_pDC->GetSafeHdc() ;
	wglUseFontBitmaps(hdc, 0, 256, 1000); 
	glListBase(1000);

	float R ;
	if( pDoc->m_ContourList.GetCount() > 0 )
	{
		CalculateExtents() ; // Collect overall figure extents (in meters)
		R = Radius ;

		//11/29/03 experiment to eliminate probs w/non-square windows
		float glleft = -R ;
		float gltop = +R ;
		float nearplane = -R ; //rev 07/25/03
		float farplane = R ; //rev 07/25/03

		float glleft2 = glleft ;
		float gltop2 = gltop ;
		float glright2 = ( glleft + 2*R ) ;
		float glbottom2 = ( gltop - 2*R ) ;

		//adjust for non-square viewing window
		float dxdy = (float)dx/(float)dy ;  //=1.00 for square window
		if( dxdy > 1 )
		{
			glOrtho( glleft2*dxdy , glright2*dxdy, glbottom2, gltop2, nearplane, farplane ) ;
		}
		else
		{
			glOrtho( glleft2 , glright2, glbottom2/dxdy, gltop2/dxdy, nearplane, farplane ) ;
		}
		
		glTranslatef( -m_Center.x, -m_Center.y, -m_Center.z ) ;
	}
	else
	{  
		CString txtstr ;
		glOrtho( -1.f , 1.f, -1.f, 1.f, -1.f, 1.f ) ;
		glTranslatef( 0.f, 0.f, 0.f ) ;
		txtstr = "Nothing to draw" ;
		glColor3f( 0.f, 0.f, 0.f ) ;
		glRasterPos3f(0.0F, 0.0F, 0.0F ); 
		glCallLists(txtstr.GetLength(), GL_UNSIGNED_BYTE, txtstr); 

		//clean up & exit
		glFlush(); 
		glDeleteLists(1000, 256) ; 
		SwapBuffers( m_pDC->GetSafeHdc() );
		return ;
	}

	glPushMatrix() ;

	//01/09/05 implement tessellation
	GLUtesselator *tobj;
	tobj = gluNewTess();

	//added 02/09/05 as part of mem leak fix
	while( gm_VertexPtrList.GetCount() > 0 )
	{
		GLdouble* pV = (GLdouble*)gm_VertexPtrList.RemoveHead() ;
		delete[] pV ;
		pV = NULL ;
	}

	gluTessCallback(tobj, GLU_TESS_BEGIN, (void (CALLBACK *) ())beginCallback);
	gluTessCallback(tobj, GLU_TESS_VERTEX, (void (CALLBACK *) ()) vertexCallback);
	gluTessCallback(tobj, GLU_TESS_END, (void (CALLBACK *) ())endCallback);
	gluTessCallback(tobj, GLU_TESS_ERROR,(void (CALLBACK *) ())errorCallback);
	gluTessCallback(tobj, GLU_TESS_COMBINE, (void (CALLBACK *) ())combineCallback);

	glShadeModel(GL_SMOOTH);    
	gluTessProperty(tobj, GLU_TESS_WINDING_RULE,
               m_WindingRule );

	//only one polygon, but multiple contours
	gluTessBeginPolygon(tobj, NULL);


	POSITION pos = pDoc->m_ContourList.GetHeadPosition() ;
	while ( pos ) 
	{
		CContour* pCtr = (CContour*)pDoc->m_ContourList.GetNext( pos ) ;
		ASSERT( pCtr != NULL && pCtr->m_NumVertex > 0 && pCtr->m_ppVertexArray != NULL ) ;
		int numcorners = pCtr->m_NumVertex ;

		gluTessBeginContour(tobj);

		for( int cnridx = 0; cnridx < numcorners; cnridx++ )
		{
			GLdouble* glvert = pCtr->m_ppVertexArray[cnridx];
			gluTessVertex( tobj, glvert, glvert ) ;
		   TRACE( "Draw: Sent vertex(%f,%f,%f,%f,%f,%f)\n", glvert[0],glvert[1],glvert[2],glvert[3],glvert[4],glvert[5] ) ;
		}

		gluTessEndContour(tobj);
		
	} //end of all contour definitions

		gluTessEndPolygon(tobj);

	//clean up & exit
	glFlush(); 
	glDeleteLists(1000, 256) ; // delete our 256 glyph display lists 
	SwapBuffers( m_pDC->GetSafeHdc() );
	gluDeleteTess( tobj ) ;

	//added 02/09/05 as part of mem leak fix
	while( gm_VertexPtrList.GetCount() > 0 )
	{
		GLdouble* pV = (GLdouble*)gm_VertexPtrList.RemoveHead() ;
		delete[] pV ;
		pV = NULL ;
	}
}
  void MapPainterOpenGL::DrawArea(const Projection& projection,
                                  const MapParameter& /*parameter*/,
                                  const MapPainter::AreaData& area)
  {
    if (area.fillStyle->GetFillColor().IsVisible()) {
      glColor4d(area.fillStyle->GetFillColor().GetR(),
                area.fillStyle->GetFillColor().GetG(),
                area.fillStyle->GetFillColor().GetB(),
                area.fillStyle->GetFillColor().GetA());

      gluTessProperty(tesselator,
                      GLU_TESS_BOUNDARY_ONLY,
                      GL_FALSE);

      gluTessBeginPolygon(tesselator,
                          NULL);

      gluTessBeginContour(tesselator);

      for (size_t i=area.transStart; i<=area.transEnd; i++) {

        gluTessVertex(tesselator,
                      (GLdouble*)&coordBuffer->buffer[i],
                      (GLdouble*)&coordBuffer->buffer[i]);
      }

      gluTessEndContour(tesselator);

      if (!area.clippings.empty()) {
        // Clip areas within the area by using CAIRO_FILL_RULE_EVEN_ODD
        for (std::list<PolyData>::const_iterator c=area.clippings.begin();
            c!=area.clippings.end();
            c++) {
          const PolyData& data=*c;

          gluTessBeginContour(tesselator);

          for (size_t i=data.transStart; i<=data.transEnd; i++) {
            gluTessVertex(tesselator,
                          (GLdouble*)&coordBuffer->buffer[i],
                          (GLdouble*)&coordBuffer->buffer[i]);
          }

          gluTessEndContour(tesselator);
        }
      }

      gluTessEndPolygon(tesselator);
    }

    if (area.fillStyle->GetBorderWidth()>0 &&
        area.fillStyle->GetBorderColor().IsVisible()) {
      double borderWidth=projection.ConvertWidthToPixel(area.fillStyle->GetBorderWidth());

      glColor4d(area.fillStyle->GetBorderColor().GetR(),
                area.fillStyle->GetBorderColor().GetG(),
                area.fillStyle->GetBorderColor().GetB(),
                area.fillStyle->GetBorderColor().GetA());

      glLineWidth(borderWidth);

      glBegin(GL_LINE_LOOP);

      for (size_t i=area.transStart; i<=area.transEnd; i++) {
        glVertex3d(coordBuffer->buffer[i].GetX(),
                   coordBuffer->buffer[i].GetY(),
                   0.0);
      }

      glEnd();
    }
  }
Example #27
0
//      Build PolyTessGeo Object from OGR Polygon
//      Using OpenGL/GLU tesselator
int PolyTessGeo::BuildTessGLU()
{
    
    unsigned int iir, ip;
    GLdouble *geoPt;


#if 0    
    //  Make a quick sanity check of the polygon coherence
    bool b_ok = true;
    OGRLineString *tls = poly->getExteriorRing();
    if(!tls) {
        b_ok = false;
    }
    else {
        int tnpta  = poly->getExteriorRing()->getNumPoints();
        if(tnpta < 3 )
            b_ok = false;
    }

    
    for( iir=0 ; iir < poly->getNumInteriorRings() ; iir++)
    {
        int tnptr = poly->getInteriorRing(iir)->getNumPoints();
        if( tnptr < 3 )
            b_ok = false;
    }
    
    if( !b_ok )
        return ERROR_BAD_OGRPOLY;
    
#endif
    


    //  Allocate a work buffer, which will be grown as needed
#define NINIT_BUFFER_LEN 10000
    m_pwork_buf = (GLdouble *)malloc(NINIT_BUFFER_LEN * 2 * sizeof(GLdouble));
    m_buf_len = NINIT_BUFFER_LEN * 2;
    m_buf_idx = 0;

      //    Create an array to hold pointers to allocated vertices created by "combine" callback,
      //    so that they may be deleted after tesselation.
    m_pCombineVertexArray = new wxArrayPtrVoid;

    //  Create tesselator
    GLUtessobj = gluNewTess();

    //  Register the callbacks
    gluTessCallback(GLUtessobj, GLU_TESS_BEGIN_DATA,   (GLvoid (*) ())&beginCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_BEGIN_DATA,   (GLvoid (*) ())&beginCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_VERTEX_DATA,  (GLvoid (*) ())&vertexCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_END_DATA,     (GLvoid (*) ())&endCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_COMBINE_DATA, (GLvoid (*) ())&combineCallback);
    gluTessCallback(GLUtessobj, GLU_TESS_ERROR_DATA,   (GLvoid (*) ())&errorCallback);

    gluTessProperty(GLUtessobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
    gluTessNormal(GLUtessobj, 0, 0, 1);

//      Get total number of points(vertices)  to build a buffer
    int npta  = 0;

    for( int i=0 ; i < m_ncnt ; i++)
        npta += m_cntr[i];


    geoPt = (GLdouble *)malloc((npta + 6) * 3 * sizeof(GLdouble));     // vertex array



   //  Grow the work buffer if necessary

    if((npta * 4) > m_buf_len)
    {
        m_pwork_buf = (GLdouble *)realloc(m_pwork_buf, npta * 4 * sizeof(GLdouble));
        m_buf_len = npta * 4;
    }


//  Define the polygon
    gluTessBeginPolygon(GLUtessobj, this);


    
    //  Check and account for winding direction of ring


      double x0, y0, x, y;
//      OGRPoint p;

      wxPoint2DDouble *pp = (wxPoint2DDouble *)m_vertexPtrArray[0];
      bool cw = !isRingClockwise(pp, m_cntr[0]);
      
      //pp++;       // skip 0?

      if(cw)
      {
            x0 = pp->m_x;
            y0 = pp->m_y;
      }
      else
      {
            x0 = pp[m_cntr[0]-1].m_x;
            y0 = pp[m_cntr[0]-1].m_y;
      }



      unsigned int ptValid = m_cntr[0];
      
//  Transcribe points to vertex array, in proper order with no duplicates
//   also, accounting for tess_orient
      GLdouble *ppt = geoPt;
      
      for(ip = 0 ; ip < (unsigned int)m_cntr[0] ; ip++)
      {
            int pidx;
            if(cw)
                  pidx = m_cntr[0] - ip - 1;

            else
                  pidx = ip;

            x = pp[pidx].m_x;
            y = pp[pidx].m_y;

            if((fabs(x-x0) > EQUAL_EPS) || (fabs(y-y0) > EQUAL_EPS))
            {
                  if(m_tess_orient == TESS_VERT)
                  {
                        *ppt++ = x;
                        *ppt++ = y;
                        *ppt++ = 0;
                  }
                  else
                  {
                        *ppt++ = y;
                        *ppt++ = x;
                        *ppt++ = 0;
                  }
            }
            else
                  ptValid--;

            x0 = x;
            y0 = y;
      }

      //  Apply LOD reduction
    int beforeLOD = ptValid;
    int afterLOD = beforeLOD;
   
 
    if(ptValid > 20 && (m_LOD_meters > .01)) {
        std::vector<bool> bool_keep(ptValid, false);

        // Keep a few key points
        bool_keep[0] = true;
        bool_keep[1] = true;
        bool_keep[ptValid-1] = true;
        bool_keep[ptValid-2] = true;
        
        DouglasPeuckerDI(geoPt, 1, ptValid-2, m_LOD_meters, bool_keep);
            
        // Create a new buffer
        double *LOD_result = (double *)malloc((m_cntr[0]) * 3 * sizeof(double));     
        double *plod = LOD_result;
        int kept_LOD =0;
        
        for(unsigned int i=0 ; i < ptValid ; i++){
            if(bool_keep[i]){
                double x = geoPt[i*3];
                double y = geoPt[(i*3) + 1];
                *plod++ = x;
                *plod++ = y;
                *plod++ = 0;
                kept_LOD++;
            }
        }

        beforeLOD = ptValid;
        afterLOD = kept_LOD;

        // Copy the lod points back into the vertex buffer
        memcpy(geoPt, LOD_result, kept_LOD * 3 * sizeof(double));
        
        free(LOD_result);
        ptValid = kept_LOD;
    }

    //  Declare the gluContour and copy the points
    gluTessBeginContour(GLUtessobj);
    
    double *DPrun = geoPt;
    for(ip = 0 ; ip < ptValid ; ip++) {
        gluTessVertex( GLUtessobj, DPrun, DPrun ) ;
        DPrun += 3;
    }
  
    gluTessEndContour(GLUtessobj);

    //  Now the interior contours
#if 1    
    int gpIndex = m_cntr[0];
    
    for(iir=0; iir < (unsigned int)m_ncnt-1; iir++){
        
            wxPoint2DDouble *pp = (wxPoint2DDouble *)m_vertexPtrArray[iir + 1];

            int npti  = m_cntr[iir+1];
            ptValid = npti;
            
            double *ppt = &geoPt[gpIndex * 3]; // next available location in geoPT
            double *DPStart = ppt;
            
      //  Check and account for winding direction of ring
            bool cw = isRingClockwise(pp, m_cntr[iir+1]);

            if(cw)
            {
                  x0 = pp[0].m_x;
                  y0 = pp[0].m_y;
            }
            else
            {
                  x0 = pp[npti-1].m_x;
                  y0 = pp[npti-1].m_y;
            }

//  Transcribe points to vertex array, in proper order with no duplicates
//   also, accounting for tess_orient
            for(int ip = 0 ; ip < npti ; ip++)
            {
                  int pidx;
                  if(cw)                               // interior contours must be cw
                        pidx = npti - ip - 1;
                  else
                        pidx = ip;


                  x = pp[pidx].m_x;
                  y = pp[pidx].m_y;

                  if((fabs(x-x0) > EQUAL_EPS) || (fabs(y-y0) > EQUAL_EPS))
                  {
                        if(m_tess_orient == TESS_VERT)
                        {
                              *ppt++ = x;
                              *ppt++ = y;
                              *ppt++ = 0;
                        }
                        else
                        {
                              *ppt++ = y;
                              *ppt++ = x;
                              *ppt++ = 0;
                        }
                  }
                  else
                        ptValid--;

                  x0 = x;
                  y0 = y;

            }
            
                       //  Declare the gluContour and reference the points
            gluTessBeginContour(GLUtessobj);
    
            double *DPruni = DPStart;
            for(ip = 0 ; ip < ptValid ; ip++)
            {
                gluTessVertex( GLUtessobj, DPruni, DPruni ) ;
                DPruni += 3;
            }
        
            gluTessEndContour(GLUtessobj);

            gpIndex +=  m_cntr[iir+1];
      }
#endif
        
        
        
        

    m_pTPG_Last = NULL;
    m_pTPG_Head = NULL;
    m_nvmax = 0;

    //      Ready to kick off the tesselator
    gluTessEndPolygon(GLUtessobj);          // here it goes

    m_nvertex_max = m_nvmax;               // record largest vertex count, updates in callback


    //  Tesselation all done, so...

    //  Create the data structures

    m_ppg_head = new PolyTriGroup;
    m_ppg_head->m_bSMSENC = m_b_senc_sm;

    m_ppg_head->nContours = m_ncnt;

    m_ppg_head->pn_vertex = m_cntr;             // pointer to array of poly vertex counts
    m_ppg_head->data_type = DATA_TYPE_DOUBLE;
    

//  Transcribe the raw geometry buffer
//  Converting to float as we go, and
//  allowing for tess_orient
//  Also, convert to SM if requested

// Recalculate the size of the geometry buffer
    unsigned int nptfinal = m_cntr[0] + 2;
//     for(int i=0 ; i < nint ; i++)
//         nptfinal += cntr[i+1] + 2;
    
    //  No longer need the full geometry in the SENC,
    nptfinal = 1;
    
    m_nwkb = (nptfinal + 1) * 2 * sizeof(float);
    m_ppg_head->pgroup_geom = (float *)calloc(sizeof(float), (nptfinal + 1) * 2);
    float *vro = m_ppg_head->pgroup_geom;
    ppt = geoPt;
    float tx,ty;

    for(ip = 0 ; ip < nptfinal ; ip++)
    {
        if(TESS_HORZ == m_tess_orient)
        {
            ty = *ppt++;
            tx = *ppt++;
        }
        else
        {
            tx = *ppt++;
            ty = *ppt++;
        }

        if(m_b_senc_sm)
        {
            //  Calculate SM from chart common reference point
            double easting, northing;
            toSM(ty, tx, m_ref_lat, m_ref_lon, &easting, &northing);
            *vro++ = easting;              // x
            *vro++ = northing;             // y
        }
        else
        {
            *vro++ = tx;                  // lon
            *vro++ = ty;                  // lat
        }

        ppt++;                      // skip z
    }

    m_ppg_head->tri_prim_head = m_pTPG_Head;         // head of linked list of TriPrims


    //  Convert the Triangle vertex arrays into a single memory allocation of floats
    //  to reduce SENC size and enable efficient access later
    
    //  First calculate the total byte size
    int total_byte_size = 2 * sizeof(float);
    TriPrim *p_tp = m_ppg_head->tri_prim_head;
    while( p_tp ) {
        total_byte_size += p_tp->nVert * 2 * sizeof(float);
        p_tp = p_tp->p_next; // pick up the next in chain
    }
    
    float *vbuf = (float *)malloc(total_byte_size);
    p_tp = m_ppg_head->tri_prim_head;
    float *p_run = vbuf;
    while( p_tp ) {
        float *pfbuf = p_run;
        GLdouble *pdouble_buf = (GLdouble *)p_tp->p_vertex;
        
        for( int i=0 ; i < p_tp->nVert * 2 ; ++i){
            float x = (float)( *((GLdouble *)pdouble_buf) );
            pdouble_buf++;
            *p_run++ = x;
        }
        
        free(p_tp->p_vertex);
        p_tp->p_vertex = (double *)pfbuf;
        p_tp = p_tp->p_next; // pick up the next in chain
    }
    m_ppg_head->bsingle_alloc = true;
    m_ppg_head->single_buffer = (unsigned char *)vbuf;
    m_ppg_head->single_buffer_size = total_byte_size;
    m_ppg_head->data_type = DATA_TYPE_FLOAT;
    
    
    
    
    
    
    gluDeleteTess(GLUtessobj);

    free( m_pwork_buf );
    m_pwork_buf = NULL;

    free (geoPt);

    //      Free up any "Combine" vertices created
    for(unsigned int i = 0; i < m_pCombineVertexArray->GetCount() ; i++)
          free (m_pCombineVertexArray->Item(i));
    delete m_pCombineVertexArray;

    m_bOK = true;

    
    return 0;
}
Example #28
0
void init (void) 
{
   GLUtesselator *tobj;
   GLdouble rect[4][3] = {50.0, 50.0, 0.0,
                          200.0, 50.0, 0.0,
                          200.0, 200.0, 0.0,
                          50.0, 200.0, 0.0};
   GLdouble tri[3][3] = {75.0, 75.0, 0.0,
                         125.0, 175.0, 0.0,
                         175.0, 75.0, 0.0};
   GLdouble star[5][6] = {250.0, 50.0, 0.0, 1.0, 0.0, 1.0,
                          325.0, 200.0, 0.0, 1.0, 1.0, 0.0,
                          400.0, 50.0, 0.0, 0.0, 1.0, 1.0,
                          250.0, 150.0, 0.0, 1.0, 0.0, 0.0,
                          400.0, 150.0, 0.0, 0.0, 1.0, 0.0};

   glClearColor(0.0, 0.0, 0.0, 0.0);

   startList = glGenLists(2);

   tobj = gluNewTess();
   gluTessCallback(tobj, GLU_TESS_VERTEX, 
                   glVertex3dv);
   gluTessCallback(tobj, GLU_TESS_BEGIN, 
                   beginCallback);
   gluTessCallback(tobj, GLU_TESS_END, 
                   endCallback);
   gluTessCallback(tobj, GLU_TESS_ERROR, 
                   errorCallback);

   /*  rectangle with triangular hole inside  */
   glNewList(startList, GL_COMPILE);
   glShadeModel(GL_FLAT);    
   gluTessBeginPolygon(tobj, NULL);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, rect[0], rect[0]);
         gluTessVertex(tobj, rect[1], rect[1]);
         gluTessVertex(tobj, rect[2], rect[2]);
         gluTessVertex(tobj, rect[3], rect[3]);
      gluTessEndContour(tobj);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, tri[0], tri[0]);
         gluTessVertex(tobj, tri[1], tri[1]);
         gluTessVertex(tobj, tri[2], tri[2]);
      gluTessEndContour(tobj);
   gluTessEndPolygon(tobj);
   glEndList();

   gluTessCallback(tobj, GLU_TESS_VERTEX, 
                   vertexCallback);
   gluTessCallback(tobj, GLU_TESS_BEGIN, 
                   beginCallback);
   gluTessCallback(tobj, GLU_TESS_END, 
                   endCallback);
   gluTessCallback(tobj, GLU_TESS_ERROR, 
                   errorCallback);
   gluTessCallback(tobj, GLU_TESS_COMBINE, 
                   combineCallback);

   /*  smooth shaded, self-intersecting star  */
   glNewList(startList + 1, GL_COMPILE);
   glShadeModel(GL_SMOOTH);    
   gluTessProperty(tobj, GLU_TESS_WINDING_RULE,
                   GLU_TESS_WINDING_POSITIVE);
   gluTessBeginPolygon(tobj, NULL);
      gluTessBeginContour(tobj);
         gluTessVertex(tobj, star[0], star[0]);
         gluTessVertex(tobj, star[1], star[1]);
         gluTessVertex(tobj, star[2], star[2]);
         gluTessVertex(tobj, star[3], star[3]);
         gluTessVertex(tobj, star[4], star[4]);
      gluTessEndContour(tobj);
   gluTessEndPolygon(tobj);
   glEndList();
   gluDeleteTess(tobj);
}
Example #29
0
int PolyTessGeo::BuildTessGL(void)
{
#ifdef ocpnUSE_GL
    
      int iir, ip;
      int *cntr;
      GLdouble *geoPt;

      wxString    sout;
      wxString    sout1;
      wxString    stemp;


#ifdef __WXMSW__
//  If using the OpenGL dlls provided with Windows,
//  load the dll and establish addresses of the entry points needed

#ifdef USE_GLU_DLL

      if(!s_glu_dll_ready)
      {


            s_hGLU_DLL = LoadLibrary("glu32.dll");
            if (s_hGLU_DLL != NULL)
            {
                  s_lpfnTessProperty = (LPFNDLLTESSPROPERTY)GetProcAddress(s_hGLU_DLL,"gluTessProperty");
                  s_lpfnNewTess = (LPFNDLLNEWTESS)GetProcAddress(s_hGLU_DLL, "gluNewTess");
                  s_lpfnTessBeginContour = (LPFNDLLTESSBEGINCONTOUR)GetProcAddress(s_hGLU_DLL, "gluTessBeginContour");
                  s_lpfnTessEndContour = (LPFNDLLTESSENDCONTOUR)GetProcAddress(s_hGLU_DLL, "gluTessEndContour");
                  s_lpfnTessBeginPolygon = (LPFNDLLTESSBEGINPOLYGON)GetProcAddress(s_hGLU_DLL, "gluTessBeginPolygon");
                  s_lpfnTessEndPolygon = (LPFNDLLTESSENDPOLYGON)GetProcAddress(s_hGLU_DLL, "gluTessEndPolygon");
                  s_lpfnDeleteTess = (LPFNDLLDELETETESS)GetProcAddress(s_hGLU_DLL, "gluDeleteTess");
                  s_lpfnTessVertex = (LPFNDLLTESSVERTEX)GetProcAddress(s_hGLU_DLL, "gluTessVertex");
                  s_lpfnTessCallback = (LPFNDLLTESSCALLBACK)GetProcAddress(s_hGLU_DLL, "gluTessCallback");

                  s_glu_dll_ready = true;
            }
            else
            {
                  return ERROR_NO_DLL;
            }
      }

#endif
#endif


    //  Allocate a work buffer, which will be grown as needed
#define NINIT_BUFFER_LEN 10000
      s_pwork_buf = (GLdouble *)malloc(NINIT_BUFFER_LEN * 2 * sizeof(GLdouble));
      s_buf_len = NINIT_BUFFER_LEN * 2;
      s_buf_idx = 0;

      //    Create an array to hold pointers to allocated vertices created by "combine" callback,
      //    so that they may be deleted after tesselation.
      s_pCombineVertexArray = new wxArrayPtrVoid;

    //  Create tesselator
      GLUtessobj = gluNewTess();

    //  Register the callbacks
      gluTessCallback(GLUtessobj, GLU_TESS_BEGIN,   (GLvoid (__CALL_CONVENTION *) ())&beginCallback);
      gluTessCallback(GLUtessobj, GLU_TESS_BEGIN,   (GLvoid (__CALL_CONVENTION *) ())&beginCallback);
      gluTessCallback(GLUtessobj, GLU_TESS_VERTEX,  (GLvoid (__CALL_CONVENTION *) ())&vertexCallback);
      gluTessCallback(GLUtessobj, GLU_TESS_END,     (GLvoid (__CALL_CONVENTION *) ())&endCallback);
      gluTessCallback(GLUtessobj, GLU_TESS_COMBINE, (GLvoid (__CALL_CONVENTION *) ())&combineCallback);

//    gluTessCallback(GLUtessobj, GLU_TESS_ERROR,   (GLvoid (__CALL_CONVENTION *) ())&errorCallback);

//    glShadeModel(GL_SMOOTH);
      gluTessProperty(GLUtessobj, GLU_TESS_WINDING_RULE,
                      GLU_TESS_WINDING_POSITIVE );

    //  gluTess algorithm internally selects vertically oriented triangle strips and fans.
    //  This orientation is not optimal for conventional memory-mapped raster display shape filling.
    //  We can "fool" the algorithm by interchanging the x and y vertex values passed to gluTessVertex
    //  and then reverting x and y on the resulting vertexCallbacks.
    //  In this implementation, we will explicitely set the preferred orientation.

    //Set the preferred orientation
      tess_orient = TESS_HORZ;                    // prefer horizontal tristrips



//      Get total number of contours
      m_ncnt  = m_pxgeom->n_contours;

//      Allocate cntr array
      cntr = (int *)malloc(m_ncnt * sizeof(int));

//      Get total number of points(vertices)
      int npta  = m_pxgeom->contour_array[0];
      cntr[0] = npta;
      npta += 2;                            // fluff

      for( iir=0 ; iir < m_ncnt-1 ; iir++)
      {
            int nptr = m_pxgeom->contour_array[iir+1];
            cntr[iir+1] = nptr;

            npta += nptr + 2;             // fluff
      }



//      printf("xgeom npta: %d\n", npta);
      geoPt = (GLdouble *)malloc((npta) * 3 * sizeof(GLdouble));     // vertex array



   //  Grow the work buffer if necessary

      if((npta * 4) > s_buf_len)
      {
            s_pwork_buf = (GLdouble *)realloc(s_pwork_buf, npta * 4 * sizeof(GLdouble));
            s_buf_len = npta * 4;
      }


//  Define the polygon
      gluTessBeginPolygon(GLUtessobj, NULL);


//      Create input structures

//    Exterior Ring
      int npte = m_pxgeom->contour_array[0];
      cntr[0] = npte;

      GLdouble *ppt = geoPt;


//  Check and account for winding direction of ring
      bool cw = true;

      double x0, y0, x, y;
      OGRPoint p;

      wxPoint2DDouble *pp = m_pxgeom->vertex_array;
      pp++;       // skip 0?

      if(cw)
      {
//            poly->getExteriorRing()->getPoint(0, &p);
            x0 = pp->m_x;
            y0 = pp->m_y;
      }
      else
      {
//            poly->getExteriorRing()->getPoint(npte-1, &p);
            x0 = pp[npte-1].m_x;
            y0 = pp[npte-1].m_y;
//            x0 = p.getX();
//            y0 = p.getY();
      }

//      pp++;

      gluTessBeginContour(GLUtessobj);

//  Transcribe points to vertex array, in proper order with no duplicates
//   also, accounting for tess_orient
      for(ip = 0 ; ip < npte ; ip++)
      {
            int pidx;
            if(cw)
                  pidx = npte - ip - 1;

            else
                  pidx = ip;

//            poly->getExteriorRing()->getPoint(pidx, &p);
            x = pp[pidx].m_x;
            y = pp[pidx].m_y;

//            pp++;

            if((fabs(x-x0) > EQUAL_EPS) || (fabs(y-y0) > EQUAL_EPS))
            {
                  GLdouble *ppt_temp = ppt;
                  if(tess_orient == TESS_VERT)
                  {
                        *ppt++ = x;
                        *ppt++ = y;
                  }
                  else
                  {
                        *ppt++ = y;
                        *ppt++ = x;
                  }

                  *ppt++ = 0.0;

                  gluTessVertex( GLUtessobj, ppt_temp, ppt_temp ) ;
 //printf("tess from xgeom, external vertex %g %g\n", x, y);

            }
            else
                  cntr[0]--;

            x0 = x;
            y0 = y;
      }

      gluTessEndContour(GLUtessobj);


      int index_offset = npte;
#if 1
//  Now the interior contours
      for(iir=0; iir < m_ncnt-1; iir++)
      {
            gluTessBeginContour(GLUtessobj);

//            int npti = cntr[iir];
            int npti  = m_pxgeom->contour_array[iir+1];

      //  Check and account for winding direction of ring
            bool cw = false; //!(poly->getInteriorRing(iir)->isClockwise() == 0);

            if(!cw)
            {
                  x0 = pp[index_offset].m_x;
                  y0 = pp[index_offset].m_y;
            }
            else
            {
                  x0 = pp[index_offset + npti-1].m_x;
                  y0 = pp[index_offset + npti-1].m_y;
            }

//  Transcribe points to vertex array, in proper order with no duplicates
//   also, accounting for tess_orient
            for(int ip = 0 ; ip < npti ; ip++)
            {
                  OGRPoint p;
                  int pidx;
                  if(!cw)                               // interior contours must be cw
                        pidx = npti - ip - 1;
                  else
                        pidx = ip;


                  x = pp[pidx + index_offset].m_x;
                  y = pp[pidx + index_offset].m_y;

                  if((fabs(x-x0) > EQUAL_EPS) || (fabs(y-y0) > EQUAL_EPS))
                  {
                        GLdouble *ppt_temp = ppt;
                        if(tess_orient == TESS_VERT)
                        {
                              *ppt++ = x;
                              *ppt++ = y;
                        }
                        else
                        {
                              *ppt++ = y;
                              *ppt++ = x;
                        }
                        *ppt++ = 0.0;

                        gluTessVertex( GLUtessobj, ppt_temp, ppt_temp ) ;
//      printf("tess from xgeom, internal vertex %d %g %g\n", ip, x, y);

                  }
                  else
                        cntr[iir+1]--;

                  x0 = x;
                  y0 = y;

            }

            gluTessEndContour(GLUtessobj);

            index_offset += npti;
      }
#endif

    //  Store some SM conversion data in static store,
    //  for callback access
      s_bSENC_SM =  false;

      s_bmerc_transform = true;
      s_transform_x_rate   =  m_pxgeom->x_rate;
      s_transform_x_origin =  m_pxgeom->x_offset;
      s_transform_y_rate   =  m_pxgeom->y_rate;
      s_transform_y_origin =  m_pxgeom->y_offset;


    //      Ready to kick off the tesselator

      s_pTPG_Last = NULL;
      s_pTPG_Head = NULL;

      s_nvmax = 0;

      gluTessEndPolygon(GLUtessobj);          // here it goes

      m_nvertex_max = s_nvmax;               // record largest vertex count, updates in callback


    //  Tesselation all done, so...

    //  Create the data structures

      m_ppg_head = new PolyTriGroup;
      m_ppg_head->m_bSMSENC = s_bSENC_SM;

      m_ppg_head->nContours = m_ncnt;
      m_ppg_head->pn_vertex = cntr;             // pointer to array of poly vertex counts
      m_ppg_head->data_type = DATA_TYPE_DOUBLE;
      

//  Transcribe the raw geometry buffer
//  Converting to float as we go, and
//  allowing for tess_orient
//  Also, convert to SM if requested

      int nptfinal = npta;
      
      //  No longer need the full geometry in the SENC,
      nptfinal = 1;
      
      m_nwkb = (nptfinal +1) * 2 * sizeof(float);
      m_ppg_head->pgroup_geom = (float *)malloc(m_nwkb);
      float *vro = m_ppg_head->pgroup_geom;
      ppt = geoPt;
      float tx,ty;

      for(ip = 0 ; ip < nptfinal ; ip++)
      {
            if(TESS_HORZ == tess_orient)
            {
                  ty = *ppt++;
                  tx = *ppt++;
            }
            else
            {
                  tx = *ppt++;
                  ty = *ppt++;
            }

            if(0/*bSENC_SM*/)
            {
            //  Calculate SM from chart common reference point
                  double easting, northing;
//                  toSM(ty, tx, ref_lat, ref_lon, &easting, &northing);
                  *vro++ = easting;              // x
                  *vro++ = northing;             // y
            }
            else
            {
                  *vro++ = tx;                  // lon
                  *vro++ = ty;                  // lat
            }

            ppt++;                      // skip z
      }

      m_ppg_head->tri_prim_head = s_pTPG_Head;         // head of linked list of TriPrims

      //  Convert the Triangle vertex arrays into a single memory allocation of floats
      //  to reduce SENC size and enable efficient access later
      
      //  First calculate the total byte size
      int total_byte_size = 2 * sizeof(float);
      TriPrim *p_tp = m_ppg_head->tri_prim_head;
      while( p_tp ) {
          total_byte_size += p_tp->nVert * 2 * sizeof(float);
          p_tp = p_tp->p_next; // pick up the next in chain
      }
      
      float *vbuf = (float *)malloc(total_byte_size);
      p_tp = m_ppg_head->tri_prim_head;
      float *p_run = vbuf;
      while( p_tp ) {
          float *pfbuf = p_run;
          GLdouble *pdouble_buf = (GLdouble *)p_tp->p_vertex;
          
          for( int i=0 ; i < p_tp->nVert * 2 ; ++i){
              float x = (float)( *((GLdouble *)pdouble_buf) );
              *p_run++ = x;
              pdouble_buf++;
          }
          
          free(p_tp->p_vertex);
          p_tp->p_vertex = (double *)pfbuf;
          p_tp = p_tp->p_next; // pick up the next in chain
      }
      m_ppg_head->bsingle_alloc = true;
      m_ppg_head->single_buffer = (unsigned char *)vbuf;
      m_ppg_head->single_buffer_size = total_byte_size;
      m_ppg_head->data_type = DATA_TYPE_FLOAT;
      
      gluDeleteTess(GLUtessobj);

      free( s_pwork_buf );
      s_pwork_buf = NULL;

      free (geoPt);

      //    All allocated buffers are owned now by the m_ppg_head
      //    And will be freed on dtor of this object
      delete m_pxgeom;

      //      Free up any "Combine" vertices created
      for(unsigned int i = 0; i < s_pCombineVertexArray->GetCount() ; i++)
            free (s_pCombineVertexArray->Item(i));
      delete s_pCombineVertexArray;


      m_pxgeom = NULL;

      m_bOK = true;

#endif          //#ifdef ocpnUSE_GL
      
      return 0;
}
Example #30
0
nuiRenderObject* nuiTessellator::GenerateFromPath(float Quality)
{
  nuiPath Points;

  mpPath->Tessellate(Points, Quality);
  uint count = Points.GetCount();
  if (!count)
    return nullptr;
  
  gluTessNormal(mpTess, 0,0,1);
  gluTessProperty(mpTess,GLU_TESS_TOLERANCE, 0);
  gluTessCallback(mpTess, GLU_TESS_BEGIN_DATA,    NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessBegin);
  gluTessCallback(mpTess, GLU_TESS_EDGE_FLAG_DATA,NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessEdgeFlag);
  gluTessCallback(mpTess, GLU_TESS_VERTEX_DATA,   NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessVertex);
  gluTessCallback(mpTess, GLU_TESS_END_DATA,      NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessEnd);
  gluTessCallback(mpTess, GLU_TESS_COMBINE_DATA,  NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessCombine);
  gluTessCallback(mpTess, GLU_TESS_ERROR_DATA,    NUI_GLU_CALLBACK &nuiTessellator::StaticInternalTessError);

  gluTessProperty(mpTess,GLU_TESS_BOUNDARY_ONLY, mOutline?GL_TRUE:GL_FALSE);
  gluTessProperty(mpTess,GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);

  mpObject = new nuiRenderObject();
  mEdgeFlag = true;

  gluTessBeginPolygon(mpTess, this);

  bool beginNext = true;

  //printf("Start tesselation\n");
  for (uint i = 0; i < count; i++)
  {
    nuiPoint& rPoint = Points[i];
    if (rPoint.GetType() != nuiPointTypeStop)
    {
      if (beginNext)
      {
        gluTessBeginContour(mpTess);
        beginNext = false;
      }

      double vec[4] = { rPoint[0], rPoint[1], rPoint[2], 0 };
      //printf("%d input %f %f\n", i, vec[0], vec[1]);
      gluTessVertex(mpTess, vec, (void*)mTempPoints.AddVertex(rPoint));
    }
    else
    {
      //printf("End Contour\n");
      gluTessEndContour(mpTess);
      beginNext = true;
    }
  }
  if (Points.Back().GetType() != nuiPointTypeStop)
    gluTessEndContour(mpTess);

  gluTessEndPolygon(mpTess); 

  nuiRenderObject* pObject = mpObject;
  mpObject = NULL;
  mTempPoints.Clear();
  return pObject;
}