Have a better lookat() ?
Thant Tessman
thant at horus.esd.sgi.com
Thu Apr 4 03:28:53 AEST 1991
Here is my twice-yearly posting of an alternative to the lookat command:
To compile: cc example.c upat.c -lgl_s -lm -o example
----------------------cut here--------------------------
#!/bin/sh -v
# this is a shell archive (once) named upat.mail
# created by thant at horus at Thu Jan 17 08:59:48 PST 1991
#
# The rest of this file is a shell script which will extract:
# example.c
# upat.c
#
# to use, type sh upat.mail
#
echo x - example.c
cat > example.c << 'EndOfRecord'
#include <gl.h>
#include <device.h>
extern void upat(float vx, float vy, float vz,
float px, float py, float pz,
float ux, float uy, float uz);
main() {
int dev;
short val;
float i, j, k;
initialize();
/* first flyby */
printf("Y is up. (Just like lookat.)\n");
j = 2.0;
for (i = -8.0, k=12.0; i<12.0; i+=0.05, k-=0.05) {
color(BLACK); clear();
perspective(400, 5.0/4.0, 1.0, 50.0);
upat(i, j, k,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0);
draw_axes();
swapbuffers();
}
/* second flyby */
printf("Z is up, but same path.\n");
j = 2.0;
for (i = -8.0, k=12.0; i<12.0; i+=0.05, k-=0.05) {
color(BLACK); clear();
perspective(400, 5.0/4.0, 1.0, 50.0);
upat(i, j, k,
0.0, 0.0, 0.0,
0.0, 0.0, 1.0);
draw_axes();
swapbuffers();
}
/* third flyby */
printf("(1, 1, 1) is up. Different path.\n");
for (i = -8.0, j=10.0, k=12.0; i<12.0; i+=0.05, k-=0.05, j-=0.05) {
color(BLACK); clear();
perspective(400, 5.0/4.0, 1.0, 50.0);
upat(i, j, k,
0.0, 0.0, 0.0,
1.0, 1.0, 1.0);
draw_axes();
swapbuffers();
}
}
initialize() {
keepaspect(5, 4);
winopen("");
doublebuffer();
gconfig();
qdevice(ESCKEY);
}
draw_axes() {
color(RED);
move(0.0, 0.0, 0.0);
draw(1.0, 0.0, 0.0);
cmov(1.2, 0.0, 0.0);
charstr("x");
color(GREEN);
move(0.0, 0.0, 0.0);
draw(0.0, 1.0, 0.0);
cmov(0.0, 1.2, 0.0);
charstr("y");
color(BLUE);
move(0.0, 0.0, 0.0);
draw(0.0, 0.0, 1.0);
cmov(0.0, 0.0, 1.2);
charstr("z");
color(WHITE);
move(0.5, 0.5, 0.5);
draw(0.5, 0.5, 0.0);
move(0.5, 0.0, 0.0);
draw(0.5, 0.5, 0.0);
draw(0.0, 0.5, 0.0);
move(0.5, 0.5, 0.5);
draw(0.0, 0.5, 0.5);
move(0.0, 0.5, 0.0);
draw(0.0, 0.5, 0.5);
draw(0.0, 0.0, 0.5);
move(0.5, 0.5, 0.5);
draw(0.5, 0.0, 0.5);
move(0.5, 0.0, 0.0);
draw(0.5, 0.0, 0.5);
draw(0.0, 0.0, 0.5);
}
EndOfRecord
len=`wc -c < example.c `
if [ $len != 1993 ] ; then
echo error: example.c was $len bytes long, should have been 1993
fi
echo x - upat.c
cat > upat.c << 'EndOfRecord'
#include "math.h"
#include "gl.h"
#include "stdio.h"
#define X 0
#define Y 1
#define Z 2
void normalize(float *);
void cross(float *result, float *v1, float *v2);
void upat(float vx, float vy, float vz,
float px, float py, float pz,
float ux, float uy, float uz) {
int i;
float forward[3], side[3], up[3];
float m[4][4];
forward[X] = px - vx;
forward[Y] = py - vy;
forward[Z] = pz - vz;
up[X] = ux; /* temporarily use view-up to hold world-up */
up[Y] = uy;
up[Z] = uz;
normalize(forward);
/* make side from view forward and world up */
cross(side, forward, up);
normalize(side);
/* make view up from view forward and view side */
cross(up, side, forward);
m[0][0] = side[X];
m[1][0] = side[Y];
m[2][0] = side[Z];
m[3][0] = 0.0;
m[0][1] = up[X];
m[1][1] = up[Y];
m[2][1] = up[Z];
m[3][1] = 0.0;
m[0][2] = -forward[X];
m[1][2] = -forward[Y];
m[2][2] = -forward[Z];
m[3][2] = 0.0;
m[0][3] = 0.0;
m[1][3] = 0.0;
m[2][3] = 0.0;
m[3][3] = 1.0;
multmatrix(m);
translate(-vx, -vy, -vz);
}
void normalize(float *v) {
float r;
r = sqrt( v[X]*v[X] + v[Y]*v[Y] + v[Z]*v[Z] );
v[X] /= r;
v[Y] /= r;
v[Z] /= r;
}
void cross(float *result, float *v1, float *v2) {
result[X] = v1[Y]*v2[Z] - v1[Z]*v2[Y];
result[Y] = v1[Z]*v2[X] - v1[X]*v2[Z];
result[Z] = v1[X]*v2[Y] - v1[Y]*v2[X];
}
EndOfRecord
len=`wc -c < upat.c `
if [ $len != 1480 ] ; then
echo error: upat.c was $len bytes long, should have been 1480
fi
More information about the Comp.sys.sgi
mailing list