#include <../../config.h>
#include "glp.h"
#include <math.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
GLPcontext :: ~GLPcontext(void)
{
delete_all();
}
int
GLPcontext :: StartPage(int mode)
{
feedmode = mode;
#ifdef DEBUG
cout << "RGBA feedmode = " << mode << "\n" << flush;
#endif
glFeedbackBuffer(feedsize, GL_3D_COLOR, feedback);
glRenderMode(GL_FEEDBACK);
return (0);
}
int
GLPcontext :: StartPage(int mode,
int size,
GLPrgba *rgba)
{
feedmode = mode;
#ifdef DEBUG
cout << "Index feedmode = " << mode << "\n" << flush;
#endif
glFeedbackBuffer(feedsize, GL_3D_COLOR, feedback);
glRenderMode(GL_FEEDBACK);
if (colormap != NULL)
delete colormap;
colorsize = size;
colormap = new GLPrgba[size];
memcpy(colormap, rgba, size * sizeof(GLPrgba));
return (0);
}
#include <stdio.h>
int
GLPcontext :: UpdatePage(GLboolean more)
{
int i, used, count, v;
GLfloat *current;
GLPvertex vertices[3];
GLboolean depth,
shade;
GLint shademodel;
#ifdef DEBUG
cout << "UpdatePage(" << (more ? "GL_TRUE" : "GL_FALSE") << ")\n" << flush;
#endif
depth = glIsEnabled(GL_DEPTH_TEST);
glGetIntegerv(GL_SHADE_MODEL, &shademodel);
shade = shademodel == GL_SMOOTH;
used = glRenderMode(more ? GL_FEEDBACK : GL_RENDER);
fprintf( stderr, "yseD: %d\n", used );
if (used <= 0) return (GLP_NO_FEEDBACK);
#ifdef DEBUG
cout << "glGetError() after glRenderMode returned " << glGetError() << "\n" << flush;
cout << "First: used = " << used << ", feedback[0] = " << feedback[0] << "\n" << flush;
#endif
current = feedback;
while (used > 0)
{
#ifdef DEBUG
cout << "Loop: used = " << used << "\n" << flush;
#endif
switch ((int)*current)
{
case GL_POINT_TOKEN :
current ++;
used --;
i = get_vertex(vertices + 0, current);
current += i;
used -= i;
add_primitive(depth, shade, 1, vertices);
break;
case GL_LINE_TOKEN: case GL_LINE_RESET_TOKEN:
current ++;
used --;
i = get_vertex(vertices + 0, current);
current += i;
used -= i;
i = get_vertex(vertices + 1, current);
current += i;
used -= i;
add_primitive(depth, shade, 2, vertices);
break;
case GL_POLYGON_TOKEN :
count = (int)current[1];
current += 2;
used -= 2;
v = 0;
while (count > 0 && used > 0)
{
i = get_vertex( vertices + v, current );
current += i;
used -= i;
count --;
if (v == 2)
{
add_primitive( depth, shade, 3, vertices );
vertices[1] = vertices[2];
v = 0;
}
else
v++;
};
break;
case GL_BITMAP_TOKEN :
case GL_DRAW_PIXEL_TOKEN :
case GL_COPY_PIXEL_TOKEN :
current ++;
used --;
i = get_vertex(vertices + 0, current);
current += i;
used -= i;
break;
case GL_PASS_THROUGH_TOKEN :
#ifdef DEBUG
std::cout << "UpdatePage: Ignoring passthrough token " << current[1] << "...\n" << std::flush;
#endif
current += 2;
used -= 2;
break;
default :
std::cout << "UpdatePage: Ignoring unknown token " << current[0] << "...\n" << std::flush;
current ++;
used --;
break;
};
};
return (GLP_SUCCESS);
}
int
GLPcontext :: EndPage(void)
{
GLPbbox *bbox;
GLPprimitive *prim;
#ifdef DEBUG
cout << "EndPage()\n" << flush;
#endif
UpdatePage(GL_FALSE);
if (bboxes == NULL) return (GLP_NO_FEEDBACK);
for (bbox = bboxes; bbox != NULL; bbox = bbox->next)
{
};
delete_all();
#ifdef DEBUG
cout << "EndPage() - done.\n" << flush;
#endif
return (GLP_SUCCESS);
}
void
GLPcontext :: SetOptions(int print_options)
{
options = print_options;
}
void
GLPcontext :: add_primitive(GLboolean depth,
GLboolean shade,
int num_verts,
GLPvertex *verts)
{
int i,
count;
GLfloat min[3],
max[3];
GLPprimitive *newprim,*pprim,*ppprim;
GLPbbox *bbox,
*joinbbox,
*nextbbox;
#ifdef DEBUG
cout << "add_primitive(" << (depth ? "GL_TRUE" : "GL_FALSE") << ", "
<< (shade ? "GL_TRUE" : "GL_FALSE") << ", "
<< num_verts << ", "
<< (int)verts << ")\n" << flush;
#endif
newprim = new GLPprimitive;
newprim->left = NULL;
newprim->right = NULL;
newprim->shade = shade;
newprim->num_verts = num_verts;
memcpy( newprim->verts, verts, sizeof(GLPvertex) * num_verts );
min[0] = min[1] = min[2] = 1e20;
max[0] = max[1] = max[2] = -1e20;
for (i = 0; i < num_verts; i ++)
{
if ( verts[i].xyz[0] < min[0] ) min[0] = verts[i].xyz[0];
if ( verts[i].xyz[1] < min[1] ) min[1] = verts[i].xyz[1];
if ( verts[i].xyz[2] < min[2] ) min[2] = verts[i].xyz[2];
if ( verts[i].xyz[0] > max[0] ) max[0] = verts[i].xyz[0];
if ( verts[i].xyz[1] > max[1] ) max[1] = verts[i].xyz[1];
if ( verts[i].xyz[2] > max[2] ) max[2] = verts[i].xyz[2];
};
newprim->zmin = min[2];
newprim->zmax = max[2];
min[0] = floor( min[0] * 0.015625 ) * 64.0;
min[1] = floor( min[1] * 0.015625 ) * 64.0;
max[0] = ceil( max[0] * 0.015625 ) * 64.0;
max[1] = ceil( max[1] * 0.015625 ) * 64.0;
for (bbox = bboxes; bbox != NULL; bbox = bbox->next)
{
count = 0;
if ( min[0] > bbox->min[0] && min[0] < bbox->max[0] ) count++;
if ( max[0] > bbox->min[0] && max[0] < bbox->max[0] ) count++;
if ( min[1] > bbox->min[1] && min[1] < bbox->max[1] ) count++;
if ( max[1] > bbox->min[1] && max[1] < bbox->max[1] ) count++;
if ( count > 0 ) break;
};
if (bbox == NULL)
{
bbox = new GLPbbox;
bbox->prev = NULL;
bbox->next = bboxes;
if (bboxes != NULL) bboxes->prev = bbox;
bboxes = bbox;
bbox->min[0] = min[0];
bbox->max[0] = max[0];
bbox->min[1] = min[1];
bbox->max[1] = max[1];
bbox->min[2] = min[2];
bbox->max[2] = max[2];
bbox->primitives = newprim;
bbox->lastprim = newprim;
}
else if (count < 4)
{
if ( min[0] < bbox->min[0] ) bbox->min[0] = min[0];
if ( max[0] > bbox->max[0] ) bbox->max[0] = max[0];
if ( min[1] < bbox->min[1] ) bbox->min[1] = min[1];
if ( max[1] > bbox->max[1] ) bbox->max[1] = max[1];
do
{
count = 0;
for (joinbbox = bboxes; joinbbox != NULL; joinbbox = nextbbox)
{
nextbbox = joinbbox->next;
if (joinbbox == bbox)
continue;
else if (( bbox->min[0] > joinbbox->min[0] && bbox->min[0] < joinbbox->max[0]) ||
( bbox->max[0] > joinbbox->min[0] && bbox->max[0] < joinbbox->max[0]) ||
( bbox->min[1] > joinbbox->min[1] && bbox->min[1] < joinbbox->max[1]) ||
( bbox->max[1] > joinbbox->min[1] && bbox->max[1] < joinbbox->max[1]))
{
count++;
if (joinbbox->prev == NULL)
bboxes = joinbbox->next;
else
(joinbbox->prev)->next = joinbbox->next;
if (nextbbox != NULL)
nextbbox->prev = joinbbox->prev;
for (i = 0; i < 3; i ++)
{
if ( joinbbox->min[i] < bbox->min[i] ) bbox->min[i] = joinbbox->min[i];
if ( joinbbox->max[i] > bbox->max[i] ) bbox->max[i] = joinbbox->max[i];
};
add_subtree( &bbox->primitives, joinbbox->primitives );
delete joinbbox;
};
};
}
while (count > 0);
add_tree( &bbox->primitives, newprim);
}
else
{
add_tree( &bbox->primitives, newprim);
};
}
int
GLPcontext :: get_vertex(GLPvertex *v,
GLfloat *p)
{
int i;
v->xyz[0] = p[0];
v->xyz[1] = p[1];
v->xyz[2] = p[2];
#ifdef DEBUG
cout << "{ " << p[0] << ", " << p[1] << ", " << p[2] << "}, " << flush;
#endif
if (feedmode == GL_COLOR_INDEX && colorsize > 0)
{
i = (int)(p[3] + 0.5);
v->rgba[0] = colormap[i][0];
v->rgba[1] = colormap[i][1];
v->rgba[2] = colormap[i][2];
v->rgba[3] = colormap[i][3];
return (4);
}
else
{
v->rgba[0] = p[3];
v->rgba[1] = p[4];
v->rgba[2] = p[5];
v->rgba[3] = p[6];
return (7);
};
}
void GLPcontext :: delete_tree( GLPprimitive *tree )
{
if ( !tree ) return;
delete_tree( tree->left );
delete_tree( tree->right );
delete tree;
}
void
GLPcontext :: delete_all(void)
{
GLPbbox *bbox,
*nextbbox;
GLPprimitive *prim,
*nextprim;
#ifdef DEBUG
cout << "delete_all()\n" << flush;
#endif
for (bbox = bboxes, nextbbox = NULL; bbox != NULL; bbox = nextbbox)
{
delete_tree( bbox->primitives );
nextbbox = bbox->next;
delete bbox;
};
bboxes = NULL;
delete_tree( tree );
tree = NULL;
#ifdef DEBUG
cout << "delete_all(): done.\n" << flush;
#endif
}
void GLPcontext::add_subtree( GLPprimitive **ptree, GLPprimitive *prim )
{
GLPprimitive *left, *right;
if ( !prim ) return;
left = prim->left;
right = prim->right;
prim->left = NULL;
prim->right = NULL;
add_tree( ptree, prim );
add_subtree( ptree, left );
add_subtree( ptree, right );
}
void GLPcontext::add_tree( GLPprimitive **ptree, GLPprimitive *prim )
{
static int count=0;
if ( !*ptree )
{
*ptree = prim;
} else {
if ( (prim->zmin+prim->zmax) == ((*ptree)->zmin+(*ptree)->zmax) )
{
if ( count++ ) {
prim->right = (*ptree)->left;
(*ptree)->left = prim;
count = 0;
} else {
prim->left = (*ptree)->right;
(*ptree)->right = prim;
}
} else if ( (prim->zmin+prim->zmax) > ((*ptree)->zmin+(*ptree)->zmax) )
{
if ( (*ptree)->left )
add_tree( &(*ptree)->left, prim );
else
(*ptree)->left = prim;
} else {
if ( (*ptree)->right )
add_tree( &(*ptree)->right, prim );
else
(*ptree)->right = prim;
}
}
}