space.c 11.8 KB

/*====================================================================
 * space.c
 *
 * Copyright 1995, Silicon Graphics, Inc.
 * All Rights Reserved.
 *
 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics,
 * Inc.; the contents of this file may not be disclosed to third
 * parties, copied or duplicated in any form, in whole or in part,
 * without the prior written permission of Silicon Graphics, Inc.
 *
 * RESTRICTED RIGHTS LEGEND:
 * Use, duplication or disclosure by the Government is subject to
 * restrictions as set forth in subdivision (c)(1)(ii) of the Rights
 * in Technical Data and Computer Software clause at DFARS
 * 252.227-7013, and/or in similar or successor clauses in the FAR,
 * DOD or NASA FAR Supplement. Unpublished - rights reserved under the
 * Copyright Laws of the United States.
 *====================================================================*/


#include <ultra64.h>
#include <ultralog.h>
#include "gfx.h"
#include "matrix.h"

#include "mvtview.h"
#include "enterprise_mvt.h"



/* 
 * Mercury orbit parameters
 */
static float mercury_planet_radius = 40;
static float mercury_orbit_radius  = 600;
static float mercury_vertical_off  = 90;
static float mercury_angle         = -15;

/* 
 * Venus orbit parameters
 */
static float venus_planet_radius = 50;
static float venus_orbit_radius  = 700;
static float venus_vertical_off  = 0;
static float venus_angle         = -10;

/* 
 * Earth orbit parameters
 */
static float earth_planet_radius = 50;
static float earth_orbit_radius  = 850;
static float earth_vertical_off  = 0;
static float earth_angle         = 5;

/*
 * Enterprise parameters
 */
static float enterprise_mercury_orbit_radius = 10;
static float enterprise_mercury_angle        = 102.5;
static float enterprise_mercury_speed        = -2.5;
static float enterprise_mercury_pos[3];
static float enterprise_mercury_dir[3] = {-1.75,10,-2.1};
static float enterprise_mercury_rotation;

static float enterprise_venus_orbit_radius = 20;
static float enterprise_venus_angle        = 180;
static float enterprise_venus_speed        = -5;
static float enterprise_venus_pos[3];
static float enterprise_venus_dir[3] = {-2.5,10,0};
static float enterprise_venus_rotation;

static float enterprise_earth_orbit_radius = 20;
static float enterprise_earth_angle        = 0;
static float enterprise_earth_speed        = 2.5;
static float enterprise_earth_pos[3];
static float enterprise_earth_dir[3] = {0.5,5,0};
static float enterprise_earth_rotation;

/*
 * Misc. parameters
 */
static float sun_radius = 50;
static int   mercury_loop = 0;
static int   venus_loop   = 0;
static int   earth_loop   = 0;
static float speed_factor = 1.0;


/*
 * MVT parameters
 */
static int   xluback     = 1;
static int   interpolate = 1;
static float tdelta      = 0.0;
static float mvt_scale   = 0.05;


/*****************************************************************************

Initialize all MVTs.

*****************************************************************************/
static void
spaceInit(void)
{
   MVTinit_template(0, enterprise, ENTERPRISE);

   /*
    * Instance all enterprise ships in the galaxy
    */
   MVTcreate_group(0,MVT_NO_INDEP_ROT);
   MVTinstance_object(0,
               0.0, 0.0, 0.0, 0.0,          /* will get offset by dynamic mtx */
               ENTERPRISE_ANGLE_OFFSET,     /* most probably zero */
               1,                           /* do translates */
               xluback,                     /* xlu background? */
               interpolate,                 /* interpolate between samples */
               mvt_scale,                   /* mvt/geometry scale */
               tdelta,                      /* transition delta for t->g */
               ENTERPRISE_TRANSITION_DIST); /* transition distance */
   MVTcreate_group(0,MVT_NO_INDEP_ROT);
   MVTinstance_object(1,
               0.0, 0.0, 0.0, 0.0,          /* will get offset by dynamic mtx */
               ENTERPRISE_ANGLE_OFFSET,     /* most probably zero */
               1,                           /* do translates */
               xluback,                     /* xlu background? */
               interpolate,                 /* interpolate between samples */
               mvt_scale,                   /* mvt/geometry scale */
               tdelta,                      /* transition delta for t->g */
               ENTERPRISE_TRANSITION_DIST); /* transition distance */

   MVTcreate_group(0,MVT_NO_INDEP_ROT);
   MVTinstance_object(2,
               0.0, 0.0, 0.0, 0.0,          /* will get offset by dynamic mtx */
               ENTERPRISE_ANGLE_OFFSET,     /* most probably zero */
               1,                           /* do translates */
               xluback,                     /* xlu background? */
               interpolate,                 /* interpolate between samples */
               mvt_scale,                   /* mvt/geometry scale */
               tdelta,                      /* transition delta for t->g */
               ENTERPRISE_TRANSITION_DIST); /* transition distance */
}


