1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
/*************************************************************************
* Copyright (c) 2011 AT&T Intellectual Property
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors: Details at https://graphviz.org
*************************************************************************/
#include "polytess.h"
#include <stddef.h>
#include <util/alloc.h>
#include <xdot/xdot.h>
tessPoly TP;
#ifndef _WIN32
#define CALLBACK
#endif
static void CALLBACK combineCallback(double coords[3],
double *vertex_data[4],
float weight[4],
double **dataOut) {
(void)vertex_data;
(void)weight;
int i;
double *vertex = gv_calloc(6, sizeof(double));
vertex[0] = coords[0];
vertex[1] = coords[1];
vertex[2] = coords[2];
for (i = 3; i < 6; i++)
{
vertex[i] = 0;
}
*dataOut = vertex;
}
static void CALLBACK vertexCallback(void *vertex) {
glVertex3dv(vertex);
}
// OpenGL’s `gluTessCallback` function has a prototype indicating it takes a
// `void(*)(void)`. But its documentation describes passing in various function
// pointers with differing calling conventions. To use this API while also
// pacifying all the various build environments, we need this rather silly
// wrapper.
#ifdef _MSC_VER
// MSVC is of the (correct) opinion that casting between function pointers of
// incompatible calling conventions is unacceptable behavior…
#define MAKE_GLU_CALLBACK(f) f
#else
// …nevertheless other compilers insist we cast or they believe we have made a
// typo
#define MAKE_GLU_CALLBACK(f) ((void (*)(void))(f))
#endif
static GLUtesselator* Init(void)
{
// Create a new tessellation object
GLUtesselator* tobj = gluNewTess();
// Set callback functions
gluTessCallback(tobj, GLU_TESS_VERTEX, MAKE_GLU_CALLBACK(vertexCallback));
gluTessCallback(tobj, GLU_TESS_BEGIN, MAKE_GLU_CALLBACK(glBegin));
gluTessCallback(tobj, GLU_TESS_END, MAKE_GLU_CALLBACK(glEnd));
gluTessCallback(tobj, GLU_TESS_COMBINE, MAKE_GLU_CALLBACK(combineCallback));
return tobj;
}
static void Set_Winding_Rule(GLUtesselator *tobj, GLenum winding_rule)
{
// Set the winding rule
gluTessProperty(tobj, GLU_TESS_WINDING_RULE, winding_rule);
}
static void Render_Contour2(GLUtesselator *tobj, sdot_op* p)
{
double *d = gv_calloc(p->op.u.polygon.cnt * 3, sizeof(double));
for (size_t x = 0; x < p->op.u.polygon.cnt; x++)
{
d[x * 3] = p->op.u.polygon.pts[x].x;
d[x * 3 + 1] = p->op.u.polygon.pts[x].y;
d[x * 3 + 2] = p->op.u.polygon.pts[x].z + view->Topview->global_z;
}
for (size_t x = 0; x < p->op.u.polygon.cnt; x++) //loop through the vertices
{
gluTessVertex(tobj, &d[x * 3], &d[x * 3]); //store the vertex
}
}
static void Begin_Polygon(GLUtesselator *tobj)
{
gluTessBeginPolygon(tobj, NULL);
}
static void End_Polygon(GLUtesselator *tobj)
{
gluTessEndPolygon(tobj);
}
static void Begin_Contour(GLUtesselator *tobj)
{
gluTessBeginContour(tobj);
}
static void End_Contour(GLUtesselator *tobj)
{
gluTessEndContour(tobj);
}
void drawTessPolygon(sdot_op* p)
{
if (!TP.tobj)
{
TP.tobj=Init();
TP.windingRule=GLU_TESS_WINDING_ODD;
}
Set_Winding_Rule(TP.tobj,TP.windingRule);
Begin_Polygon(TP.tobj);
Begin_Contour(TP.tobj);
Render_Contour2(TP.tobj,p);
End_Contour(TP.tobj);
End_Polygon(TP.tobj);
}
|