Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
glsmap/smap_makemesh.c
/* Copyright (c) Mark J. Kilgard, 1998. */ |
/* This program is freely distributable without licensing fees |
and is provided without guarantee or warrantee expressed or |
implied. This program is -not- in the public domain. */ |
#include <assert.h> |
#include <stdlib.h> |
#include <math.h> |
#include <glsmap.h> |
#include "glsmapint.h" |
static struct { |
int xl; |
int yl; |
int zl; |
int swap; /* swap final (s,t) */ |
int flip; /* flip final s or t, ie. [0..1] --> [1..0] */ |
float dir; |
} faceInfo[5] = { |
{ 0, 1, 2, 0, 1.0, 1.0 }, /* front */ |
{ 0, 2, 1, 0, -1.0, 1.0 }, /* top */ |
{ 0, 2, 1, 0, 1.0, -1.0 }, /* bottom */ |
{ 1, 2, 0, 1, -1.0, 1.0 }, /* left */ |
{ 1, 2, 0, 1, 1.0, -1.0 }, /* right */ |
}; |
static struct { |
int xl; |
int yl; |
float dir; |
} edgeInfo[4] = { |
{ 0, 1, -1.0 }, |
{ 0, 1, 1.0 }, |
{ 1, 0, -1.0 }, |
{ 1, 0, 1.0 } |
}; |
void |
__smapValidateSphereMapMesh(SphereMapMesh *mesh) |
{ |
/* setup some local variables for variable array size indexing */ |
INITFACE(mesh); |
INITBACK(mesh); |
float st[2]; /* (s,t) coordinate */ |
/* range=[0..1,0..1] */ |
float v[3]; /* (x,y,z) location on cube map */ |
/* range=[-1..1,-1..1,-1..1] */ |
float rv[3]; /* reflection vector, ie. cube map location */ |
/* normalized onto unit sphere */ |
float len; /* distance from v[3] to origin */ |
/* for converting to rv[3] */ |
int side; /* which of 5 faces (all but back face) */ |
int i, j; |
int xl, yl, zl; /* renamed X, Y, Z index */ |
int swap; |
int flip; |
int edge; /* which edge of back face */ |
float sc, tc; /* singularity (s,t) on back face circle */ |
if (mesh->face) { |
assert(mesh->back == &(mesh->face[5*sqsteps])); |
return; |
} |
assert(mesh->back == NULL); |
mesh->face = (STXY*) |
malloc((5*sqsteps+4*ringedspokes) * sizeof(STXY)); |
mesh->back = &(mesh->face[5*sqsteps]); |
/* for the front and four side faces */ |
for (side=0; side<5; side++) { |
/* use faceInfo to parameterize face construction */ |
xl = faceInfo[side].xl; |
yl = faceInfo[side].yl; |
zl = faceInfo[side].zl; |
swap = faceInfo[side].swap; |
flip = faceInfo[side].flip; |
/* cube map "Z" coordinate */ |
v[zl] = faceInfo[side].dir; |
for (i=0; i<mesh->steps; i++) { |
/* cube map "Y" coordinate */ |
v[yl] = 2.0/(mesh->steps-1) * i - 1.0; |
for (j=0; j<mesh->steps; j++) { |
/* cube map "X" coordinate */ |
v[xl] = 2.0/(mesh->steps-1) * j - 1.0; |
/* normalize cube map location to construct */ |
/* reflection vector */ |
len = sqrt(1.0 + v[xl]*v[xl] + v[yl]*v[yl]); |
rv[0] = v[0]/len; |
rv[1] = v[1]/len; |
rv[2] = v[2]/len; |
/* map reflection vector to sphere map (s,t) */ |
/* NOTE: face[side][i][j] (x,y) gets updated */ |
smapRvecToSt(rv, FACExy(side,i,j)); |
/* update texture coordinate, */ |
/* normalize [-1..1,-1..1] to [0..1,0..1] */ |
if (!swap) { |
FACE(side,i,j).s = (-v[xl] + 1.0)/2.0; |
FACE(side,i,j).t = (flip*v[yl] + 1.0)/2.0; |
} else { |
FACE(side,i,j).s = (flip*-v[yl] + 1.0)/2.0; |
FACE(side,i,j).t = (v[xl] + 1.0)/2.0; |
} |
} |
} |
} |
/* The back face must be specially handled. The center |
point in the back face of a cube map becomes a |
a singularity around the circular edge of a sphere map. */ |
/* Carefully work from each edge of the back face to center |
of back face mapped to the outside of the sphere map. */ |
/* cube map "Z" coordinate, always -1 since backface */ |
v[2] = -1; |
/* for each edge */ |
/* [x=-1, y=-1..1, z=-1] */ |
/* [x= 1, y=-1..1, z=-1] */ |
/* [x=-1..1, y=-1, z=-1] */ |
/* [x=-1..1, y= 1, z=-1] */ |
for (edge=0; edge<4; edge++) { |
/* cube map "X" coordinate */ |
v[edgeInfo[edge].xl] = edgeInfo[edge].dir; |
for (j=0; j<mesh->steps; j++) { |
/* cube map "Y" coordinate */ |
v[edgeInfo[edge].yl] = 2.0/(mesh->steps-1) * j - 1.0; |
/* normalize cube map location to construct */ |
/* reflection vector */ |
len = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); |
rv[0] = v[0]/len; |
rv[1] = v[1]/len; |
rv[2] = v[2]/len; |
/* Map reflection vector to sphere map (s,t). */ |
smapRvecToSt(rv, st); |
/* Determine distinance from the center of sphere */ |
/* map (0.5,0.5) to (s,t) */ |
len = sqrt((st[0]-0.5)*(st[0]-0.5) + (st[1]-0.5)*(st[1]-0.5)); |
/* Calculate (s,t) location extended to the singularity */ |
/* at the center of the back face (ie, extend to */ |
/* circle edge of the sphere map). */ |
sc = (st[0]-0.5)/len * 0.5 + 0.5; |
tc = (st[1]-0.5)/len * 0.5 + 0.5; |
/* (s,t) at back face edge. */ |
BACK(edge,0,j).s = (-v[0] + 1.0)/2.0; |
BACK(edge,0,j).t = (-v[1] + 1.0)/2.0; |
BACK(edge,0,j).x = st[0]; |
BACK(edge,0,j).y = st[1]; |
/* If just two rings, we just generate a back face edge |
vertex and a center vertex (2 rings), but if there |
are more rings, we carefully interpolate between the |
edge and center vertices. Notice how smapStToRvec is used |
to map the interpolated (s,t) into a reflection vector |
that must then be extended to the back cube face (it is |
not correct to just interpolate the texture |
coordinates!). */ |
if (mesh->rings > 2) { |
float ist[2]; /* interpolated (s,t) */ |
float ds, dt; /* delta s and delta t */ |
/* Start interpolating from the edge. */ |
ist[0] = st[0]; |
ist[1] = st[1]; |
/* Calculate delta s and delta t for interpolation. */ |
ds = (sc - ist[0]) / (mesh->rings-1); |
dt = (tc - ist[1]) / (mesh->rings-1); |
for (i=1; i<mesh->rings-1; i++) { |
/* Incremental interpolation of (s,t). */ |
ist[0] = ist[0] + ds; |
ist[1] = ist[1] + dt; |
/* Calculate reflection vector from interpolated (s,t). */ |
smapStToRvec(ist, rv); |
/* Assert that z must be on the back cube face. */ |
assert(rv[2] <= -sqrt(1.0/3.0)); |
/* Extend reflection vector out of back cube face. */ |
/* Note: z is negative value so negate z to avoid */ |
/* inverting x and y! */ |
rv[0] = rv[0] / -rv[2]; |
rv[1] = rv[1] / -rv[2]; |
BACK(edge,i,j).s = (-rv[0] + 1.0)/2.0; |
BACK(edge,i,j).t = (-rv[1] + 1.0)/2.0; |
BACK(edge,i,j).x = ist[0]; |
BACK(edge,i,j).y = ist[1]; |
} |
} |
/* (s,t) at circle edge of the sphere map is ALWAYS */ |
/* at center of back cube map face */ |
BACK(edge,mesh->rings-1,j).s = 0.5; |
BACK(edge,mesh->rings-1,j).t = 0.5; |
/* Location of singularity at the edge of the sphere map. */ |
BACK(edge,mesh->rings-1,j).x = sc; |
BACK(edge,mesh->rings-1,j).y = tc; |
if (mesh->edgeExtend) { |
/* Add an extra ring to avoid seeing the */ |
/* tessellation boundary of the sphere map's sphere. */ |
BACK(edge,mesh->rings,j).s = 0.5; |
BACK(edge,mesh->rings,j).t = 0.5; |
/* 0.33 below is a fudge factor. */ |
BACK(edge,mesh->rings,j).x = sc + 0.33*(sc - st[0]); |
BACK(edge,mesh->rings,j).y = tc + 0.33*(tc - st[1]); |
} |
} |
} |
for (edge=0; edge<4; edge++) { |
for (j=0; j<mesh->steps; j++) { |
for (i=1; i<mesh->rings-1; i++) { |
} |
} |
} |
} |
void |
smapConfigureSphereMapMesh(SphereMap *smap, |
int steps, int rings, int edgeExtend) |
{ |
SphereMapMesh *mesh = smap->mesh; |
if (steps == mesh->steps && |
rings == mesh->rings && |
edgeExtend == mesh->edgeExtend) { |
return; |
} |
mesh->steps = steps; |
mesh->rings = rings; |
mesh->edgeExtend = edgeExtend; |
mesh->face = NULL; |
mesh->back = NULL; |
} |
Copyright © 2008 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2008-02-08