/*****************************************************************************
*****************************************************************************/
static void
drawPlanet(Mtx *viewing, Mtx *viewing_planet, Mtx *mtx,
           int axis, float init_angle,
           float planet_radius, float orbit_radius, float angle, float voff,
           float planet_pos[3], Gfx *mtx_dl, Gfx *gfx_dl)
{
   Mtx scale,trans,rot,rot_in_place;

   if (orbit_radius != 0.0) {
      /* compute planet rotation/position */
      guTranslate(&trans, 0, orbit_radius, voff);
      guRotate(&rot, angle, 0, 0, 1);
      if (axis == 0)
         guRotate(&rot_in_place, init_angle, 1, 0, 0);
      else if (axis == 1)
         guRotate(&rot_in_place, init_angle, 0, 1, 0);
      else if (axis == 2)
         guRotate(&rot_in_place, init_angle, 0, 0, 1);
      guScale(&scale, planet_radius/100.0,
                      planet_radius/100.0, 
                      planet_radius/100.0);
      multMtx(mtx,&scale,&rot_in_place);
      multMtx(mtx,mtx,&trans);

      multMtx(viewing_planet,&rot,viewing);

      planet_pos[0] = planet_pos[1] = planet_pos[2] = 0;
      multMtxPos(planet_pos,&trans,planet_pos);
      multMtxPos(planet_pos,&rot,  planet_pos);

   } else {
      planet_pos[0] = planet_pos[1] = planet_pos[2] = 0;
      copyMtx(viewing_planet,viewing);
      guScale(mtx, planet_radius/100.0,
                   planet_radius/100.0, 
                   planet_radius/100.0);
   }


   /* set matrices and draw geometry */
   if (mtx_dl) gSPDisplayList(glistp++, mtx_dl);
   if (gfx_dl) gSPDisplayList(glistp++, gfx_dl);
}


/*****************************************************************************
*****************************************************************************/
static void
MVTorbitShip(int object_id, float planet_pos[3], float planet_radius,
          float planet_angle, float ship_orbit_radius, float ship_angle,
          float init_rotation, float ship_pos[3], float *rotation)
{
   Mtx   ship_mtx,rotate_in_orbit,trans_to_orbit,trans_to_planet;

   guRotate(&rotate_in_orbit,ship_angle,0.0,0.0,1.0);
   guTranslate(&trans_to_orbit,0.0,planet_radius+ship_orbit_radius,0.0);
   guTranslate(&trans_to_planet,planet_pos[0],planet_pos[1],planet_pos[2]);

   makeIdentMtx(&ship_mtx);
   multMtx(&ship_mtx,&ship_mtx,&trans_to_orbit);
   multMtx(&ship_mtx,&ship_mtx,&rotate_in_orbit);
   multMtx(&ship_mtx,&ship_mtx,&trans_to_planet);

   ship_pos[0] = ship_pos[1] = ship_pos[2] = 0.0;
   multMtxPos(ship_pos, &ship_mtx, ship_pos);
   *rotation = ship_angle + init_rotation;
   if (*rotation >  180) *rotation = -1*(360 - *rotation);
   if (*rotation < -180) *rotation =  1*(*rotation + 360);

   MVTset_position(object_id, ship_pos, *rotation);
}


/*****************************************************************************
*****************************************************************************/
static void 
MVTdirectShip(int object_id,  float ship_pos[3], float dir[3], float rotation)
{
   ship_pos[0] += speed_factor*dir[0];
   ship_pos[1] += speed_factor*dir[1];
   ship_pos[2] += speed_factor*dir[2];

   MVTset_position(object_id, ship_pos, rotation);
}


