sl@0: /* sl@0: * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: Node interface sl@0: * sl@0: */ sl@0: sl@0: #ifndef __M3G_NODE_H__ sl@0: #define __M3G_NODE_H__ sl@0: sl@0: /*! sl@0: * \internal sl@0: * \file sl@0: * \brief Node interface sl@0: */ sl@0: sl@0: #include "m3g_transformable.h" sl@0: sl@0: #include "m3g_gl.h" sl@0: #include "m3g_math.h" sl@0: #include "m3g_lightmanager.h" sl@0: #include "m3g_renderqueue.h" sl@0: sl@0: #define NODE_ALPHA_FACTOR_BITS 16 sl@0: sl@0: /* NOTE: Implementation depends on these values -- do not change! */ sl@0: #define CULLMASK_OUTSIDE 0x0 sl@0: #define CULLMASK_INSIDE 0x1 sl@0: #define CULLMASK_INTERSECTS 0x2 sl@0: #define CULLMASK_ALL 0xAAA sl@0: M3G_CT_ASSERT(CULLMASK_INSIDE == (CULLMASK_INTERSECTS >> 1)); sl@0: sl@0: /* sl@0: * Estimated load metrics for VF culling sl@0: * sl@0: */ sl@0: #define VFC_BBOX_COST 30 sl@0: #define VFC_NODE_OVERHEAD 10 sl@0: #define VFC_RENDERCALL_OVERHEAD 15 sl@0: #define VFC_TRIANGLE_COST 1 sl@0: #define VFC_VERTEX_COST 1 sl@0: sl@0: /* sl@0: * Enable bit masks sl@0: */ sl@0: #define NODE_RENDER_BIT 0x1 sl@0: #define NODE_PICK_BIT 0x2 sl@0: sl@0: /*! sl@0: * \internal sl@0: * \brief RayIntersection object sl@0: */ sl@0: struct M3GRayIntersectionImpl sl@0: { sl@0: Node *root; sl@0: Camera *camera; sl@0: M3Gfloat x; sl@0: M3Gfloat y; sl@0: M3Gfloat tMin; sl@0: M3Gfloat distance; sl@0: M3Gint submeshIndex; sl@0: M3Gfloat textureS[M3G_NUM_TEXTURE_UNITS]; sl@0: M3Gfloat textureT[M3G_NUM_TEXTURE_UNITS]; sl@0: M3Gfloat normal[3]; sl@0: Node *intersected; sl@0: }; sl@0: sl@0: /* sl@0: RayIntersection Java side result must be in this format. sl@0: sl@0: Offsets Contents sl@0: ------------------------------------- sl@0: 0 distance sl@0: 1 subMeshIndex sl@0: 2-3 textureS coordinates sl@0: 4-5 textureT coordinates sl@0: 6-8 normal coordinates sl@0: 9-14 ray coordinates and direction sl@0: sl@0: */ sl@0: sl@0: /*! sl@0: * \internal sl@0: * \brief Recursively inherited state passed to each SetupRender call sl@0: */ sl@0: typedef struct sl@0: { sl@0: Matrix toCamera; sl@0: M3Gbitmask cullMask; sl@0: } SetupRenderState; sl@0: sl@0: /* Function pointer prototypes */ sl@0: sl@0: typedef M3Gbool (*m3gAlignFuncPtr) (Node *self, const Node *refNode); sl@0: typedef void (*m3gDoRenderFuncPtr) (Node *self, RenderContext *ctx, const Matrix *toCamera, M3Gint patchIndex); sl@0: typedef M3Gint (*m3gGetBBoxFuncPtr) (Node *self, AABB *bbox); sl@0: typedef M3Gbool (*m3gRayIntersectFuncPtr) (Node *self, M3Gint mask, M3Gfloat *ray, RayIntersection *ri, Matrix *toGroup); sl@0: typedef M3Gbool (*m3gSetupRenderFuncPtr) (Node *self, const Node *caller, SetupRenderState *rs, RenderQueue *renderQueue); sl@0: typedef void (*m3gUpdateDuplicateRefFuncPtr) (Node *self, Object **pairs, M3Gint numPairs); sl@0: typedef M3Gbool (*m3gValidate) (Node *self, M3Gbitmask state, M3Gint scope); sl@0: sl@0: /*! sl@0: * \internal sl@0: * \brief Node class virtual functions sl@0: */ sl@0: typedef struct sl@0: { sl@0: TransformableVFTable transformable; sl@0: sl@0: m3gAlignFuncPtr align; sl@0: m3gDoRenderFuncPtr doRender; sl@0: m3gGetBBoxFuncPtr getBBox; sl@0: m3gRayIntersectFuncPtr rayIntersect; sl@0: m3gSetupRenderFuncPtr setupRender; sl@0: m3gUpdateDuplicateRefFuncPtr updateDuplicateReferences; sl@0: m3gValidate validate; sl@0: } NodeVFTable; sl@0: sl@0: /*! sl@0: * \internal sl@0: * \brief Node class structure sl@0: * sl@0: */ sl@0: struct M3GNodeImpl sl@0: { sl@0: Transformable transformable; sl@0: sl@0: /* See default values form RI implementation Node.java */ sl@0: sl@0: /* These scene graph pointers are managed by the Group class */ sl@0: sl@0: Node *parent; sl@0: Node *left; sl@0: Node *right; sl@0: sl@0: M3Gint scope; sl@0: sl@0: /* Alignment references */ sl@0: sl@0: Node *zReference; sl@0: Node *yReference; sl@0: sl@0: /* Various node flags and other bitfield data */ sl@0: sl@0: M3Guint alphaFactor : NODE_ALPHA_FACTOR_BITS; sl@0: sl@0: M3Guint zTarget : 3; /* Z alignment target */ sl@0: M3Guint yTarget : 3; /* Y alignment target */ sl@0: sl@0: M3Guint enableBits : 2; /* Rendering/picking enable bits */ sl@0: sl@0: M3Guint hasBones : 1; /* Node is part of a SkinnedMesh skeleton */ sl@0: M3Guint hasRenderables : 1; /* Node has renderables in its subtree */ sl@0: sl@0: M3Guint dirtyBits : 2; /* BBox and transform dirty bits */ sl@0: }; sl@0: sl@0: /*! sl@0: * \internal \brief Node bounding box in valid/dirty bitmasks sl@0: */ sl@0: #define NODE_BBOX_BIT 0x01 sl@0: /*! sl@0: * \internal \brief Node-child transformations in valid/dirty bitmasks sl@0: */ sl@0: #define NODE_TRANSFORMS_BIT 0x02 sl@0: sl@0: /* Sanity check; check compiler padding settings if this assert fails */ sl@0: sl@0: M3G_CT_ASSERT(sizeof(Node) == sizeof(Transformable) + 28); sl@0: sl@0: sl@0: /*---------------------------------------------------------------------- sl@0: * Virtual functions sl@0: *--------------------------------------------------------------------*/ sl@0: sl@0: static void m3gDestroyNode(Object *obj); sl@0: static M3Gbool m3gNodeAlign(Node *self, const Node *refNode); sl@0: static M3Gbool m3gNodeDuplicate(const Object *original, Object **clone, Object **pairs, M3Gint *numPairs); sl@0: static M3Gint m3gNodeGetBBox(Node *self, AABB *bbox); sl@0: static M3Gbool m3gNodeIsCompatible(M3Gint property); sl@0: static M3Gbool m3gNodeRayIntersect(Node *self, M3Gint mask, M3Gfloat *ray, RayIntersection *ri, Matrix *toGroup); sl@0: static void m3gNodeUpdateProperty(Object *self, M3Gint property, M3Gint valueSize, const M3Gfloat *value); sl@0: static void m3gNodeUpdateDuplicateReferences(Node *self, Object **pairs, M3Gint numPairs); sl@0: static M3Gbool m3gNodeValidate(Node *self, M3Gbitmask stateBits, M3Gint scope); sl@0: sl@0: sl@0: static M3G_INLINE M3Gint m3gGetNodeBBox(Node *node, AABB *bbox) sl@0: { sl@0: return M3G_VFUNC(Node, node, getBBox)(node, bbox); sl@0: } sl@0: sl@0: static M3G_INLINE M3Gbool m3gValidateNode(Node *node, M3Gbitmask stateBits, M3Gint scope) sl@0: { sl@0: return M3G_VFUNC(Node, node, validate)(node, stateBits, scope); sl@0: } sl@0: sl@0: /*---------------------------------------------------------------------- sl@0: * Internal functions sl@0: *--------------------------------------------------------------------*/ sl@0: sl@0: static void m3gInitNode(Interface *m3g, Node *node, M3GClass classID); sl@0: static M3Guint m3gGetTotalAlphaFactor(Node *node, const Node *root); sl@0: static M3Gbool m3gHasEnabledPath(const Node *node, const Node *root); sl@0: static M3Gbool m3gHasPickablePath(const Node *node, const Node *root); sl@0: static M3Gbool m3gIsChildOf(const Node *parent, const Node *child); sl@0: static Node *m3gGetRoot(const Node *node); sl@0: sl@0: static void m3gInvalidateNode(Node *node, M3Gbitmask flags); sl@0: sl@0: typedef void (*NodeFuncPtr) (Node *node, void *params); sl@0: static void m3gForSubtree (Node *node, NodeFuncPtr func, void *params); sl@0: sl@0: static void m3gSetParent (Node *node, Node *parent); sl@0: static Node *m3gGetDuplicatedInstance(Node *self, Object **references, M3Gint numRef); sl@0: sl@0: #if defined(M3G_ENABLE_VF_CULLING) sl@0: static void m3gUpdateCullingMask(SetupRenderState *s, const Camera *cam, const AABB *bbox); sl@0: #endif sl@0: sl@0: /*! sl@0: * \internal sl@0: * \brief Type-safe helper function sl@0: */ sl@0: static M3G_INLINE void m3gGetCompositeNodeTransform(const Node *node, Matrix *mtx) sl@0: { sl@0: m3gGetCompositeTransform((Transformable*) node, mtx); sl@0: M3G_ASSERT(m3gIsWUnity(mtx)); sl@0: } sl@0: sl@0: /*! sl@0: * \internal sl@0: * \brief Type-safe helper function sl@0: */ sl@0: static M3G_INLINE M3Gbool m3gGetInverseNodeTransform(const Node *node, Matrix *mtx) sl@0: { sl@0: M3Gbool ok = m3gGetInverseCompositeTransform((Transformable*) node, mtx); sl@0: M3G_ASSERT(m3gIsWUnity(mtx)); sl@0: return ok; sl@0: } sl@0: sl@0: #endif /*__M3G_NODE_H__*/