home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Virtual Reality Homebrewer's Handbook
/
vr.iso
/
vr386
/
wparse.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-03-19
|
34KB
|
1,338 lines
/* Read a World Description File */
/* Original read-world and format by Bernie Roehl, July 1992 */
/* Rewritten for animation and configuration by Dave Stampe Oct. '92 */
// Massively rewritten to port to VR-386 API by Dave Stampe 9/1/94
// The .WLD file format is for compatibility with REND386 V5.0,
// and with "Virtual Reality Creations"
// FUTURE WORLD LOADING MAY LOOK VERY DIFFERENT, AND BE MUCH BETTER
/*
This code is part of the VR-386 project, created by Dave Stampe.
VR-386 is a desendent of REND386, created by Dave Stampe and
Bernie Roehl. Almost all the code has been rewritten by Dave
Stampre for VR-386.
Copyright (c) 1994 by Dave Stampe:
May be freely used to write software for release into the public domain
or for educational use; all commercial endeavours MUST contact Dave Stampe
(dstampe@psych.toronto.edu) for permission to incorporate any part of
this software or source code into their products! Usually there is no
charge for under 50-100 items for low-cost or shareware products, and terms
are reasonable. Any royalties are used for development, so equipment is
often acceptable payment.
ATTRIBUTION: If you use any part of this source code or the libraries
in your projects, you must give attribution to VR-386 and Dave Stampe,
and any other authors in your documentation, source code, and at startup
of your program. Let's keep the freeware ball rolling!
DEVELOPMENT: VR-386 is a effort to develop the process started by
REND386, improving programmer access by rewriting the code and supplying
a standard API. If you write improvements, add new functions rather
than rewriting current functions. This will make it possible to
include you improved code in the next API release. YOU can help advance
VR-386. Comments on the API are welcome.
CONTACT: dstampe@psych.toronto.edu
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <alloc.h>
#include <dos.h> /* delay() */
#include "config.h"
#include "vr_api.h"
#include "oldtasks.h"
#include "intmath.h"
#include "splits.h"
#include "pcdevice.h"
#include "segment.h"
int old_angle_order = 0; /* if non-zero, camera angles are pan,tilt,roll */
extern int do_screen_clear;
extern int flymode, floormode;
extern unsigned char palette[];
extern int npalette;
extern TASK *tasklist;
extern char *fix_fname(char *fname);
static int keep_around = 0; /* if non-zero, don't use temp for names */
/**************** NAMED LIST SUPPORT **************/
typedef struct _name NAMEREF;
struct _name {
char *name;
void *value;
NAMEREF *next;
};
extern void *temp_mem;
extern long temp_size;
NAMEREF *add_name(NAMEREF **list, char *name, void *value)
{
NAMEREF *p;
/* check if temp usable */
if (!keep_around && (temp_mem) &&
(temp_size>(sizeof(NAMEREF)+strlen(name)+1)))
{
p = temp_mem;
temp_mem = ((char *)temp_mem) + sizeof(NAMEREF);
p->name = temp_mem;
temp_mem = ((char *)temp_mem) + strlen(name) + 1;
strcpy(p->name, name);
temp_size -= sizeof(NAMEREF)+strlen(name)+1;
}
else /* use heap */
{
temp_mem = NULL;
if ((p = malloc(sizeof(NAMEREF))) == NULL) return NULL;
p->name = strdup(name);
}
p->value = value;
p->next = *list;
*list = p;
return *list;
}
void del_namelist(NAMEREF *list)
{
if (keep_around) return;
if (temp_mem) return;
while (list)
{
if (list->name) free(list->name);
free(list);
list = list->next;
}
}
void *find_name(NAMEREF *list, char *name)
{
while (list)
{
if (!stricmp(list->name, name))
return list->value;
list = list->next;
}
return NULL;
}
char *find_value(NAMEREF *list, void *value)
{
while (list)
{
if (list->value == value)
return list->name;
list = list->next;
}
return NULL;
}
unsigned int find_color(NAMEREF *list, char *name)
{
if (isdigit(name[0])) /* handle dec/hex color */
return strtoul(name, NULL, 0);
if (name[0] == '&') return convert_color(&name[1], NULL);
return (unsigned)find_name(list, name);
}
/****************** TASK AND CONTROL SUPPORT *************/
extern void spinner(), sculspin();
struct {
char *name;
void (*fn)();
} functions[] = { {"spinner", spinner},
{"sculspin", sculspin},
{NULL, NULL} };
/******************** POLYGON, PLANE NORMAL SUPPORT ***********/
#define LSCALE 536870912.0
void scale3(float a, float b, float c,
long *ap, long *bp, long *cp)
{
float maxim; /* integerize normal */
maxim = (a > 0) ? a : -a; /* BUG IN BC 3.0 fabs()! */
maxim += (b > 0) ? b : -b;
maxim += (c > 0) ? c : -c;
if (maxim > 0.0001)
{
maxim /= LSCALE;
*ap = a/maxim;
*bp = b/maxim; /* normalize to <3.29> */
*cp = c/maxim;
}
}
void scale4(float a, float b, float c, float d,
long *ap, long *bp, long *cp, long *dp)
{
float maxim; /* integerize normal */
maxim = (a > 0) ? a : -a; /* BUG IN BC 3.0 fabs()! */
maxim += (b > 0) ? b : -b;
maxim += (c > 0) ? c : -c;
maxim += (d > 0) ? d : -d;
if (maxim > 0.0001)
{
maxim /= LSCALE;
*ap = a/maxim;
*bp = b/maxim; /* normalize to <3.29> */
*cp = c/maxim;
*dp = d/maxim;
}
}
/* facing normal, points should be in CW sequence */
/* for axis aligned (+) split directions, use: */
/* x 0 0 x 100 0 x 0 100 for constant x */
/* 0 y 0 0 y 100 100 y 0 for constant y */
/* 0 0 z 100 0 z 0 100 z for constant z */
void points_to_normal( float x1, float y1, float z1,
float x2, float y2, float z2,
float x3, float y3, float z3,
long *ap, long *bp, long *cp )
{
float v1x, v1y, v1z, v2x, v2y, v2z;
float a, b, c; /* compute line equation */
v1x = x2 - x1;
v1y = y2 - y1;
v1z = z2 - z1;
v2x = x3 - x1;
v2y = y3 - y1;
v2z = z3 - y1;
a = (v1y * v2z - v2y * v1z);
b = (v1x * v2z - v2x * v1z);
c = (v1x * v2y - v2x * v1y);
scale3(a, b, c, ap, bp, cp);
}
void points_to_eqn( float x1, float y1, float z1,
float x2, float y2, float z2,
float x3, float y3, float z3,
long *ap, long *bp, long *cp, long *dp)
{
float v1x, v1y, v1z, v2x, v2y, v2z;
float a, b, c, d; /* compute line equation */
v1x = x2 - x1;
v1y = y2 - y1;
v1z = z2 - z1;
v2x = x3 - x1;
v2y = y3 - y1;
v2z = z3 - y1;
a = (v1y * v2z - v2y * v1z);
b = (v1x * v2z - v2x * v1z);
c = (v1x * v2y - v2x * v1y);
d = -(a*x1 + b*y1 + c*z1); /* normalize to <3.29> */
scale4(a, b, c, d, ap, bp, cp, dp);
}
void normal_to_plane( float x, float y, float z,
float nx, float ny, float nz,
long *ap, long *bp, long *cp, long *dp)
{
float a, b, c, d; /* compute line equation */
/* given normal and point */
a = nx;
b = -ny;
c = nz;
d = -(a*x + b*y + c*z);
scale4(a, b, c, d, ap, bp, cp, dp);
}
/************* WORLD AND CONFIG FILE LOADING **********/
NAMEREF *areas = NULL;
NAMEREF *maps = NULL;
NAMEREF *surfdefs = NULL;
NAMEREF *objectlist = NULL;
NAMEREF *fixedolist = NULL;
NAMEREF *figurelist = NULL;
#ifdef ENABLE_STATEMACH
extern NAMEREF *statelist;
extern NAMEREF *varlist;
#endif
void dump_lists(void)
{
if(temp_mem) return; /* no need to delete if using temp. RAM */
del_namelist(areas);
del_namelist(maps);
del_namelist(surfdefs);
del_namelist(objectlist);
del_namelist(fixedolist);
del_namelist(figurelist);
#ifdef ENABLE_STATEMACH
del_namelist(statelist);
del_namelist(varlist);
#endif
}
typedef struct _surface SURFACEX;
struct _surface {
unsigned color;
char *value;
SURFACEX *next;
};
static SURFACEPAIR colormap[100]; // color pair table for mapping
int create_map_table(SURFACEX *map) // creates color pair table for mapping
{ // uses 0x80xx map flag for compatibility
int i = 0;
SURFACEX *p;
void *v;
if (map)
{
for (p = map; p; p = p->next)
{
colormap[i].old = p->color | 0x8000;
if ((v = find_name(surfdefs, p->value)) != NULL)
colormap[i].new = (unsigned) v;
else
colormap[i].new = 0;
i++;
}
}
return i;
}
extern char loadpath[];
#define match(a,b) !strnicmp(a, b, strlen(b))
OBJECT *find_seg(char *name)
{
char *p = NULL;
OBJECT *obj;
if (name[0]==0) return NULL;
if ((p = strchr(name, '.')) == NULL)
{
if ((obj = find_name(objectlist, name)) == NULL) goto try_seg;
return obj;
}
else
{ // part of figure
*p++ = '\0';
try_seg:
if ((obj = find_name(figurelist, name)) == NULL) return NULL; /* no such figure */
if (p==NULL) return obj; /* root of figure */
return find_segment_by_name(obj, p);
}
}
void clean_equals(char *b) // fixes up tokenization of string so
{ // word = word -> word=word
char *c=b, *d=b; // so it's a hack!
if(!strchr(b,'=')) return;
while(*b) /* scan string: */
{
if(*b==' ' || *b=='\t') /* if whitespace: */
{
d = b; /* record start */
while (*b==' ' || *b=='\t') *c++ = *b++; /* copy till end of ws */
if(*b=='=')
{
c = d; /* roll back position */
*c++ = *b++; /* copy = */
while (*b==' ' || *b=='\t') b++; /* skip trailing ws */
}
}
else *c++ = *b++;
}
*c = 0;
}
// these scan a line for a token
// but leave the dest unchanged if none found/error
void tokstr(char *c) // return string from line
{
char *s = strtok(NULL, " \t,\n#");
if(s) sscanf(s, "%s",c);
}
void tokstrn(char *c) // return string or null string
{
char *s = strtok(NULL, " \t,\n#");
if(s) sscanf(s, "%s",c);
else *c = 0;
}
void tokint(int *i) // return integer
{
char *s = strtok(NULL, " \t,\n#");
if(s) sscanf(s, "%d",i);
}
void tokhex(unsigned *i)
{
char *s = strtok(NULL, " \t,\n#");
if(s) *i = (unsigned int)strtoul(s, NULL, 0);
}
void toklong(long *i)
{
char *s = strtok(NULL, " \t,\n#");
if(s) sscanf(s, "%ld",i);
}
void tokfloat(float *i)
{
char *s = strtok(NULL, " \t,\n#");
if(s) sscanf(s, "%f",i);
}
void tokangle(long *i)
{
float f;
char *s = strtok(NULL, " \t,\n#");
if(s)
{
sscanf(s, "%f", &f);
*i = 65536L * f;
}
}
char *toks(void)
{
char *s = strtok(NULL, " \t,\n#");
if (s) return "";
else return s;
}
static int title_index = 0; // WORLD TITLE goes here
char *title[25] = { NULL };
// LIST OF COMMANDS
static char *commands[] = {
"loadpath", "palette", "skycolor", "groundcolor", "screencolor",
"screenclear", "ambient", "worldscale", "flymode", "light",
"window", "key", "control", "viewframe", "start", "floormode",
"hither", "yon", "eyespacing", "screendist", "attachview",
"screenwidth", "convergence", "figure", "object", "stepsize",
"task", "position", "rotate", "camera", "options",
"include", "surfacemap", "surface", "surfacedef",
"split", "splitpt", "area", "floor", "floorpts",
"ceiling", "ceilingpts", "visfrom",
"endsplits", "polyobj", "polyobj2", "videodev",
"mousedev", "headdev", "glovedev", "ptrdev",
"switchdev", "glovecursor", "ptrcursor", "segaport", "switchport",
"pgloveport", "pglovetime", "stereoset", "stereotype",
"stereoleft", "stereoright", "depthtype", "attach", "detach",
"usemap", "fixedobj",
#ifdef ENABLE_STATEMACH
"animation", "state", "if", "do",
#endif
"title", "mlight", "segment", "addrep",
"anglestep",
"version",
NULL
};
enum com_codes {
c_loadpath = 0, c_palette, c_skycolor, c_groundcolor, c_screencolor,
c_screenclear, c_ambient, c_worldscale, c_flymode, c_light,
c_window, c_key, c_control, c_viewframe, c_start, c_floormode,
c_hither, c_yon, c_eyespacing, c_screendist, c_attachview,
c_screenwidth, c_convergence, c_figure, c_object, c_stepsize,
c_task, c_position, c_rotate, c_camera, c_options,
c_include, c_surfacemap, c_surface, c_surfacedef,
c_split, c_splitpt, c_area, c_floor, c_floorpts,
c_ceiling, c_ceilingpts, c_visfrom,
c_endsplits, c_polyobj, c_polyobj2, c_videodev,
c_mousedev, c_headdev, c_glovedev, c_ptrdev,
c_switchdev, c_glovecursor, c_ptrcursor, c_segaport, c_switchport,
c_pgloveport, c_pglovetime, c_stereoset, c_stereotype,
c_stereoleft, c_stereoright, c_depthtype, c_attach, c_detach,
c_usemap, c_fixedobj,
#ifdef ENABLE_STATEMACH
c_animation, c_state, c_if, c_do,
#endif
c_title, c_mlight, c_segment, c_addrep,
c_anglestep,
c_version,
};
static SURFACEX *current_surface = NULL, *map;
static SPLIT *current_split = NULL;
static char ps[] = " \t\n,#";
static char st[] = "%s";
extern long spacestep, anglestep;
static char default_map[100] = "";
LIGHT *std_lights[3]; // default lights for the world
LIGHT *amb_light;
LIGHT * light1;
LIGHT * light2;
void create_default_lights()
{
POSE p = {1000, 15000, -5000, 0, 0, 0};
std_lights[0] = amb_light = create_light(NULL,AMBIENT_LIGHT,64);
std_lights[1] = light1 = create_light(NULL,POINT_LIGHT,64);
position_pointlight(light1,&p);
std_lights[2] = light2 = create_light(NULL,POINT_LIGHT,0);
p.x = -4000;
position_pointlight(light2,&p);
}
extern TELEPORT *fnkeyposn[10];
extern TELEPORT *fnkeyhome[10];
extern OBJECT *body_vehicle_object;
void read_world(FILE *in)
{
char obuff[256];
char inbuff[256], *buff, fname[100];
char surfacemapname[100];
char *args;
char *pname;
int i,cmd;
while (fgets(inbuff, sizeof(inbuff), in))
{
strcpy(obuff,inbuff);
buff = strtok(inbuff,"#");
for (buff = inbuff; isspace(*buff); ++buff);
if(buff[0]==0) continue;
clean_equals(buff);
for (args = buff+1; isalpha(*args); ++args);
args++;
buff = strtok(buff," \t\n");
for (cmd = 0; commands[cmd]; cmd++)
if (!stricmp(commands[cmd], buff)) break;
if (commands[cmd] == NULL) continue;
switch(cmd)
{
case c_palette:
{
FILE *in;
char *f;
tokstr(fname);
if ((in = fopen(f = fix_fname(fname), "rb")) != NULL)
{
npalette = fread(palette, 3, 256, in);
fclose(in);
}
else errprintf("Could not load palette '%s'", f);
}
break;
case c_attach:
{
OBJECT *s, *par;
if ((s = find_seg(strtok(NULL,ps))) == NULL) break;
if ((par = find_seg(strtok(NULL,ps))) == NULL) break;
attach_object(s, par, 0);
update_object(par);
break;
}
case c_stepsize:
toklong(&spacestep);
break;
case c_anglestep:
{
float a;
tokfloat(&a);
anglestep = a * 65536L;
}break;
case c_loadpath:
tokstr(loadpath);
break;
case c_skycolor:
tokhex(&sky_color);
set_skycolor(sky_color);
break;
case c_groundcolor:
tokhex(&ground_color);
set_groundcolor(ground_color);
break;
case c_screencolor:
tokhex(&screen_clear_color);
break;
case c_screenclear:
tokint(&do_screen_clear);
break;
case c_ambient:
{
int i;
tokint(&i);
set_light_intensity(amb_light,i);
break;
}
case c_worldscale:
default_stereo.world_scaling = 65536.0 * atof(strtok(NULL,ps));
break;
case c_light:
{
char *p;
POSE pose = DONTCARE_POSE;
int s;
COORD x,y,z;
x = atol(strtok(NULL,ps));
y = atol(strtok(NULL,ps));
z = atol(strtok(NULL,ps));
p = strtok(NULL, ps);
if (isdigit(*p)) s = atoi(p);
else s = !stricmp(p, "spot");
if(!s)
{
pose.x = x; // treat as location
pose.y = y;
pose.z = z;
position_pointlight(light1,&pose);
}
else
{
pose.rx = float2angle(x); // treat as angles
pose.ry = float2angle(y);
pose.rz = float2angle(z);
rotate_spotlight(light1,&pose);
}
} break;
case c_mlight:
{
char *p;
POSE pose = DONTCARE_POSE;
int s,i;
COORD x,y,z;
char parent[100];
char *m;
OBJECT *p_seg;
x = atol(strtok(NULL,ps));
y = atol(strtok(NULL,ps));
z = atol(strtok(NULL,ps));
p = strtok(NULL, ps);
if (isdigit(*p)) s = atoi(p);
else s = !stricmp(p, "spot");
sscanf(strtok(NULL,ps), "%d", &i); /* intensity*128 */
set_light_intensity(light2,i);
if(!s)
{
pose.x = x; // treat as location
pose.y = y;
pose.z = z;
position_pointlight(light2,&pose);
}
else
{
pose.rx = float2angle(x); // treat as angles
pose.ry = float2angle(y);
pose.rz = float2angle(z);
rotate_spotlight(light2,&pose);
}
tokstrn(parent);
if(parent[0]==0 || !stricmp(parent, "fixed")) break; /* not a moveable light */
if ((m=strchr(parent, '='))!=NULL)
{
*m++ = 0;
add_name(&figurelist, parent, light2->seg); /* record name */
}
else m = parent;
p_seg = find_seg(m);
if(p_seg)
{
attach_light(light2, p_seg, 0 );
update_object(p_seg);
}
break;
}
case c_segment:
{
OBJECT *this_seg, *p_seg;
char parentname[60], *oname, *p;
long tx = 0, ty = 0, tz = 0, rx = 0, ry = 0, rz = 0;
oname = NULL;
tokstrn(parentname);
tokangle(&rx);
tokangle(&ry);
tokangle(&rz);
toklong(&tx);
toklong(&ty);
toklong(&tz);
if ((p = strchr(parentname, '=')) != NULL)
{
oname = parentname;
*p++ = '\0';
}
else p = parentname;
p_seg = find_seg(p);
if ((this_seg = create_invisible_object()) != NULL)
{
POSE pose;
pose.x = tx;
pose.y = ty;
pose.z = tz;
pose.rx = rx;
pose.ry = ry;
pose.rz = rz;
attach_object(this_seg, p_seg, 0);
set_object_pose(this_seg, &pose);
update_object(this_seg);
if (oname) add_name(&figurelist, oname, this_seg);
}
}
break;
case c_camera:
{
int n;
char *c;
POSE p = ZERO_POSE;
tokint(&n);
if (n < 1 || n > 10) break;
if(n==1) goto set_start;
n--;
toklong(&(p.x));
toklong(&(p.y));
toklong(&(p.z));
if (old_angle_order)
{
tokangle(&(p.ry));
tokangle(&(p.rx));
}
else
{
tokangle(&(p.rx));
tokangle(&(p.ry));
}
tokangle(&(p.rz));
if(!fnkeyposn[n])
fnkeyposn[n] = create_teleport();
teleport_set_here(fnkeyposn[n], &p);
teleport_set_vehicle(fnkeyposn[n],NULL,NULL);
if(!fnkeyhome[n])
fnkeyhome[n] = create_teleport();
teleport_set_here(fnkeyhome[n], &p);
teleport_set_vehicle(fnkeyhome[n],NULL,NULL);
// tokangle(&(v->zoom)); // ignore for now
// toklong(&(v->hither));
// toklong(&(v->yon));
} break;
case c_start:
set_start:
{
float zoom = 0.0;
toklong(&initial_body_pose.x);
toklong(&initial_body_pose.y);
toklong(&initial_body_pose.z);
if(old_angle_order)
{
tokangle(&initial_body_pose.ry);
tokangle(&initial_body_pose.rx);
}
else
{
tokangle(&initial_body_pose.rx);
tokangle(&initial_body_pose.ry);
}
tokangle(&initial_body_pose.rz);
tokfloat(&zoom);
if(zoom>16.0) zoom = 16.0;
if(zoom>0.5)
set_camera_zoom(default_camera, float2scale(zoom));
*body_pose = initial_body_pose;
if(!fnkeyposn[0])
fnkeyposn[0] = create_teleport();
teleport_set_vehicle(fnkeyposn[0],body_vehicle_object,NULL);
teleport_set_here(fnkeyposn[0], &initial_body_pose);
if(!fnkeyhome[0])
fnkeyhome[0] = create_teleport();
teleport_set_here(fnkeyhome[0], &initial_body_pose);
teleport_set_vehicle(fnkeyhome[0],body_vehicle_object,NULL);
break;
}
case c_attachview:
{
OBJECT *vehicle = NULL;
char parentname[60];
tokstrn(parentname);
vehicle = find_seg(parentname);
if(vehicle) connect_body(vehicle);
if(!fnkeyposn[0])
fnkeyposn[0] = create_teleport();
teleport_set_here(fnkeyposn[0], &initial_body_pose);
teleport_set_vehicle(fnkeyposn[0],body_vehicle_object,NULL);
if(!fnkeyhome[0])
fnkeyhome[0] = create_teleport();
teleport_set_here(fnkeyhome[0], &initial_body_pose);
teleport_set_vehicle(fnkeyhome[0],body_vehicle_object,NULL);
}
break;
case c_hither:
{
COORD h = atol(strtok(NULL,ps));
if(h<1) h=1;
set_camera_hither(default_camera,h);
break;
}
case c_yon:
{
COORD y = atol(strtok(NULL,ps));
if(y>530000000L) y=530000000L;
set_camera_yon(default_camera,y);
break;
}
case c_title:
if((args!=NULL)&&(args[0]!=0)&&(title_index<22))
{
char s[200];
sscanf(args, "%s", s);
if(strlen(args)>36) args[36] = 0;
if(!stricmp(s,"memory"))
{
sprintf(s, "Memory Left: %ld", coreleft());
args = s;
}
title[title_index++] = strdup(args);
title[title_index] = NULL;
}break;
#ifdef ENABLE_STATEMACH
/* ANIMATION PARSER */
case c_animation:
parse_ani();
break;
case c_state:
parse_state();
break;
case c_if:
parse_if();
break;
case c_do:
parse_do();
break;
#endif
case c_figure:
{
char filename[60], parentname[60], *oname, *p;
float sx = 1, sy = 1, sz = 1;
FILE *fig;
POSE pose = ZERO_POSE;
parentname[0] = '\0';
oname = NULL;
sscanf(strtok(NULL,ps), st, filename);
tokfloat(&sx);
tokfloat(&sy);
tokfloat(&sz);
tokangle(&pose.rx);
tokangle(&pose.ry);
tokangle(&pose.rz);
toklong(&pose.x);
toklong(&pose.y);
toklong(&pose.z);
tokstrn(parentname);
add_ext(filename, "fig");
if ((p = strchr(filename, '=')) != NULL)
{
oname = filename;
*p++ = '\0';
}
else
p = filename;
if ((fig = fopen(pname = fix_fname(p), "r")) != NULL)
{
SEGMENT *this_seg, *p_seg;
p_seg = find_seg(parentname);
this_seg = load_figure_as_object(fig, default_objlist, NULL, 0, sx, sy, sz);
if (this_seg != NULL)
{
add_objlist_to_world(default_objlist);
if(p_seg)attach_object(this_seg,p_seg,0);
set_object_pose(this_seg, &pose);
update_object(this_seg);
}
fclose(fig);
if (seg_error(NULL))
{
errprintf("%s in figure file '%s'\n", seg_error(NULL), pname);
break;
}
if (oname) add_name(&figurelist, oname, this_seg);
}
else
errprintf( "Could not open '%s'", pname);
} break;
case c_fixedobj:
case c_object:
{
char mappings[100], *p, filename[100], *oname, parentname[100];
float sx = 1, sy = 1, sz = 1;
ANGLE rx = 0, ry = 0, rz = 0;
COORD tx = 0, ty = 0, tz = 0;
int dt = 0, nmaps = 0;
int nobjs = 0;
FILE *plg;
OBJECT *obj;
sscanf(strtok(NULL,ps), st, filename);
add_ext(filename, "plg");
tokfloat(&sx);
tokfloat(&sy);
tokfloat(&sz);
tokangle(&rx);
tokangle(&ry);
tokangle(&rz);
toklong(&tx);
toklong(&ty);
toklong(&tz);
tokint(&dt);
tokstrn(mappings);
map = find_name(maps, mappings);
if (!map)
map = find_name(maps, default_map);
nmaps = create_map_table(map);
tokstrn(parentname);
if (cmd == c_fixedobj || (current_split) ) // on split: force to fixed!
strcpy(parentname, "fixed");
if ((p = strchr(filename, '=')) != NULL)
{
oname = filename;
*p++ = '\0';
}
else
{
oname = NULL;
p = filename;
}
if ((plg = fopen(pname = fix_fname(p), "r")) != NULL)
{
POSE pose;
POSE zpose = ZERO_POSE; // for load of moveable
// choose load offsets
POSE *loadp = (!stricmp(parentname, "fixed")) ? &pose: &zpose ;
pose.x=tx; pose.y=ty; pose.z=tz;
pose.rx=rx; pose.ry=ry; pose.rz=rz;
nobjs = load_plg_to_objlist(plg, default_objlist, 100, loadp, sx, sy, sz, dt);
if(nobjs)
{
if(nmaps&&nobjs)
objlist_remap_surface(default_objlist, colormap, nmaps,
MAP_ALL_MASK, MAP_ALL_MASK);
if (stricmp(parentname, "fixed"))
{
SEGMENT *s, *p = NULL;
p = find_seg(parentname);
obj = convert_objlist_to_moveable_object(default_objlist);
if(obj && p) attach_object(obj, p, 0);
set_object_pose(obj, &pose);
update_object(obj);
}
else obj = first_in_objlist(default_objlist);
add_objlist_to_world(default_objlist);
if (oname) // add name NOW in case file didn't load
{
if (stricmp(parentname, "fixed"))
add_name(&objectlist, oname, obj);
else
add_name(&fixedolist, oname, obj);
}
}
if (plg_error(NULL))
{
errprintf("%s in file %s\n", plg_error(NULL), pname);
break;
}
}
else
{
errprintf("Could not open '%s'", pname);
break;
}
fclose(plg);
} break;
case c_addrep:
{
char mappings[100], *p, filename[100], *oname;
float sx = 1, sy = 1, sz = 1;
int defsize = 0;
FILE *plg;
OBJECT *obj, sobj;
POSE pose = ZERO_POSE;
int nmaps = 0;
sscanf(strtok(NULL,ps), st, filename);
add_ext(filename, "plg");
tokfloat(&sx);
tokfloat(&sy);
tokfloat(&sz);
tokangle(&pose.rx);
tokangle(&pose.ry);
tokangle(&pose.rz);
toklong(&pose.x);
toklong(&pose.y);
toklong(&pose.z);
tokint(&defsize);
tokstrn(mappings);
map = find_name(maps, mappings);
nmaps = create_map_table(map);
if ((p = strchr(filename, '=')) == NULL) break;
oname = filename;
*p++ = '\0';
if((obj = find_seg(oname))==NULL)
{
if(!(obj = find_name(fixedolist, oname))) break;
}
if ((plg = fopen(pname = fix_fname(p), "r")) != NULL)
{
while ((obj = load_extra_plg_representation(plg, obj, &pose, sx, sy, sz, defsize)) != NULL)
if (obj)
{
if(nmaps)
masked_remap_object_surface(obj, colormap, nmaps,
MAP_ALL_MASK, MAP_ALL_MASK, FALSE);
physical_update_object(obj); /* update world coords, etc */
}
if (plg_error(NULL))
{
errprintf("%s in file %s\n", plg_error(NULL), pname);
break;
}
}
else
{
errprintf( "Could not open '%s'", pname);
break;
}
fclose(plg);
} break;
case c_task:
{
char taskname[100], param[100];
long period;
int i;
void *data;
sscanf(strtok(NULL,ps), st, taskname);
period = atol(strtok(NULL,ps)) * 6L; // FASTER CLK
strcpy(param, strtok(NULL,"\n"));
for (i = 0; functions[i].name; ++i)
if (!stricmp(taskname, functions[i].name))
{
add_task(&tasklist, functions[i].fn, period, param);
break;
}
} break;
case c_position:
{
OBJECT *obj;
char oname[100];
long x, y, z;
strcpy(oname, strtok(NULL,ps));
x = atol(strtok(NULL,ps));
y = atol(strtok(NULL,ps));
z = atol(strtok(NULL,ps));
if ((obj = find_seg(oname)) != NULL)
{
POSE p = DONTCARE_POSE;
p.x = x;
p.y = y;
p.z = z;
set_object_pose(obj, &p);
update_object(obj);
}
}break;
case c_rotate:
{
OBJECT *obj;
char oname[100];
float rx, ry, rz;
strcpy(oname,strtok(NULL,ps));
rx = atof(strtok(NULL,ps));
ry = atof(strtok(NULL,ps));
rz = atof(strtok(NULL,ps));
if ((obj = find_seg(oname)) != NULL)
{
POSE p = DONTCARE_POSE;
p.rx = float2angle(rx);
p.ry = float2angle(ry);
p.rz = float2angle(rz);
set_object_pose(obj, &p);
update_object(obj);
}
}
break;
case c_include:
{
char fname[100];
FILE *in;
char *f;
strcpy(fname,strtok(NULL,ps));
if ((in = fopen(f = fix_fname(fname), "r")) != NULL)
{
read_world(in);
fclose(in);
}
else
errprintf("Could not open '%s'as include file", f);
}break;
case c_surfacemap:
{
/* starts a new map of color numbers to surface names */
strcpy(surfacemapname,strtok(NULL,ps));
current_surface = NULL;
} break;
case c_surface:
{
SURFACEX *p;
/* maps a color number to a surface name */
if ((p = malloc(sizeof(SURFACEX))) != NULL) // create list element
{
char buf2[40];
if (current_surface == NULL) // add name for color map (first)
add_name(&maps, surfacemapname, p);
else
current_surface->next = p; // or just add
current_surface = p;
p->next = NULL;
p->color = strtoul(strtok(NULL,ps), NULL, 0); // get value
strcpy(buf2,strtok(NULL,ps));
p->value = strdup(buf2);
}
}
break;
case c_surfacedef:
{ /* maps a surface name to an internal color value */
char sname[100], svalue[20];
strcpy(sname,strtok(NULL,ps)); // add to list
strcpy(svalue,strtok(NULL,ps));
add_name(&surfdefs, sname, (void *) convert_color(svalue, NULL));
} break;
case c_split:
{
float x, y, z, nnx, nny, nnz;
long nx, ny, nz;
unsigned flags = 0;
x = atof(strtok(NULL,ps));
y = atof(strtok(NULL,ps));
z = atof(strtok(NULL,ps));
nnx = atof(strtok(NULL,ps));
nny = atof(strtok(NULL,ps));
nnz = atof(strtok(NULL,ps));
tokhex(&flags);
scale3(nnx, nny, nnz, &nx, &ny, &nz);
add_split_to_world(x, y, z, nx, ny, nz, flags);
}break;
case c_splitpt:
{
float x1, x2, x3, y1, y2, y3, z1, z2, z3;
long nx, ny, nz;
unsigned flags = 0;
x1 = atof(strtok(NULL,ps));
y1 = atof(strtok(NULL,ps));
z1 = atof(strtok(NULL,ps));
x2 = atof(strtok(NULL,ps));
y2 = atof(strtok(NULL,ps));
z2 = atof(strtok(NULL,ps));
x3 = atof(strtok(NULL,ps));
y3 = atof(strtok(NULL,ps));
z3 = atof(strtok(NULL,ps));
flags = strtoul(strtok(NULL,ps), NULL, 0);
points_to_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3, &nx, &ny, &nz);
add_split_to_world(x1, y1, z1, nx, ny, nz, flags);
} break;
case c_area:
{
long x, y, z;
void *what_area();
char areaname[100];
AREA *a;
x = atol(strtok(NULL,ps));
y = atol(strtok(NULL,ps));
z = atol(strtok(NULL,ps));
sscanf(strtok(NULL,ps), st, areaname);
add_name(&areas, areaname, a=what_area(global_world_root, x, y, z));
set_area_name(a, areaname);
}break;
case c_endsplits:
end_of_world_splits();
break;
case c_polyobj:
case c_polyobj2:
{
char map[100], map2[100];
OBJECT *obj;
POLY *poly;
unsigned color;
int nv = 0;
int i;
long x[18], y[18], z[18];
map[0] = '\0';
nv = atoi(strtok(NULL,ps));
tokstrn(map);
if (cmd==c_polyobj2) tokstrn(map2);
if (nv > 18) nv = 18;
for(i=0;i<nv;i++)
{
x[i] = atol(strtok(NULL,ps));
y[i] = atol(strtok(NULL,ps));
z[i] = atol(strtok(NULL,ps));
}
i = (cmd==c_polyobj2) ? 2 : 1 ;
obj = create_fixed_object(nv, i, nv*i);
if (obj)
{
char *p;
if ((p = strtok(NULL, ps)) != NULL)
set_object_sorting(obj, atoi(p));
if (map)
color = (unsigned) find_color(surfdefs, map);
poly = add_poly(obj, color, nv);
for (i = 0; i < nv; i++)
{
add_vertex(obj, x[i], y[i], z[i]);
add_point(obj, poly, nv-i-1);
}
if (cmd == c_polyobj2)
{
if (map2)
color = (unsigned) find_color(surfdefs, map2);
poly = add_poly(obj, color, nv);
for (i = 0; i < nv; i++)
{
add_point(obj, poly, i);
}
}
compute_object(obj);
add_object_to_world(obj);
}
}break;
}
}
return;
}