home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Photo CD Demo 1
/
Demo.bin
/
gems
/
gemsiii
/
hemis.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-07
|
7KB
|
252 lines
/*
Hemispherical Projection of a Triangle
Buming Bian
UT System---Center for High Performance Computing
Austin, Texas
*/
#include <math.h>
#include <stdio.h>
#include "GraphicsGems.h"
#include "GraphicsGems.c"
#define HOMON 4
#define PONPATCH 3
#define ERR 1.0e-10
#define ONE 1 - ERR
/* types of structures */
typedef struct {
Point3 pt[PONPATCH]; /* Vertices coordinates */
double ref; /* Reflectivity of the patch */
double trs; /* transmittance of the patch */
} Patch;
/* return a patch normal. */
Vector3 *patchnorm(suf)
Patch *suf;
{
Vector3 *vt1 = NEWTYPE(Vector3);
Vector3 *vt2 = NEWTYPE(Vector3);
Vector3 *norm = NEWTYPE(Vector3);
vt1 = V3Sub(&suf->pt[1], &suf->pt[0], vt1);
vt2 = V3Sub(&suf->pt[2], &suf->pt[0], vt2);
norm = V3Normalize(V3Cross(vt1, vt2, norm));
free(vt1); free(vt2);
return(norm);
}
/******************************************************************************
* Compute the form factor. Homogeneous transformation is applied to the two *
* input Patches such that the center of patch suf1 located at origin with *
* its normal coinciding with z axis. A hemisphere is constructed above the xy*
* plane, patch suf2 is projected on the hemisphere to form a spherical *
* triangle. This spherical triangle is again projected on the xy plane and *
* the projected area is the form factor of patch suf2 to patch suf1. *
******************************************************************************/
double hemisphere(suf1, suf2)
Patch *suf1, *suf2;
{
int i, j;
double out, hm[HOMON][HOMON], projectarea();
Vector3 *vect[PONPATCH];
void patchtransf(), ghmgn();
/* use patch suf1 to form the homogeneous transformation matrix */
ghmgn(suf1, hm);
/* apply the transformation to patch suf2 */
patchtransf(hm, suf2);
/* represent the vertices with vectors */
for (i = 0; i < PONPATCH; i++)
vect[i] = V3New(suf2->pt[i].x, suf2->pt[i].y, suf2->pt[i].z);
/* Normalize the form factor so the all sub-total of the form factor */
out = projectarea(vect);
for (i = 0; i < PONPATCH; i++)
free(vect[i]);
return(ABS(out/PI));
}
/* Calculate the form factor by adding up all the ellipse sectors formed by two
* neighbor points */double projectarea(vect)
Vector3 *vect[PONPATCH];
{
int i;
double out= 0, twopntarea();
for (i = 0; i < PONPATCH; i++)
out += twopntarea(vect[i], vect[(i+1)%PONPATCH]);
return(out);
}
/* Calculate the area of the ellipsoid triangle */double twopntarea(vect1, vect2)
Vector3 *vect1, *vect2;
{
double a, b;
double sum, cos_sita, halfsita, halfa, d1, d2;
double arccos(), arctan();
Vector3 *major, *norm, *v;
/* Find out the normal vector of the great circle */
major = V3New(0, 0, 1.0);
norm = V3Duplicate(vect1);
v = NEWTYPE(Vector3);
norm = V3Normalize(V3Cross(norm, vect2, v));
cos_sita = ABS(V3Dot(major, norm));
if (cos_sita < ERR){
/* if the normal vector is perpendicular to z axis, form factor is zero */
sum = 0.0;
free(norm);
free(major);
return(sum);
}
halfsita = cos_sita / 2.0;
halfa = PI * halfsita;
if (cos_sita < ONE){
/* project the great circle on to the equatorial plane and calculate the form factor */
major = V3Normalize(V3Cross(major, norm, v));
norm->x *= -1; norm->y *= -1; norm->z = 0;
d1 = sqrt(V3Dot(vect1, vect1));
d2 = sqrt(V3Dot(vect2, vect2));
a = V3Dot(major, vect1) / d1;
if (ABS(a) > 1.0) a /= ABS(a);
b = V3Dot(norm, vect1);
sum = arccos(a, b);
a = V3Dot(major, vect2) / d2;
if (ABS(a) > 1.0) a /= ABS(a);
b = V3Dot(norm, vect2);
sum -= arccos(a, b);
}
else{
/* if the normal vector is parallel to z axis, form factor is maximum */
sum = arctan(vect1->x, vect1->y);
sum -= arctan(vect2->x, vect2->y);
}
sum *= halfsita;
free(norm); free(major); free(v);
if (sum > halfa) sum -= 2.0 * halfa;
else if (sum < -halfa) sum += 2.0 * halfa;
return(sum);
}
double arccos(x, y)
double x, y;
{
double angle;
angle = acos(x);
if (y < 0) angle = 2 * PI - angle;
return(angle);
}
double arctan(x, y)
double x, y;
{
double angle;
angle = atan2(y, x);
if (y < 0) angle = 2 * PI + angle;
return(angle);
}
/* Derive the homogenous transformation matrix for the given patch */
void ghmgn(suf, hm)
Patch *suf;
double hm[HOMON][HOMON];
{
int i, j;
Vector3 *v1;
Point3 *pnt = NEWTYPE(Vector3);
double a, b, c, d, x1, y1, z1;
double tt[HOMON][HOMON], tr1[HOMON][HOMON];
double tr2[HOMON][HOMON], rr[HOMON][HOMON];
void mtxprd();
pnt->x = (suf->pt[0].x+suf->pt[1].x+suf->pt[2].x)/PONPATCH;
pnt->y = (suf->pt[0].y+suf->pt[1].y+suf->pt[2].y)/PONPATCH;
pnt->z = (suf->pt[0].z+suf->pt[1].z+suf->pt[2].z)/PONPATCH;
for (i = 0; i < HOMON; i++)
for (j = 0; j < HOMON; j++)
if (i == j){
tt[i][j] = 1.0; tr1[i][j] = 1.0; tr2[i][j] = 1.0; }
else{
tt[i][j] = 0; tr1[i][j] = 0; tr2[i][j] = 0; }
v1 = patchnorm(suf);
tt[3][0] = -pnt->x; tt[3][1] = -pnt->y; tt[3][2] = -pnt->z;
free(pnt);
d = sqrt(SQR(v1->y)+SQR(v1->z));
if (d > ERR){
tr1[0][0] = 1;
tr1[3][3] = 1;
tr1[1][1] = v1->z/d;
tr1[2][2] = v1->z/d;
tr1[2][1] = -v1->y/d;
tr1[1][2] = v1->y/d;
}
mtxprd(tt, tr1, rr);
tr2[0][0] = d; tr2[2][2] = d; tr2[2][0] = -v1->x; tr2[0][2] = v1->x;
free(v1);
mtxprd(rr, tr2, hm);
}
/* Transform a given patch */
void patchtransf(hm, suf)
double hm[HOMON][HOMON];
Patch *suf;
{
int i;
void pnttransf();
for (i = 0; i < PONPATCH; i++)
pnttransf(hm, &suf->pt[i]);
}
/* Transform a given point */
void pnttransf(hm, pnt)
double hm[HOMON][HOMON];
Point3 *pnt;
{
int i;
double hi[HOMON], ho[HOMON];
void transform();
hi[0] = pnt->x; hi[1] = pnt->y; hi[2] = pnt->z; hi[3] = 1.;
transform(hm, hi, ho);
pnt->x = ho[0] / ho[3]; pnt->y = ho[1] / ho[3]; pnt->z = ho[2] / ho[3];
}
/* Transform a given vector */
void vecttransf(hm, vect)
double hm[HOMON][HOMON];
Vector3 *vect;
{
int i;
double hi[HOMON], ho[HOMON];
void transform();
hi[0] = vect->x; hi[1] = vect->y; hi[2] = vect->z; hi[3] = 0.;
transform(hm, hi, ho);
vect->x = ho[0]; vect->y = ho[1]; vect->z = ho[2];
}
/* Transform a given vector */
void transform(hm, hi, ho)
double hm[HOMON][HOMON];
double hi[HOMON], ho[HOMON];
{
int j, k;
for (j = 0; j < HOMON; j++){
ho[j] = 0;
for (k = 0; k < HOMON; k++)
ho[j] += hi[k] * hm[k][j];
}
}
/* Multiple two matrices */
void mtxprd(h1, h2, h3)
double h1[HOMON][HOMON], h2[HOMON][HOMON],h3[HOMON][HOMON];
{
int i, j, k;
for (i = 0; i < HOMON; i++)
for (j = 0; j < HOMON; j++){
h3[i][j] = 0;
for (k = 0; k < HOMON; k++)
h3[i][j] += h1[i][k] * h2[k][j];
}
}