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