-
Stuart Levy authoredStuart Levy authored
cat_model.h 6.02 KiB
#ifndef CAT_MODEL_H
#define CAT_MODEL_H
/*
* Read and display 3-D models from .obj/.ma files
* (wavefront .obj geometry, Maya 2.x/3.x .ma Maya ASCII material properties).
*
* Stuart Levy, slevy@ncsa.uiuc.edu
* National Center for Supercomputing Applications,
* University of Illinois 2001.
* This file is part of partiview, released under the
* Illinois Open Source License; see the file LICENSE.partiview for details.
*/
/*
* Library of renderable 3-D models,
*/
#include "geometry.h"
#include "cat_modelutil.h"
#include "textures.h"
/* A TextureHookFunc is called (from Appearance?::ApplyOGL()) while textures are
* being bound. It's called (possibly several times, if several objects have video textures) as:
* int hookfunc( objnoptr, data-passed-when-hook-was-registered, Appearance *ap, WavFaces * )
* It should
* Look at ap->txim->filename to find out which texture this is.
* return 0 if there's no special processing desired (e.g. video disabled);
* in that case, ApplyOGL will apply whatever texture it would have if un-hooked.
* or
* if(*objnoptr != desired_video_texture) {
* // make like txbind( video_texture, objnoptr );
* glBindTexture( desired_video_texture );
* *objno = desired_video_texture;
* maybe apply other opengl settings, e.g. to material properties;
* you could use the Appearance pointer to see what other settings apply.
* }
* return 1:
*/
typedef int (*TextureHookFunc)( int *txobjno, void *hookdata, class Appearance *, class WavFaces * );
/* 3-D model, in shared memory */
class Model : public Shmem {
public:
const char *name; /* model name */
const char *fname; /* name of model file */
long fmtime;
int defined;
Model *next; /* link in list of all Models */
Model();
void init();
virtual ~Model();
static Model *find( const char *name );
enum fstatus {
UNREAD = -2, /* file exists, but we haven't loaded it */
OUTDATED = -1, /* we've read a copy, but file has changed */
NONESUCH = 0, /* there is no such file */
READIT = 1 /* we have a current copy */
}; /* So, > 0 means "yes", < 0 means "try it", = 0 "don't bother" */
virtual void render() { }
static void preinit();
static void purge();
void discard();
virtual int HookTextures( TextureHookFunc hook, void *data, const char *txnametag ) { return 0; }
static enum fstatus seenFile( const char *fname ); /* Seen this model file?*/
static char **pathdirs; /* Search path for findFile() */
static char *findFile( const char *name ); /* returns salloc()ed string */
protected:
static Model **allModels; /* List of all Models */
static Model **trashModels;
int unused;
void add(); /* add this Model to list */
};
/* Generic appearance parameters.
* Should have subclasses for the various appearance types.
* Too bad.
*/
class Appearance : public Shmem {
public:
const char *name; /* Wavefront/Maya name of this appearance (shading group) */
Appearance *next;
Appearance *use;
int defined; /* Have we filled the rest of this structure in yet? */
int lighted; /* or not */
int smooth; /* or flat */
int shiny; /* or matte */
int textured; /* or not */
float Kd; /* ambient, diffuse, specular coefs */
float Cs[3]; /* surface color */
float Ca[3]; /* ambient color */
float shininess; /* specular exponent */
float Cspec[3]; /* specular color */
/* in case we're textured... */
char *txdir; /* directory in which to search for textures */
const char *txfname;
Texture *txim;
int txloaded;
TextureHookFunc hookfunc;
void *hookdata;
void applyOGL( class WavFaces * ); /* apply appearance to OpenGL state */
Appearance();
void init();
~Appearance();
void add( Appearance **list );
static Appearance *find( Appearance **listhead, const char *name );
static Appearance *findCreate( Appearance **listhead, const char *name );
static Appearance *create();
void loadTextures();
int HookTextures( TextureHookFunc hook, void *data, const char *txnametag );
static void purge( Appearance **listhead );
};
class MayaScene : public Shmem {
MayaScene();
protected:
const char *fname;
Appearance *aps;
int readScene( const char *scenefname, int complain );
const char *parseFileNode( const char *name, FILE *f, char *line, int lineroom, int *lno );
const char *parseMatNode( const char *name, FILE *f, char *line, int lineroom, int *lno, const char *kind );
const char *parseEngineNode( const char *name, FILE *f, char *line, int lineroom, int *lno );
const char *parseScrapNode( const char *name, FILE *f, char *line, int lineroom, int *lno );
const char *parseConnect( char *from, char *to );
Appearance *partials; /* Used while parsing only */
friend class WavObj;
};
class WavObj; /* Forward */
class WavFaces : public Shmem {
public:
vvec<int> nfv; /* Numbers of verts per face; nfv.count = nfaces */
vvec<int> fv; /* Table of all verts */
Appearance *ap; /* with this appearance */
WavObj *obj; /* reference back to our parent object */
WavFaces *next; /* next group of faces */
WavFaces();
~WavFaces();
static WavFaces *create();
void init();
};
/* Wavefront object, read from .obj file,
* with appearance read from Maya scene file.
*/
class WavObj : public Model {
public:
vvec<Point> pt; /* 3-D Points */
vvec<Point> tx; /* texture coords */
vvec<Point> norm; /* surface normals */
MayaScene *scene; /* basis for appearances */
WavFaces *faces;
WavObj();
void init();
~WavObj();
static WavObj *create();
static int readFile( const char *name, const char *fname, const char *scenename, int complain );
void render();
WavObj & operator=( const WavObj &src ) {
pt = src.pt; tx = src.tx; norm = src.norm;
scene = src.scene; faces = src.faces;
return *this;
}
// If you say
// wavobj->HookTextures( NULL, NULL, "" )
// it will remove any hooks on any textures in that model.
virtual int HookTextures( TextureHookFunc hook, void *data, const char *txnametag );
private:
WavObj *addObj( const char *name, const char *group );
};
class HappyFace : public Model {
public:
static void initialize();
};
#endif /*CAT_MODEL_H*/