/* Public domain */ #ifndef _FREESG_SG_H_ #define _FREESG_SG_H_ #include /* For AG_Surface */ #include /* Macros around precision-specific GL calls, GLU */ #if defined(_FREESG_INTERNAL) || defined(_USE_SG_GL) # include # include # include #endif /* _FREESG_INTERNAL or _USE_SG_GL */ /* Definitions internal to the SG implementation */ #include #ifdef _FREESG_INTERNAL # define Strlcpy AG_Strlcpy # define Strlcat AG_Strlcat # define NODE SGNODE # define NODE_OPS SGNODE_OPS # undef MAX # define MAX(h,i) ((h) > (i) ? (h) : (i)) # undef MIN # define MIN(l,o) ((l) < (o) ? (l) : (o)) #endif /* _FREESG_INTERNAL */ struct sg; struct sg_node; struct sg_point; struct sg_camera; struct sg_view; struct ag_menu_item; struct ag_widget; /* Side with respect to some line or plane */ enum sg_side { SG_LEFT, SG_RIGHT }; /* Vertex winding */ enum sg_winding { SG_CW, SG_CCW }; /* Packed OpenGL vertex structure. */ typedef struct sg_glvertex2 { double x, y; } SG_GLVertex2; typedef struct sg_glvertex3 { double x, y, z; } SG_GLVertex3; /* Extra class operations for scene graph nodes */ typedef struct sg_node_class { struct ag_object_class _inherit; void (*menuInstance)(void *, struct ag_menu_item *, struct sg_view *); void (*menuClass)(struct sg *, struct ag_menu_item *, struct sg_view *); void (*draw)(void *, struct sg_view *); int (*intersect)(void *, M_Geom3, M_GeomSet3 *); void *(*edit)(void *, struct sg_view *); } SG_NodeClass; /* Our scene graph node class */ typedef struct sg_node { struct ag_object _inherit; Uint flags; #define SG_NODE_SELECTED 0x01 /* Selection flag */ #define SG_NODE_HIDE 0x02 /* Disable rendering */ struct sg *sg; /* Back pointer to sg */ M_Matrix44 T; /* Transformation from parent */ AG_TAILQ_ENTRY(sg_node) rnodes; /* Used for quick inverse traversal */ AG_TAILQ_ENTRY(sg_node) nodes; /* For flat list */ } SG_Node; /* Our scene graph class */ typedef struct sg { struct ag_object _inherit; Uint flags; #define SG_OVERLAY_WIREFRAME 0x01 /* Overlay scene wireframe */ #define SG_OVERLAY_VERTICES 0x02 /* Draw points at vertices */ #define SG_OVERLAY_VNORMALS 0x04 /* Draw vertex normals */ #define SG_OVERLAY_FNORMALS 0x08 /* Draw facet normals */ #define SG_SKIP_UNKNOWN_NODES 0x10 /* Ignore unknown node types in save (otherwise LoadObject will fail) */ #define SG_NO_DEFAULT_NODES 0x20 /* Don't create default camera/lights */ SG_Node *root; /* Root of graph */ AG_TAILQ_HEAD(,sg_node) nodes; /* Flat list of nodes */ } SG; #define SGNODE(node) ((struct sg_node *)(node)) #define SGNODE_OPS(node) ((struct sg_node_class *)(AGOBJECT(node)->cls)) #define SGNODE_SELECTED(node) (((SG_Node *)(node))->flags & SG_NODE_SELECTED) /* Iterate over attached nodes in the SG. */ #define SG_FOREACH_NODE(node, sg) \ for((node) = AG_TAILQ_FIRST(&sg->nodes); \ (node) != AG_TAILQ_END(&sg->nodes); \ (node) = AG_TAILQ_NEXT(SGNODE(node), nodes)) /* Iterate over all selected nodes in the SG. */ #define SG_FOREACH_NODE_SELECTED(node, sg) \ SG_FOREACH_NODE((node),sg) \ if (!((node)->flags & SG_NODE_SELECTED)) { \ continue; \ } else /* Built-in classes and subsystems */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include __BEGIN_DECLS extern AG_ObjectClass sgClass; extern SG_NodeClass sgNodeClass; void SG_InitSubsystem(void); void SG_DestroySubsystem(void); SG *SG_New(void *, const char *, Uint); void *SG_Edit(void *); void SG_RenderNode(SG *, SG_Node *, struct sg_view *); int SG_NodeSave(SG *, SG_Node *, AG_DataSource *); int SG_NodeLoad(SG *, SG_Node **, AG_DataSource *); SG_Node *SG_SearchNodes(SG_Node *, const char *); void *SG_FindNode(SG *, const char *); void SG_GetNodeTransform(void *, M_Matrix44 *); void SG_GetNodeTransformInverse(void *, M_Matrix44 *); void *SG_NodeEdit(void *); #define SG_Identity(n) M_MatIdentity44v(&SGNODE(n)->T) #define SG_Translatev(n,v) M_MatTranslate44v(&SGNODE(n)->T,(v)) #define SG_Translate(n,x,y,z) M_MatTranslate44(&SGNODE(n)->T,(x),(y),(z)) #define SG_TranslateX(n,t) M_MatTranslate44X(&SGNODE(n)->T,(t)) #define SG_TranslateY(n,t) M_MatTranslate44Y(&SGNODE(n)->T,(t)) #define SG_TranslateZ(n,t) M_MatTranslate44Z(&SGNODE(n)->T,(t)) #define SG_Scale(n,s) M_MatUniScale44(&SGNODE(n)->T,(s)) #define SG_Rotatev(n,a,d) M_MatRotateAxis44(&SGNODE(n)->T,(a),(d)) #define SG_RotateI(n,d) M_MatRotate44I(&SGNODE(n)->T,(d)) #define SG_RotateJ(n,d) M_MatRotate44J(&SGNODE(n)->T,(d)) #define SG_RotateK(n,d) M_MatRotate44K(&SGNODE(n)->T,(d)) #define SG_Rotatevd(n,a,v) M_MatRotateAxis44(&SGNODE(n)->T,M_Radians(a),(v)) #define SG_RotateId(n,a) M_MatRotate44I(&SGNODE(n)->T,M_Radians(a)) #define SG_RotateJd(n,a) M_MatRotate44J(&SGNODE(n)->T,M_Radians(a)) #define SG_RotateKd(n,a) M_MatRotate44K(&SGNODE(n)->T,M_Radians(a)) #define SG_Orbitv(n,p,a,d) M_MatOrbitAxis44(&SGNODE(n)->T, \ M_VecSub3((p),SG_NodePos(n)),(a),(d)); #define SG_Orbitvd(n,p,a,d) SG_Orbitv((n),(p),(a),M_Radians(d)) /* Return the absolute (world) coordinates of a node. */ static __inline__ M_Vector3 SG_NodePos(void *p) { SG_Node *node = (SG_Node *)p; M_Matrix44 T; M_Vector3 v = M_VecZero3(); SG_GetNodeTransformInverse(node, &T); M_MatMult44Vector3v(&v, &T); return (v); } /* Return the absolute (world) direction of a node. */ static __inline__ M_Vector3 SG_NodeDir(void *p) { SG_Node *node = (SG_Node *)p; M_Matrix44 T; M_Vector3 v = M_VecK3(); /* Convention */ SG_GetNodeTransform(node, &T); M_MatMult44Vector3v(&v, &T); return (v); } /* Return the absolute scaling factor of a node. */ static __inline__ M_Real SG_NodeSize(void *p) { SG_Node *node = p; M_Matrix44 T; SG_GetNodeTransform(node, &T); return (T.m[0][0]); } /* Compute the intersection(s) between a node and a geometrical object. */ static __inline__ int SG_Intersect(SG_Node *node, M_Geom3 g, M_GeomSet3 *S) { SG_NodeClass *nc = (SG_NodeClass *)AGOBJECT_CLASS(node); if (nc->intersect == NULL) { return (-1); } return nc->intersect(node, g, S); } __END_DECLS #include #endif /* _FREESG_SG_H_ */