270 lines
5.9 KiB
C
270 lines
5.9 KiB
C
|
/*
|
||
|
* Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved.
|
||
|
*
|
||
|
* $Id: modsupt.c 2.5 1997/04/09 15:47:03 TOMN Exp $
|
||
|
* $Locker: $
|
||
|
*
|
||
|
* Model support routines
|
||
|
Last change: TN 4 Apr 97 11:15 am
|
||
|
*/
|
||
|
#include "v1db.h"
|
||
|
#include "shortcut.h"
|
||
|
#include "brassert.h"
|
||
|
|
||
|
BR_RCS_ID("$Id: modsupt.c 2.5 1997/04/09 15:47:03 TOMN Exp $")
|
||
|
|
||
|
/*
|
||
|
* Generate U and V values for a model's vertices.
|
||
|
*
|
||
|
* The vertices are optionally transformed by a 3x4 matrix
|
||
|
*
|
||
|
* The u,v values are then assigned according to one of the
|
||
|
* following schemes -
|
||
|
*
|
||
|
* Planar mapping:
|
||
|
* u = (x+1)/2
|
||
|
* v = (y+1)/2
|
||
|
*
|
||
|
* Spherical mapping:
|
||
|
* u = atan2(-z,x)/2*pi
|
||
|
* v = 1-atan2(sqrt(x*x+z*z),y)/pi
|
||
|
*
|
||
|
* Cylindrical mapping:
|
||
|
* u = atan2(-z,x)/2*pi
|
||
|
* v = (y+1)/2
|
||
|
*
|
||
|
* Disc mapping:
|
||
|
* u = atan2(-z,x)/2*pi
|
||
|
* v = sqrt(x*x+z*z)
|
||
|
*/
|
||
|
void BR_PUBLIC_ENTRY BrModelApplyMap(br_model *model,int map_type, br_matrix34 *xform)
|
||
|
{
|
||
|
int v;
|
||
|
br_vertex *vp;
|
||
|
br_vector3 mv;
|
||
|
br_matrix34 default_xform;
|
||
|
br_scalar d;
|
||
|
|
||
|
UASSERT_MESSAGE("BrModelApplyMap NULL pointer to a model", model != NULL);
|
||
|
UASSERT(model->vertices != NULL);
|
||
|
UASSERT(map_type >= 0 && map_type <= BR_APPLYMAP_NONE);
|
||
|
|
||
|
/*
|
||
|
* If no default provided, use identity
|
||
|
*/
|
||
|
if(xform == NULL) {
|
||
|
BrMatrix34Identity(&default_xform);
|
||
|
xform = &default_xform;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Set mapping for each vertex
|
||
|
*/
|
||
|
for(v=0, vp=model->vertices; v < model->nvertices; v++, vp++) {
|
||
|
BrMatrix34ApplyP(&mv,&vp->p,xform);
|
||
|
|
||
|
switch(map_type) {
|
||
|
case BR_APPLYMAP_NONE:
|
||
|
/*
|
||
|
* No mapping:
|
||
|
* u = 0
|
||
|
* v = 0
|
||
|
*/
|
||
|
vp->map.v[0] = BR_SCALAR(0.0);
|
||
|
vp->map.v[1] = BR_SCALAR(0.0);
|
||
|
break;
|
||
|
|
||
|
case BR_APPLYMAP_PLANE:
|
||
|
/*
|
||
|
* Planar mapping:
|
||
|
* u = (x+1)/2
|
||
|
* v = (y+1)/2
|
||
|
*/
|
||
|
vp->map.v[0] = BR_MUL(mv.v[0]+BR_SCALAR(1.0),
|
||
|
BrFractionToScalar(BR_FRACTION(0.5)));
|
||
|
|
||
|
vp->map.v[1] = BR_MUL(mv.v[1]+BR_SCALAR(1.0),
|
||
|
BrFractionToScalar(BR_FRACTION(0.5)));
|
||
|
break;
|
||
|
|
||
|
case BR_APPLYMAP_SPHERE:
|
||
|
/*
|
||
|
* Spherical mapping:
|
||
|
* u = atan2(-z,x)/2*pi
|
||
|
* v = 1-atan2(sqrt(x*x+z*z),y)/pi
|
||
|
*/
|
||
|
vp->map.v[0] = BR_DIV(
|
||
|
BrAngleToDegree(BR_ATAN2(-mv.v[2],mv.v[0])),
|
||
|
BR_SCALAR(360.0));
|
||
|
|
||
|
d = BR_LENGTH2(mv.v[0],mv.v[2]);
|
||
|
|
||
|
vp->map.v[1] = BR_SCALAR(1.0) - BR_DIV(
|
||
|
BrAngleToDegree(BR_ATAN2(d,mv.v[1])),
|
||
|
BR_SCALAR(180.0));
|
||
|
|
||
|
break;
|
||
|
|
||
|
case BR_APPLYMAP_CYLINDER:
|
||
|
/*
|
||
|
* Cylindrical mapping:
|
||
|
* u = atan2(-z,x)/2*pi
|
||
|
* v = (y+1)/2
|
||
|
*/
|
||
|
vp->map.v[0] = BR_DIV(
|
||
|
BrAngleToDegree(BR_ATAN2(-mv.v[2],mv.v[0])),
|
||
|
BR_SCALAR(360.0));
|
||
|
|
||
|
vp->map.v[1] = BR_MUL(mv.v[1]+BR_SCALAR(1.0),
|
||
|
BrFractionToScalar(BR_FRACTION(0.5)));
|
||
|
break;
|
||
|
|
||
|
|
||
|
case BR_APPLYMAP_DISC:
|
||
|
/*
|
||
|
* Disc mapping:
|
||
|
* u = atan2(-y,x)/2*pi
|
||
|
* v = sqrt(x*x+y*y)
|
||
|
*/
|
||
|
vp->map.v[0] = BR_DIV(
|
||
|
BrAngleToDegree(BR_ATAN2(-mv.v[1],mv.v[0])),
|
||
|
BR_SCALAR(360.0));
|
||
|
|
||
|
vp->map.v[1] = BR_LENGTH2(mv.v[0],mv.v[1]);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Work out a transform such that it can be fed to BrModelApplyMap
|
||
|
* and have the mapping type fit the bounds of the model exactly
|
||
|
*
|
||
|
* The two axis along which the mapping can be applied are provided -
|
||
|
*
|
||
|
* BR_FITMAP_PLUS_X,
|
||
|
* BR_FITMAP_PLUS_Y,
|
||
|
* BR_FITMAP_PLUS_Z,
|
||
|
* BR_FITMAP_MINUS_X,
|
||
|
* BR_FITMAP_MINUS_Y,
|
||
|
* BR_FITMAP_MINUS_Z,
|
||
|
*
|
||
|
* Returns the supplied pointer to 'transform'
|
||
|
*/
|
||
|
|
||
|
br_matrix34 * BR_PUBLIC_ENTRY BrModelFitMap(br_model *model, int axis_0, int axis_1, br_matrix34 *transform)
|
||
|
{
|
||
|
br_vector3 axis_3;
|
||
|
br_vector3 tr;
|
||
|
br_vector3 sc;
|
||
|
int i;
|
||
|
|
||
|
static br_vector3 axis_vectors[] = {
|
||
|
BR_VECTOR3( 1, 0, 0), /* +X */
|
||
|
BR_VECTOR3( 0, 1, 0), /* +Y */
|
||
|
BR_VECTOR3( 0, 0, 1), /* +Z */
|
||
|
BR_VECTOR3(-1, 0, 0), /* -X */
|
||
|
BR_VECTOR3( 0,-1, 0), /* -Y */
|
||
|
BR_VECTOR3( 0, 0,-1), /* -Z */
|
||
|
};
|
||
|
|
||
|
UASSERT(model != NULL);
|
||
|
UASSERT(transform != NULL);
|
||
|
UASSERT(axis_0 >= BR_FITMAP_PLUS_X && axis_0 <= BR_FITMAP_MINUS_Z);
|
||
|
UASSERT(axis_1 >= BR_FITMAP_PLUS_X && axis_1 <= BR_FITMAP_MINUS_Z);
|
||
|
|
||
|
/*
|
||
|
* Start the mapping transform by filling in the two user
|
||
|
* supplied axes (as columns), and then using a cross product to generate
|
||
|
* the third column.
|
||
|
*/
|
||
|
BrMatrix34Identity(transform);
|
||
|
|
||
|
BrVector3Cross(&axis_3,
|
||
|
axis_vectors + axis_0,
|
||
|
axis_vectors + axis_1);
|
||
|
|
||
|
for(i=0; i< 3; i++) {
|
||
|
transform->m[i][0] = axis_vectors[axis_0].v[i];
|
||
|
transform->m[i][1] = axis_vectors[axis_1].v[i];
|
||
|
transform->m[i][2] = axis_3.v[i];
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Find the translation to align the object with the mapping
|
||
|
*/
|
||
|
for(i=0; i< 3; i++)
|
||
|
tr.v[i] = -(BR_CONST_DIV(model->bounds.max.v[i],2) +
|
||
|
BR_CONST_DIV(model->bounds.min.v[i],2));
|
||
|
|
||
|
/*
|
||
|
* Find the scale to fit object to the mapping
|
||
|
*/
|
||
|
for(i=0; i< 3; i++)
|
||
|
if(model->bounds.max.v[i] != model->bounds.min.v[i])
|
||
|
sc.v[i] = BR_RCP(BR_CONST_DIV(model->bounds.max.v[i],2) -
|
||
|
BR_CONST_DIV(model->bounds.min.v[i],2));
|
||
|
else
|
||
|
sc.v[i] = BR_SCALAR(1.0);
|
||
|
|
||
|
BrMatrix34PreScale(transform,sc.v[0],sc.v[1],sc.v[2]);
|
||
|
BrMatrix34PreTranslate(transform,tr.v[0],tr.v[1],tr.v[2]);
|
||
|
|
||
|
return transform;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Free a model
|
||
|
*/
|
||
|
void BR_PUBLIC_ENTRY BrModelFree(br_model *m)
|
||
|
{
|
||
|
UASSERT(m != NULL);
|
||
|
|
||
|
BrResFree(m);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Allocate a model of a given size
|
||
|
*/
|
||
|
br_model * BR_PUBLIC_ENTRY BrModelAllocate(char *name, int nvertices, int nfaces)
|
||
|
{
|
||
|
br_model *m;
|
||
|
|
||
|
UASSERT(nvertices >= 0);
|
||
|
UASSERT(nfaces >= 0);
|
||
|
|
||
|
m = BrResAllocate(v1db.res,sizeof(*m),BR_MEMORY_MODEL);
|
||
|
|
||
|
m->nvertices = nvertices;
|
||
|
m->nfaces = nfaces;
|
||
|
|
||
|
if(name)
|
||
|
m->identifier = BrResStrDup(m, name);
|
||
|
|
||
|
if(nvertices)
|
||
|
m->vertices = BrResAllocate(m, nvertices*sizeof(*m->vertices),BR_MEMORY_VERTICES);
|
||
|
|
||
|
if(nfaces)
|
||
|
m->faces = BrResAllocate(m, nfaces * sizeof(*m->faces),BR_MEMORY_FACES);
|
||
|
|
||
|
return m;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Allocate a primitive list of the given type and size.
|
||
|
*/
|
||
|
br_primitive_list * BR_PUBLIC_ENTRY BrPrimitiveListAllocate(br_uint_32 prim_type, br_uint_16 num_prims)
|
||
|
{
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Add the primitive list passed to the model passed.
|
||
|
*/
|
||
|
br_uint_32 BR_PUBLIC_ENTRY BrModelAddPrimitiveList(br_model *model, br_primitive_list *primitive_list)
|
||
|
{
|
||
|
return(0);
|
||
|
}
|
||
|
|