brender-1997/v1db/modsupt.c
2022-05-03 14:31:40 -07:00

269 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);
}