/* NODEGEN/vrml.h */ /* This vrml.H header file, as well as the other files in the NODEGEN * directory that also are present in the main VRML/ directory are different * of those in the main directory for two reasons: * 1) we want to isolate node generation code as much as possible from * already implemented node code. * 2) node generation requires some other data that is not needed in the * node implementations itself and vice versa: the node implementations need * data that is not needed for node code generation. */ #ifndef _VRML_H_ #define _VRML_H_ #include "error.H" /* VRML'97 field Types */ typedef enum fieldType { tdummy, tSFBool, tSFString, tSFInt32, tSFFloat, tSFTime, tSFVec2f, tSFVec3f, tSFColor, tSFRotation, tSFImage, tSFNode, tMFBool, tMFString, tMFInt32, tMFFloat, tMFTime, tMFVec2f, tMFVec3f, tMFColor, tMFRotation, tMFImage, tMFNode } fieldType; #ifndef __cplusplus /* exact declaration not needed nor wanted in the plain C code of * lex.l and error.c */ typedef void *fieldValueBase[2]; typedef void SFNode, MFNode, MFString; #else /* _cplusplus */ #include /* ***************************** simple types ***************************** */ // Only basic constructors and convertors to the nearest standard type are provided. // Use builtin C++ types or your own vector .... classes (with appropriate // own type convertor) for computations. class SFBool { bool val; public: inline SFBool(int b =false) { val = b; } inline operator bool() { return val; } friend ostream& operator<<(ostream& s, SFBool& v) { return s << (v.val ? "TRUE" : "FALSE"); } friend ostream& operator<<(ostream& s, SFBool* v) { return v ? operator<<(s, *v) : (s << "NULL"); } }; class SFString { char *val; public: inline SFString(char *s =0) { val = s; } inline operator char*() { return val; } friend ostream& operator<<(ostream& s, SFString& v) { return s << v.val; } friend ostream& operator<<(ostream& s, SFString* v) { return v ? operator<<(s, *v) : (s << "NULL"); } }; class SFInt32 { int val; public: inline SFInt32(int d =0) { val = d; } inline operator int() { return val; } friend ostream& operator<<(ostream& s, SFInt32& v) { return s << v.val; } friend ostream& operator<<(ostream& s, SFInt32* v) { return v ? operator<<(s, *v) : (s << "NULL"); } }; class SFFloat { float val; public: inline SFFloat(float f =0.) { val = f; } inline operator float() { return val; } friend ostream& operator<<(ostream& s, SFFloat& v) { return s << v.val; } friend ostream& operator<<(ostream& s, SFFloat* v) { return v ? operator<<(s, *v) : (s << "NULL"); } }; class SFTime { double val; public: inline SFTime(double f =0.) { val = f; } inline operator double() { return val; } friend ostream& operator<<(ostream& s, SFTime& v) { return s << v.val; } friend ostream& operator<<(ostream& s, SFTime* v) { return v ? operator<<(s, *v) : (s << "NULL"); } }; struct SFVec2f { float s, t; inline SFVec2f(float ss =0., float tt =0.) { s = ss; t = tt; } friend ostream& operator<<(ostream& s, SFVec2f& v) { return s << v.s << ' ' << v.t; } friend ostream& operator<<(ostream& s, SFVec2f* v) { return v ? operator<<(s, *v) : (s << "NULL"); } }; struct SFVec3f { float x, y, z; inline SFVec3f(float xx =0., float yy =0., float zz =0.) { x=xx; y=yy; z=zz; } friend ostream& operator<<(ostream& s, SFVec3f& v) { return s << v.x << ' ' << v.y << ' ' << v.z; } friend ostream& operator<<(ostream& s, SFVec3f* v) { return v ? operator<<(s, *v) : (s << "NULL"); } }; struct SFColor { float r, g, b; inline SFColor(float rr =0., float gg =0., float bb =0.) { r=rr; g=gg; b=bb; } friend ostream& operator<<(ostream& s, SFColor& v) { return s << v.r << ' ' << v.g << ' ' << v.b; } friend ostream& operator<<(ostream& s, SFColor* v) { return v ? operator<<(s, *v) : (s << "NULL"); } }; struct SFRotation { float x, y, z, radians; inline SFRotation(float xx =0., float yy =0., float zz =0., float rad =0.) { x=xx; y=yy; z=zz, radians=rad; } friend ostream& operator<<(ostream& s, SFRotation& v) { return s << v.x << ' ' << v.y << ' ' << v.z << ' ' << v.radians; } friend ostream& operator<<(ostream& s, SFRotation* v) { return v ? operator<<(s, *v) : (s << "NULL"); } }; class SFImage { void construct(int w, int h, int n, unsigned int *pix); void destruct(void); public: int width, height, num_components; unsigned int *pixels; SFImage(unsigned int w =0, unsigned int h =0, unsigned int n =0, unsigned int *pix =0); SFImage(const SFImage& src); SFImage& operator=(const SFImage& src); ~SFImage(); friend ostream& operator<<(ostream&, SFImage&); friend ostream& operator<<(ostream& s, SFImage* im) { return im ? operator<<(s, *im) : (s << "NULLL"); } }; // SFNode class is defined at the bottom of this file as we first need to define // a couple of other types on which SFNode builds. /* ***************************** array types ***************************** */ #include "Array.H" typedef array MFBool; typedef array MFString; typedef array MFInt32; typedef array MFFloat; typedef array MFTime; typedef array MFVec2f; typedef array MFVec3f; typedef array MFColor; typedef array MFRotation; typedef array MFImage; // MFNode is defined at the bottom of this file, after SFNode /* ***************************** field value union ***************************** */ // for printing field type.names, implemented in fieldValue.C extern char *fieldTypeName(const fieldType& type); inline ostream& operator<<(ostream& s, fieldType& v) { return s << fieldTypeName(v); } // a fieldValue type without constructors, so it can be used in // unions, such as the yacc stack type (see yacc.y). struct fieldValueBase { public: // union of pointers to classes that represent VRML field values. union { void *anyValue; SFBool *sfboolValue; SFString *sfstringValue; SFInt32 *sfint32Value; SFFloat *sffloatValue; SFTime *sftimeValue; SFVec2f *sfvec2fValue; SFVec3f *sfvec3fValue; SFColor *sfcolorValue; SFRotation *sfrotationValue; SFImage *sfimageValue; class SFNode **sfnodeValue; // sfnodeValue is a pointer to an SFNode * MFBool *mfboolValue; MFString *mfstringValue; MFInt32 *mfint32Value; MFFloat *mffloatValue; MFTime *mftimeValue; MFVec2f *mfvec2fValue; MFVec3f *mfvec3fValue; MFColor *mfcolorValue; MFRotation *mfrotationValue; MFImage *mfimageValue; class MFNode *mfnodeValue; }; // value type (tSFBool etc...) fieldType type; // checks whether value is of given type (done before assignements e.g.) int check(fieldType typ) { if (typ != type) { Error("fieldValueBase::check", "type conflict (%s,%s)", fieldTypeName(typ), fieldTypeName(type)); return 0; } else return 1; } public: friend ostream& operator<<(ostream&, fieldValueBase&); }; class fieldValue: public fieldValueBase { private: void do_assign(fieldValue& v); void do_duplicate(fieldValue& v); public: // constructors fieldValue(fieldType typ =tdummy, void* value =0) { type = typ; anyValue = value; } fieldValue(const fieldValueBase& val) { type = val.type; anyValue = val.anyValue; } // the following constructors construct a fieldValue object from a // SFBool ... pointer. fieldValue(SFBool *val) { type = tSFBool; sfboolValue = val; } fieldValue(SFInt32 *val) { type = tSFInt32; sfint32Value = val; } fieldValue(SFString *val) { type = tSFString; sfstringValue = val; } fieldValue(SFFloat *val) { type = tSFFloat; sffloatValue = val; } fieldValue(SFTime *val) { type = tSFTime; sftimeValue = val; } fieldValue(SFVec2f *val) { type = tSFVec2f; sfvec2fValue = val; } fieldValue(SFVec3f *val) { type = tSFVec3f; sfvec3fValue = val; } fieldValue(SFColor *val) { type = tSFColor; sfcolorValue = val; } fieldValue(SFRotation *val) { type = tSFRotation; sfrotationValue = val; } fieldValue(SFImage *val) { type = tSFImage; sfimageValue = val; } fieldValue(SFNode **val) { type = tSFNode; sfnodeValue = val; } fieldValue(MFBool *val) { type = tMFBool; mfboolValue = val; } fieldValue(MFInt32 *val) { type = tMFInt32; mfint32Value = val; } fieldValue(MFString *val) { type = tMFString; mfstringValue = val; } fieldValue(MFFloat *val) { type = tMFFloat; mffloatValue = val; } fieldValue(MFTime *val) { type = tMFTime; mftimeValue = val; } fieldValue(MFVec2f *val) { type = tMFVec2f; mfvec2fValue = val; } fieldValue(MFVec3f *val) { type = tMFVec3f; mfvec3fValue = val; } fieldValue(MFColor *val) { type = tMFColor; mfcolorValue = val; } fieldValue(MFRotation *val) { type = tMFRotation; mfrotationValue = val; } fieldValue(MFImage *val) { type = tMFImage; mfimageValue = val; } fieldValue(MFNode *val) { type = tMFNode; mfnodeValue = val; } // assginement operator: no type checking and only the value pointer is // copied. See assign(), duplicate() and instantiate() below if the // object pointed to needs to be copied or duplicated. fieldValue& operator=(const fieldValue& val) { anyValue = val.anyValue; type = val.type; return *this; } #ifdef NEVER fieldValue& operator=(SFBool *val) { check(tSFBool); sfboolValue = val; return *this; } fieldValue& operator=(SFString *val) { check(tSFString); sfstringValue = val; return *this; } fieldValue& operator=(SFInt32 *val) { check(tSFInt32); sfint32Value = val; return *this; } fieldValue& operator=(SFFloat *val) { check(tSFFloat); sffloatValue = val; return *this; } fieldValue& operator=(SFTime *val) { check(tSFTime); sftimeValue = val; return *this; } fieldValue& operator=(SFVec2f *val) { check(tSFVec2f); sfvec2fValue = val; return *this; } fieldValue& operator=(SFVec3f *val) { check(tSFVec3f); sfvec3fValue = val; return *this; } fieldValue& operator=(SFColor *val) { check(tSFColor); sfcolorValue = val; return *this; } fieldValue& operator=(SFRotation *val) { check(tSFRotation); sfrotationValue = val; return *this; } fieldValue& operator=(SFImage *val) { check(tSFImage); sfimageValue = val; return *this; } fieldValue& operator=(SFNode **val) { check(tSFNode); sfnodeValue = val; return *this; } fieldValue& operator=(MFBool *val) { check(tMFBool); mfboolValue = val; return *this; } fieldValue& operator=(MFString *val) { check(tMFString); mfstringValue = val; return *this; } fieldValue& operator=(MFInt32 *val) { check(tMFInt32); mfint32Value = val; return *this; } fieldValue& operator=(MFFloat *val) { check(tMFFloat); mffloatValue = val; return *this; } fieldValue& operator=(MFTime *val) { check(tMFTime); mftimeValue = val; return *this; } fieldValue& operator=(MFVec2f *val) { check(tMFVec2f); mfvec2fValue = val; return *this; } fieldValue& operator=(MFVec3f *val) { check(tMFVec3f); mfvec3fValue = val; return *this; } fieldValue& operator=(MFColor *val) { check(tMFColor); mfcolorValue = val; return *this; } fieldValue& operator=(MFRotation *val) { check(tMFRotation); mfrotationValue = val; return *this; } fieldValue& operator=(MFImage *val) { check(tMFImage); mfimageValue = val; return *this; } fieldValue& operator=(MFNode *val) { check(tMFNode); mfnodeValue = val; return *this; } #endif // type convertors: retrieve type and value pointer. operator fieldType() { return type; } operator void*() { return anyValue; } // type convertors (cast a fieldValue to a SFBool pointer etc...) operator SFBool*() { check(tSFBool); return sfboolValue; } operator SFString*() { check(tSFString); return sfstringValue; } operator SFInt32*() { check(tSFInt32); return sfint32Value; } operator SFFloat*() { check(tSFFloat); return sffloatValue; } operator SFTime*() { check(tSFTime); return sftimeValue; } operator SFVec2f*() { check(tSFVec2f); return sfvec2fValue; } operator SFVec3f*() { check(tSFVec3f); return sfvec3fValue; } operator SFColor*() { check(tSFColor); return sfcolorValue; } operator SFRotation*(){ check(tSFRotation); return sfrotationValue; } operator SFImage*() { check(tSFImage); return sfimageValue; } operator SFNode**() { check(tSFNode); return sfnodeValue; } operator MFBool*() { check(tMFBool); return mfboolValue; } operator MFString*() { check(tMFString); return mfstringValue; } operator MFInt32*() { check(tMFInt32); return mfint32Value; } operator MFFloat*() { check(tMFFloat); return mffloatValue; } operator MFTime*() { check(tMFTime); return mftimeValue; } operator MFVec2f*() { check(tMFVec2f); return mfvec2fValue; } operator MFVec3f*() { check(tMFVec3f); return mfvec3fValue; } operator MFColor*() { check(tMFColor); return mfcolorValue; } operator MFRotation*(){ check(tMFRotation); return mfrotationValue; } operator MFImage*() { check(tMFImage); return mfimageValue; } operator MFNode*() { check(tMFNode); return mfnodeValue; } // value retrieval: return (a reference to) the SFBool ... value pointed to operator SFBool&() { check(tSFBool); return *sfboolValue; } operator SFString&() { check(tSFString); return *sfstringValue; } operator SFInt32&() { check(tSFInt32); return *sfint32Value; } operator SFFloat&() { check(tSFFloat); return *sffloatValue; } operator SFTime&() { check(tSFTime); return *sftimeValue; } operator SFVec2f&() { check(tSFVec2f); return *sfvec2fValue; } operator SFVec3f&() { check(tSFVec3f); return *sfvec3fValue; } operator SFColor&() { check(tSFColor); return *sfcolorValue; } operator SFRotation&(){ check(tSFRotation); return *sfrotationValue; } operator SFImage&() { check(tSFImage); return *sfimageValue; } operator SFNode*&() { check(tSFNode); return *sfnodeValue; } operator MFBool&() { check(tMFBool); return *mfboolValue; } operator MFString&() { check(tMFString); return *mfstringValue; } operator MFInt32&() { check(tMFInt32); return *mfint32Value; } operator MFFloat&() { check(tMFFloat); return *mffloatValue; } operator MFTime&() { check(tMFTime); return *mftimeValue; } operator MFVec2f&() { check(tMFVec2f); return *mfvec2fValue; } operator MFVec3f&() { check(tMFVec3f); return *mfvec3fValue; } operator MFColor&() { check(tMFColor); return *mfcolorValue; } operator MFRotation&(){ check(tMFRotation); return *mfrotationValue; } operator MFImage&() { check(tMFImage); return *mfimageValue; } operator MFNode&(); // implemented after MFNode class declaration // the following methods assign, duplicate and swap the values pointed to // by sf*Value. Watch out: especially for SFImage values, assignment or // duplication may require copying of large amounts of data. // checks the type and assigns the object pointed to by src. // - this->*Value remains the same // - if the type is tSFNode, only the pointer to the node is assigned. // (src and this will point to the same SFNode). // - this->*Value and src.*Value must not be nil. void assign(fieldValue& src); // duplicates *src.*Value ands let this->*Value point to the duplicate. // - this->*Value gets a new value // - If the type is tSFNode, only the pointer to the node is duplicated. // that means: a new SFNode* is created and initialized with // *src.sfnodeValue (which can be NULL). // - this->*Value can be nil, but src.*Value must not be nil void duplicate(fieldValue& src); void duplicate(void) { duplicate(*this); } // creates a new instance of the object pointed to by 'this' and lets // this->*Value point to the new instance. This member function is // identical to duplicate(void), except if the type is tSFNode or tMFNode. // If the type is tSFNode or tMFNode, the node(s) is(are) replaced // by new node instances w.r.t. the master node. (see SFNode::instantiate()). void instantiate(class Proto *master =0); // if (this->*Value is not nil) assign(); else duplicate(). Used to // do assignements if it is not certain that the destination (this) // has already been initialized. void assign_or_duplicate_if_nil(fieldValue& src); }; extern fieldValue default_fieldValue(fieldType); /* ********************** node interface declaration ********************** */ typedef enum interfaceKind {kdummy, keventIn, kexposedField, kfield, keventOut} interfaceKind; extern char *interfaceKindName(const interfaceKind& kind); inline ostream& operator<<(ostream& s, interfaceKind& v) { return s << interfaceKindName(v); } class interfaceDeclaration { void construct(interfaceKind k, fieldType t, char *id, fieldValue val, class redirection *r); void destruct(void); void do_synchronize(void); public: interfaceKind kind; // field, exposedField, eventIn or eventOut fieldType type; // value type (SFBool ...) char *Id; // id name of field ... fieldValue value; // points to the actual value // node class Ids if type is SFNode or MFNode char* nodeClassId; SFNode *nodeClass; // points to corresponding (EXTERN)PROTO interface field or event // (IS statement in PROTO scene graph node value declaration). // This could be avoided by letting 'value' be a reference to the // PROTO interface value, but that would create problems concerning // PROTO instantiation. class redirection *ref; // -1 when constructed, 0 when initialized by initialize(), incremented // at each assignement. Can be used to keep track of whether the value // has been updated or not. long clock; // if checkval is not nil, it shall be a pointer to a function that is // called after an assignement to check the validity of the assigned value. // If valid, it shall return 'true', if not valid, it shall print an // warning or error message, restore a default value and return 'false'. bool (*checkval)(fieldValue& value); // constructors and destructor interfaceDeclaration(interfaceKind k=kdummy, fieldType t=tdummy, char* id=0); interfaceDeclaration(interfaceKind k, fieldType t, char* id, fieldValue val); interfaceDeclaration(const interfaceDeclaration& src); interfaceDeclaration& operator=(const interfaceDeclaration& src); ~interfaceDeclaration(void); // initializes a field (with a value read from a VRML file). clock is // set to 0. void initialize(fieldValue& val); // replaces value by a new instance void instantiate(class Proto *master =0); // assigns the value to the field. If the field is a synonym for some other // field, that other field is assigned the value to as well. // clock is incremented. void assign(fieldValue& val); // lets the field or event be a synonym of the field or event 'decl' of // the specified node (e.g. IS statement in PROTO scene graph node // value declaration). void redirect(SFNode *node, interfaceDeclaration *decl =0); // if the interface declaration is a redirection (by using the IS // statement in VRML file), and the clock values differ, meaning // that one of both this value of to value referred to has been updated, // the value referred to and its clock value are copied to 'this'. void synchronize(void) { if (ref) do_synchronize(); } friend ostream& operator<<(ostream&, interfaceDeclaration&); }; /* ***************************** SFNode class **************************** */ class SFNode { protected: virtual void construct (const char *id, const int nr, const interfaceDeclaration *iface); virtual void destruct(void); virtual void instantiate_interface(Proto *master =0); public: const char *typeId, *nameId; // if not 0, nameId is name of DEF'ed node or 0 int nameIndex; // if not -1, index of DEF'ed node in namedNodes table // nr of events/fields and their description int nrInterfaceDeclarations; interfaceDeclaration *interface; // parent class Ids and pointers */ array parentClassIds; array parentNodes; array dependNodes; // is this node a super node class description? bool isParent; // filename and lineno when the node was created. char *filename; int line; // initialized to 0, incremented each time a value of the node is updated. long clock; // user data. union { long i; void *p; } client_data; // constructors and destructor SFNode(const char* id =0, const int nr =0, const interfaceDeclaration* iface =0); SFNode(const SFNode& src); SFNode& operator=(const SFNode& src); virtual ~SFNode(); // the following routines look up the field, eventIn, eventOut with given Id // in the interface of the current node. NULL is returned if not found. interfaceDeclaration* get_field(char *fieldId); interfaceDeclaration* get_eventIn(char *eventInId); interfaceDeclaration* get_eventOut(char *eventOutId); // composes a unique name identifying the node, for debugging etc... virtual char* name(char* buf =0); // Creates and returns an instance of 'this', basically a copy of 'this' // with it's own interface and field/event redirections resolved to // the interface of the Proto node that is passed (if one is passed) // as an argument. virtual SFNode* instantiate(class Proto *master =0); // Returns a pointer to the first node of nodes scene graph. The first node // is the node itself if it is a builtin node and the first node of the PROTO // scene graph if it is a PROTO node (see Proto.H). Used for PROTO node resolution. virtual SFNode *firstnode(void) { return this; } // Some interface members may be synonym of enclosing PROTO interface members. // Nodes can also store (stricktly spoken redudant) data, derived from the // interface member values (e.g.: PROTO-resolved children node pointers). // The synchronize member function will take care that the node's state is // made consistent again after some potential changes (e.g. eventIns). // Children node graphs are traversed. This function should be called for // the world's root nodes before rendering each frame. virtual void synchronize(void) { for (int i=0; i { public: inline MFNode(int len =0, SFNode **table =0) { if (len>0) init(len, table); } // inline void render(void) { for (int i=0; irender(); } } inline void synchronize(void) { for (int i=0; isynchronize(); } } // returns a new MFNode with instances of the contained SFNodes MFNode *instantiate(class Proto *master =0); // copies 'this' to 'result', replacing PROTO's by the first node in their // scene graph (see SFNode::firstnode() void firstnodes(array *result); }; // couldn't be implemented before because class MFNode needs to be known. inline fieldValue::operator MFNode&() { check(tMFNode); return *mfnodeValue; } #include "./Proto.H" #endif /*__cplusplus*/ #endif /*_VRML_H_*/