home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1997 March
/
VPR9703A.ISO
/
VPR_DATA
/
DOGA
/
SOURCES
/
POLYEDIT.LZH
/
MODEL
/
EDGE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-03-26
|
13KB
|
549 lines
/*
* エッジ
*
* Copyright T.Kobayashi 1994.7.9
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "matrix.h"
#include "vector.h"
#include "matclass.h"
#include "strclass.h"
#include "ml.h"
#include "poly.h"
#include "view.h"
extern int EdgeClassID ;
#define EDGEALLOCUNIT 256
#ifndef __GNUC__
#define inline
#endif
static inline int EdgeEqual(EdgeData *e1, EdgeData *e2)
{
return memcmp(e1, e2, sizeof(short)*6) == 0;
}
static inline int EdgeCompare(EdgeData *e1, EdgeData *e2)
{
int *i1, *i2;
i1 = (int*)e1;
i2 = (int*)e2;
if (i1[0] != i2[0])
return i1[0] - i2[0];
if (i1[1] != i2[1])
return i1[1] - i2[1];
return i1[2] - i2[2];
}
static int EdgeSearchEdge(EdgeClass *edge, EdgeData *ed)
{
int i, j;
int begin, end;
if ((ed->x1 < edge->min[0] && ed->x2 < edge->min[0])
|| (ed->y1 < edge->min[1] && ed->y2 < edge->min[1])
|| (ed->z1 < edge->min[2] && ed->z2 < edge->min[2])
|| (ed->x1 > edge->max[0] && ed->x2 > edge->max[0])
|| (ed->y1 > edge->max[1] && ed->y2 > edge->max[1])
|| (ed->z1 > edge->max[2] && ed->z2 > edge->max[2])) {
return -1;
}
#if 0
for (i = 0; i < edge->edges; ++i) {
if (EdgeEqual(&edge->edge[i], ed)) {
return i;
}
}
#else
begin = -1;
end = edge->edges;
while (begin < end-1) {
i = (begin+end)/2;
j = EdgeCompare(&edge->edge[i], ed);
if (j == 0) {
return i;
} else if (j < 0) {
end = i;
} else {
begin = i;
}
}
#endif
return -1;
}
static EdgeClass *EdgeRealloc(EdgeClass *edge, int size)
{
int i;
EdgeClass *newedge;
newedge = (EdgeClass*)ObjectAlloc(sizeof(EdgeClass) + sizeof(EdgeData) * size, EdgeClassID);
if (size > edge->allocsize) {
memcpy(newedge->edge, edge->edge, sizeof(EdgeData) * edge->allocsize);
} else {
memcpy(newedge->edge, edge->edge, sizeof(EdgeData) * size);
}
for (i = 0; i < 3; ++i) {
newedge->min[i] = edge->min[i];
newedge->max[i] = edge->max[i];
}
newedge->edges = edge->edges;
newedge->allocsize = size;
ObjectFree((Object*)edge);
return newedge;
}
static EdgeClass *EdgeAppendEdge(EdgeClass *edge, EdgeData *ed)
{
int pos;
int j, begin, end;
if (edge->allocsize <= edge->edges) {
edge = EdgeRealloc(edge, edge->allocsize + EDGEALLOCUNIT);
}
#if 0
pos = edge->edges;
#else
/*
getch();
for (pos = 0; pos < edge->edges; pos++)
printf("\n(%4d,%4d,%4d)-(%4d,%4d,%4d)",
edge->edge[pos].x1, edge->edge[pos].y1, edge->edge[pos].z1,
edge->edge[pos].x2, edge->edge[pos].y2, edge->edge[pos].z2);
printf("\nEdgeAppendEdge(%d)(%4d,%4d,%4d)-(%4d,%4d,%4d):",edge->edges,
ed->x1, ed->y1, ed->z1, ed->x2, ed->y2, ed->z2);
*/
begin = -1;
pos = end = edge->edges;
while (begin < end-1) {
pos = (begin+end)/2;
j = EdgeCompare(&edge->edge[pos], ed);
if (j == 0) {
edge->edge[pos].count++;
/*printf("hit%d\n", pos);*/
return edge;
} else if (j < 0) {
end = pos;
} else {
begin = pos;
}
}
pos = end;
if (pos < edge->edges) {
memmove(&edge->edge[pos+1], &edge->edge[pos], sizeof(EdgeData) * (edge->edges-pos));
}
/*printf("add%d", pos);*/
#endif
edge->edge[pos] = *ed;
if (edge->min[0] > ed->x1) edge->min[0] = ed->x1;
if (edge->min[0] > ed->x2) edge->min[0] = ed->x2;
if (edge->min[1] > ed->y1) edge->min[1] = ed->y1;
if (edge->min[1] > ed->y2) edge->min[1] = ed->y2;
if (edge->min[2] > ed->z1) edge->min[2] = ed->z1;
if (edge->min[2] > ed->z2) edge->min[2] = ed->z2;
if (edge->max[0] < ed->x1) edge->max[0] = ed->x1;
if (edge->max[0] < ed->x2) edge->max[0] = ed->x2;
if (edge->max[1] < ed->y1) edge->max[1] = ed->y1;
if (edge->max[1] < ed->y2) edge->max[1] = ed->y2;
if (edge->max[2] < ed->z1) edge->max[2] = ed->z1;
if (edge->max[2] < ed->z2) edge->max[2] = ed->z2;
edge->edges++;
return edge;
}
static EdgeClass *EdgeDeletePos(EdgeClass *edge, int pos)
{
if (pos < 0 || edge->edges <= pos) {
return edge;
}
#if 0
if (pos != edge->edges-1) {
edge->edge[pos] = edge->edge[edge->edges-1];
}
#else
if (pos != edge->edges-1) {
memmove(&edge->edge[pos], &edge->edge[pos+1], sizeof(EdgeData) * (edge->edges-pos-1));
}
#endif
edge->edges--;
return edge;
}
static void EdgeCreate(EdgeData *ed, Vertex *p1, Vertex *p2)
{
Vertex *p3;
if (p1->x > p2->x
|| (p1->x == p2->x && (p1->y > p2->y || (p1->y == p2->y && p1->z > p2->z)))) {
p3 = p1; p1 = p2; p2 = p3;
}
ed->x1 = p1->x;
ed->y1 = p1->y;
ed->z1 = p1->z;
ed->x2 = p2->x;
ed->y2 = p2->y;
ed->z2 = p2->z;
ed->count = 1;
}
int EdgeSearch(EdgeClass *edge, Vertex *p1, Vertex *p2)
{
EdgeData ed;
EdgeCreate(&ed, p1, p2);
return EdgeSearchEdge(edge, &ed);
}
EdgeClass *EdgeAppend(EdgeClass *edge, Vertex *p1, Vertex *p2)
{
EdgeData ed;
EdgeCreate(&ed, p1, p2);
#if 0
int pos;
if ((pos = EdgeSearchEdge(edge, &ed)) < 0) {
edge = EdgeAppendEdge(edge, &ed);
} else {
edge->edge[pos].count++;
}
#else
edge = EdgeAppendEdge(edge, &ed);
#endif
return edge;
}
EdgeClass *EdgeDelete(EdgeClass *edge, Vertex *p1, Vertex *p2)
{
int pos;
if ((pos = EdgeSearch(edge, p1, p2)) >= 0) {
edge = EdgeDeletePos(edge, pos);
}
return edge;
}
EdgeClass *EdgeAlloc(int size)
{
EdgeClass *edge;
if (size < EDGEALLOCUNIT) {
size = EDGEALLOCUNIT;
} else {
size = ((size / EDGEALLOCUNIT) + 1) * EDGEALLOCUNIT;
}
edge = (EdgeClass*)ObjectAlloc(sizeof(EdgeClass) + sizeof(EdgeData) * size, EdgeClassID);
edge->allocsize = size;
edge->edges = 0;
edge->min[0] = edge->min[1] = edge->min[2] = 32767;
edge->max[0] = edge->max[1] = edge->max[2] = -32767;
return edge;
}
static int EdgeSearchPoly(EdgeClass *edge, Polygon *poly)
{
int i, j;
int vers = poly->vers ;
/*printf("EdgeSearchPoly: (%d,%d,%d)-(%d,%d,%d)\n",
edge->min[0], edge->min[1], edge->min[2],
edge->max[0], edge->max[1], edge->max[2]);*/
for( i = 0 ; i < vers ; i++ )
{
/*printf("Check (%d,%d,%d)\n", poly->ver[i].x, poly->ver[i].y, poly->ver[i].z);*/
if (edge->min[0] <= poly->ver[i].x && poly->ver[i].x <= edge->max[0]
&& edge->min[1] <= poly->ver[i].y && poly->ver[i].y <= edge->max[1]
&& edge->min[2] <= poly->ver[i].z && poly->ver[i].z <= edge->max[2]) {
int ip = i-1, in = i+1;
if (i == 0) ip = vers-1;
if (i == vers-1) in = 0;
for (j = 0; j < edge->edges; ++j) {
if (poly->ver[i].x == edge->edge[j].x1
&& poly->ver[i].y == edge->edge[j].y1
&& poly->ver[i].z == edge->edge[j].z1) {
if ((poly->ver[ip].x == edge->edge[j].x2
&& poly->ver[ip].y == edge->edge[j].y2
&& poly->ver[ip].z == edge->edge[j].z2)
|| (poly->ver[in].x == edge->edge[j].x2
&& poly->ver[in].y == edge->edge[j].y2
&& poly->ver[in].z == edge->edge[j].z2)) {
/*printf("hit\n");*/
return TRUE;
}
}
}
}
}
/*printf("miss\n");*/
return FALSE;
}
EdgeClass *EdgeSelectVertex(EdgeClass *edge, Vertex *p1)
{
int i, ni;
if (p1->x < edge->min[0] || p1->y < edge->min[1] || p1->z < edge->min[2]
|| p1->x > edge->max[0] || p1->y > edge->max[1] || p1->z > edge->max[2]) {
edge->edges = 0;
return edge;
}
ni = 0;
for (i = 0; i < edge->edges; ++i) {
if ((edge->edge[i].x1 == p1->x
&& edge->edge[i].y1 == p1->y
&& edge->edge[i].z1 == p1->z)
|| (edge->edge[i].x2 == p1->x
&& edge->edge[i].y2 == p1->y
&& edge->edge[i].z2 == p1->z)) {
if (ni != i) {
edge->edge[ni] = edge->edge[i];
}
ni++;
}
}
edge->edges = ni;
return edge;
}
EdgeClass *EdgeMulMatrix(EdgeClass *edge, MatrixClass* mat)
{
int imat[5][3];
int i, x, y, z;
EdgeData *ed;
MatToInt( imat, mat->mat );
ed = edge->edge;
for (i = 0; i < edge->edges; i++) {
x = (int)ed->x1 * imat[0][0]
+ (int)ed->y1 * imat[1][0]
+ (int)ed->z1 * imat[2][0]
+ imat[4][0] ;
y = (int)ed->x1 * imat[0][1]
+ (int)ed->y1 * imat[1][1]
+ (int)ed->z1 * imat[2][1]
+ imat[4][1] ;
z = (int)ed->x1 * imat[0][2]
+ (int)ed->y1 * imat[1][2]
+ (int)ed->z1 * imat[2][2]
+ imat[4][2] ;
if (x > 0) {
ed->x1 = imat[3][0] + (short)( ( x + 32767) >> 16 );
} else {
ed->x1 = imat[3][0] - (short)( (-x + 32767) >> 16 );
}
if (y > 0) {
ed->y1 = imat[3][1] + (short)( ( y + 32767) >> 16 );
} else {
ed->y1 = imat[3][1] - (short)( (-y + 32767) >> 16 );
}
if (z > 0) {
ed->z1 = imat[3][2] + (short)( ( z + 32767) >> 16 );
} else {
ed->z1 = imat[3][2] - (short)( (-z + 32767) >> 16 );
}
x = (int)ed->x2 * imat[0][0]
+ (int)ed->y2 * imat[1][0]
+ (int)ed->z2 * imat[2][0]
+ imat[4][0] ;
y = (int)ed->x2 * imat[0][1]
+ (int)ed->y2 * imat[1][1]
+ (int)ed->z2 * imat[2][1]
+ imat[4][1] ;
z = (int)ed->x2 * imat[0][2]
+ (int)ed->y2 * imat[1][2]
+ (int)ed->z2 * imat[2][2]
+ imat[4][2] ;
if (x > 0) {
ed->x2 = imat[3][0] + (short)( ( x + 32767) >> 16 );
} else {
ed->x2 = imat[3][0] - (short)( (-x + 32767) >> 16 );
}
if (y > 0) {
ed->y2 = imat[3][1] + (short)( ( y + 32767) >> 16 );
} else {
ed->y2 = imat[3][1] - (short)( (-y + 32767) >> 16 );
}
if (z > 0) {
ed->z2 = imat[3][2] + (short)( ( z + 32767) >> 16 );
} else {
ed->z2 = imat[3][2] - (short)( (-z + 32767) >> 16 );
}
ed++;
}
return edge;
}
EdgeClass *EdgeLogicalOr(EdgeClass *e1, EdgeClass *e2)
{
int i, pos;
for (i = 0; i < e2->edges; i++) {
if ((pos = EdgeSearchEdge(e1, &e2->edge[i])) < 0) {
e1 = EdgeAppendEdge(e1, &e2->edge[i]);
} else {
e1->edge[pos].count += e2->edge[i].count;
}
}
return e1;
}
EdgeClass *EdgeLogicalSub(EdgeClass *e1, EdgeClass *e2)
{
int i, pos;
for (i = 0; i < e2->edges; i++) {
if ((pos = EdgeSearchEdge(e1, &e2->edge[i])) >= 0) {
e1 = EdgeDeletePos(e1, pos);
}
}
return e1;
}
EdgeClass *EdgeLogicalAnd(EdgeClass *e1, EdgeClass *e2)
{
int i, pos;
EdgeClass *edge;
edge = EdgeAlloc(0);
for (i = 0; i < e2->edges; i++) {
if ((pos = EdgeSearchEdge(e1, &e2->edge[i])) >= 0) {
edge = EdgeAppendEdge(edge, &e1->edge[pos]);
}
}
ObjectFree((Object*)e1);
return edge;
}
EdgeClass *EdgeLogicalXor(EdgeClass *e1, EdgeClass *e2)
{
int i, pos;
for (i = 0; i < e2->edges; i++) {
if ((pos = EdgeSearchEdge(e1, &e2->edge[i])) >= 0) {
e1 = EdgeDeletePos(e1, pos);
} else {
e1 = EdgeAppendEdge(e1, &e2->edge[i]);
}
}
return e1;
}
int EdgeLogicalEqual(EdgeClass *e1, EdgeClass *e2)
{
int i;
for (i = 0; i < e1->edges; i++) {
if (EdgeSearchEdge(e2, &e1->edge[i]) < 0) {
return FALSE;
}
}
for (i = 0; i < e2->edges; i++) {
if (EdgeSearchEdge(e1, &e2->edge[i]) < 0) {
return FALSE;
}
}
return TRUE;
}
EdgeClass *EdgeSelect(void)
{
int i;
EdgeClass *edge;
Polygon *poly ;
edge = EdgeAlloc(0);
poly = PolyTop();
while( poly != NULL )
{
if ( poly->select == ON ) {
for( i = 1; i < poly->vers; ++i) {
edge = EdgeAppend(edge, &poly->ver[i-1], &poly->ver[i]);
}
edge = EdgeAppend(edge, &poly->ver[0], &poly->ver[poly->vers-1]);
}
poly = BufferNext( poly );
}
return edge;
}
EdgeClass *EdgeSelectCount(EdgeClass *edge, int begin, int end)
{
int i, ni;
ni = 0;
for (i = 0; i < edge->edges; ++i) {
if (begin <= edge->edge[i].count && edge->edge[i].count <= end) {
if (ni != i) {
edge->edge[ni] = edge->edge[i];
}
ni++;
}
}
edge->edges = ni;
return edge;
}
static void SelectPoly(Polygon *poly, int sel, int flag, int sw )
/* flag : ON | OFF */
/* sw : UPDATE | AND | OR | XOR */
{
if ( poly->mode & MODE_INVISIBLE )
return ;
if ( ! sel )
flag = ! flag ;
switch( sw & SELECT_LOG )
{
case SELECT_UPDATE:
poly->select = flag ;
break ;
case SELECT_AND:
poly->select &= flag ;
break ;
case SELECT_OR:
poly->select |= flag ;
break ;
case SELECT_XOR:
poly->select ^= flag ;
break ;
default:
assert( FALSE );
}
if ( poly->select )
Selects ++ ;
}
void PolySelectEdge( EdgeClass *edge, int flag, int sw)
{
Polygon *poly ;
PolyPtr = NULL ;
Selects = 0 ;
poly = PolyTop();
while( poly != NULL )
{
SelectPoly( poly, EdgeSearchPoly(edge, poly), flag, sw );
poly = BufferNext( poly );
}
}
void DrawEdge(EdgeClass* edge, int color)
{
int i;
Vertex v1, v2;
for (i = 0; i < edge->edges; i++) {
v1.x = edge->edge[i].x1;
v1.y = edge->edge[i].y1;
v1.z = edge->edge[i].z1;
v2.x = edge->edge[i].x2;
v2.y = edge->edge[i].y2;
v2.z = edge->edge[i].z2;
ViewLine3D(&v1, &v2, color);
}
}