/*****************************************************************************
*****************************************************************************/
void 
spaceMain(Dynamic *dynamicp, float eyept[3])
{
    static u8 firstcall = 1;
    float sun_pos[3];
    float mercury_pos[3];
    float venus_pos[3];
    float earth_pos[3];

    /*
     * First time initialization
     */
    if (firstcall) {
       spaceInit();
       firstcall = 0;
    }

    drawPlanet(&dynamicp->viewing, &dynamicp->viewing_sun, &dynamicp->sun, 
               0, 0.0, sun_radius, 0.0, 0.0,
               0.0, sun_pos, sun_matrix, sun_dl);
    drawPlanet(&dynamicp->viewing,&dynamicp->viewing_mercury,&dynamicp->mercury,
               0, 0.0, mercury_planet_radius,mercury_orbit_radius,mercury_angle,
               mercury_vertical_off, mercury_pos, mercury_matrix, mercury_dl);
    drawPlanet(&dynamicp->viewing, &dynamicp->viewing_venus, 
               &dynamicp->venus, 2, -110.0 /*80.0*/,
               venus_planet_radius, venus_orbit_radius, venus_angle, 
               venus_vertical_off, venus_pos, 
               venus_matrix, craterplanet_dl);
    drawPlanet(&dynamicp->viewing, &dynamicp->viewing_earth, &dynamicp->earth, 
               0, 30.0, earth_planet_radius, earth_orbit_radius, earth_angle, 
               earth_vertical_off, earth_pos, 
               earth_matrix, earth_dl);

    if (enterprise_mercury_angle <= 100) {
       MVTdirectShip(0, enterprise_mercury_pos, enterprise_mercury_dir, 
                     enterprise_mercury_rotation);
       if (enterprise_mercury_pos[1] > 1000) 
          enterprise_mercury_angle = 180;
       else
          enterprise_mercury_angle = 100;
    } else
       MVTorbitShip(0,
              mercury_pos, mercury_planet_radius, mercury_angle,
              enterprise_mercury_orbit_radius, enterprise_mercury_angle, 
              -90.0, enterprise_mercury_pos, &enterprise_mercury_rotation);

    if (enterprise_venus_angle <= 115) {
       MVTdirectShip(1, enterprise_venus_pos, enterprise_venus_dir, 
                     enterprise_venus_rotation);
       if (enterprise_venus_pos[1] > 1300) 
          enterprise_venus_angle = 180;
       else
          enterprise_venus_angle = 115;
    } else 
       MVTorbitShip(1,
              venus_pos, venus_planet_radius, venus_angle,
              enterprise_venus_orbit_radius, enterprise_venus_angle, 
              -90.0, enterprise_venus_pos, &enterprise_venus_rotation);

    if (enterprise_earth_angle >= 266) {
       MVTdirectShip(2, enterprise_earth_pos, enterprise_earth_dir, 
                     enterprise_earth_rotation);
       if (enterprise_earth_pos[1] > 1300) 
          enterprise_earth_angle = 0;
       else
          enterprise_earth_angle = 266;
    }
    else 
       MVTorbitShip(2,
              earth_pos, earth_planet_radius, earth_angle,
              enterprise_earth_orbit_radius, enterprise_earth_angle, 
              90.0, enterprise_earth_pos, &enterprise_earth_rotation);

    MVTdraw(dynamicp, eyept);


    /* compute for next ship orbit positions */
    enterprise_mercury_angle += speed_factor*enterprise_mercury_speed;
    enterprise_venus_angle   += speed_factor*enterprise_venus_speed;
    enterprise_earth_angle   += speed_factor*enterprise_earth_speed;

    if (enterprise_mercury_angle > 360)
        enterprise_mercury_angle -= 360;
    if (enterprise_mercury_angle < 0)
        enterprise_mercury_angle += 360;
    if (enterprise_venus_angle > 360)
        enterprise_venus_angle   -= 360;
    if (enterprise_venus_angle < 0)
        enterprise_venus_angle   += 360;
    if (enterprise_earth_angle > 360)
        enterprise_earth_angle   -= 360;
    if (enterprise_earth_angle < 0)
        enterprise_earth_angle   += 360;
}