1 /* Copyright (C) 2006-2007 Claus-Justus Heine
2  *
3  * This file is part of Geomview.
4  *
5  * Geomview is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as published
7  * by the Free Software Foundation; either version 2, or (at your option)
8  * any later version.
9  *
10  * Geomview is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with Geomview; see the file COPYING.  If not, write
17  * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
18  * USA, or visit http://www.gnu.org.
19  */
20 #ifndef _GV_BSPTREE_P_H_
21 #define _GV_BSPTREE_P_H_
22 
23 #include "geomclass.h"
24 #include "nodedata.h"
25 #include "bsptree.h"
26 
27 #include "obstack.h"
28 
29 struct Poly;
30 
31 typedef struct PolyListNode PolyListNode;
32 struct PolyListNode
33 {
34   PolyListNode *next;
35   struct Poly  *poly;
36   Point3       *pn; /* If we split a polygon we compute the normal on
37 		     * the parent to avoid numerical instabilities
38 		     * caused by increasingly degenerated polygons.
39 		     */
40 
41   const void   **tagged_app; /* pointer to shared storage for the
42 			      * return value of mgtagappearance().
43 			      */
44 };
45 
46 typedef struct BSPTreeNode BSPTreeNode;
47 struct BSPTreeNode
48 {
49   BSPTreeNode  *front;
50   BSPTreeNode  *back;
51   HPoint3      plane;
52   PolyListNode *polylist;
53 };
54 
55 struct BSPTree {
56   BSPTreeNode  *tree;     /* The root of the BSPtree itself */
57   Geom         *geom;     /* The top-level Geom we belong to */
58   bool         oneshot;   /* Tree is destroyed after drawing; useful
59 			   * for location/oring != LOCAL INSTs and
60 			   * during ND-drawing. The oneshot flag is
61 			   * reset after it took affect.
62 			   */
63   PolyListNode   *init_lpl; /* While tree == NULL elements can be
64 			     * added to this list
65 			     */
66   TransformPtr Tid;       /* INST support: to support absolute
67 			   * positioning (location and origin !=
68 			   * LOCAL) we need the position of the
69 			   * top-level geometry (the one who owns the
70 			   * tree, i.e. tree->geom).
71 			   */
72   TransformPtr   Tidinv;    /* Inverse of Tid, only computed on demand */
73   TransformPtr   T;         /* INST support: transform polygons during
74 			     * tree generation, i.e. before adding
75 			     * them to init_lpl.
76 			     */
77   Transform      Tdual;     /* We need the dual of T to transform the normals
78 			     * correctly ( y^t x = 0 <=> y^t T T^{-tr}x = 0).
79 			     */
80   TransformPtr   TxT;       /* texture transform */
81   const void **tagged_app;
82 
83   struct obstack obst;  /* Scratch space for new polygons etc */
84 };
85 
86 /* if we have an appearance (but no handle to an appearance ) which
87  * overrides the transparency flag to false _or_ a material which
88  * overrides the alpha value to 1.0 (and no own color spec with alpha
89  * != 1.0) then we need not add ourselves to the BSP-tree: no facet of
90  * this Geom will ever be translucent.
91  *
92  * This does, of course, not work with INSTs or LISTs, but only with
93  * "atomic" Geom's
94  */
never_translucent(Geom * geom)95 static inline bool never_translucent(Geom *geom)
96 {
97   Appearance *ap = geom->ap;
98 
99   return (ap && !geom->aphandle &&
100 	  (((ap->override & APF_FACEDRAW) && (ap->flag & APF_FACEDRAW) == 0)
101 	   ||
102 	   ((ap->override & APF_TRANSP) && (ap->flag & APF_TRANSP) == 0)
103 	   ||
104 	   ((geom->geomflags & COLOR_ALPHA) == 0 && ap->mat &&
105 	    (ap->mat->override & MTF_ALPHA) && ap->mat->diffuse.a == 1.0)));
106 }
107 
108 /* Load the current transform form the MG-layer into tree->Tid */
BSPTreeSetId(BSPTree * tree)109 static inline void BSPTreeSetId(BSPTree *tree)
110 {
111   Transform T;
112 
113   if (tree->geom == NULL || tree != tree->geom->bsptree) {
114     abort();
115   }
116 
117   /* make sure the top-level geom has per-node data */
118   GeomNodeDataCreate(tree->geom, NULL);
119 
120   mggettransform(T);
121   if (memcmp(T, TM_IDENTITY, sizeof(Transform)) != 0) {
122     tree->Tid = obstack_alloc(&tree->obst, sizeof(Transform));
123     TmCopy(T, tree->Tid);
124   } else {
125     tree->Tid = TM_IDENTITY;
126   }
127   tree->Tidinv = NULL;
128 }
129 
BSPTreePushAppearance(BSPTree * bsptree,Geom * geom)130 static inline const void **BSPTreePushAppearance(BSPTree *bsptree, Geom *geom)
131 {
132   NodeData *data = GeomNodeDataCreate(geom, NULL);
133   const void **tagged_app = bsptree->tagged_app;
134 
135   bsptree->tagged_app = &data->tagged_ap;
136   return tagged_app;
137 }
138 
139 static inline void
BSPTreePopAppearance(BSPTree * bsptree,const void ** old_tagged_app)140 BSPTreePopAppearance(BSPTree *bsptree, const void **old_tagged_app)
141 {
142   if (bsptree != NULL && old_tagged_app != NULL) {
143     bsptree->tagged_app = old_tagged_app;
144   }
145 }
146 
BSPTreePushTransform(BSPTree * tree,TransformPtr T)147 static inline TransformPtr BSPTreePushTransform(BSPTree *tree, TransformPtr T)
148 {
149   TransformPtr old_T;
150 
151   if (tree != NULL) {
152     old_T = tree->T;
153     tree->T = T;
154     if (T != TM_IDENTITY) {
155       TmDual(T, tree->Tdual);
156     }
157     return old_T;
158   } else {
159     return TM_IDENTITY;
160   }
161 }
162 
BSPTreeSetTransform(BSPTree * tree,TransformPtr T)163 static inline void BSPTreeSetTransform(BSPTree *tree, TransformPtr T)
164 {
165   if (tree != NULL) {
166     tree->T = T;
167     if (T != TM_IDENTITY) {
168       TmDual(T, tree->Tdual);
169     }
170   }
171 }
172 
BSPTreePopTransform(BSPTree * tree,TransformPtr old_T)173 static inline void BSPTreePopTransform(BSPTree *tree, TransformPtr old_T)
174 {
175   if (tree != NULL) {
176     tree->T = old_T;
177     if (old_T != TM_IDENTITY) {
178       TmDual(old_T, tree->Tdual);
179     }
180   }
181 }
182 
BSPTreePushTxTransform(BSPTree * tree,TransformPtr T)183 static inline TransformPtr BSPTreePushTxTransform(BSPTree *tree, TransformPtr T)
184 {
185   TransformPtr old_TxT;
186 
187   if (tree != NULL) {
188     old_TxT = tree->TxT;
189     tree->TxT = T;
190     return old_TxT;
191   } else {
192     return TM_IDENTITY;
193   }
194 }
195 
BSPTreeSetTxTransform(BSPTree * tree,TransformPtr T)196 static inline void BSPTreeSetTxTransform(BSPTree *tree, TransformPtr T)
197 {
198   if (tree != NULL) {
199     tree->TxT = T;
200   }
201 }
202 
BSPTreePopTxTransform(BSPTree * tree,TransformPtr old_T)203 static inline void BSPTreePopTxTransform(BSPTree *tree, TransformPtr old_T)
204 {
205   if (tree != NULL) {
206     tree->TxT = old_T;
207   }
208 }
209 
210 #endif
211 
212 /*
213  * Local Variables: ***
214  * c-basic-offset: 2 ***
215  * End: ***
216  */
217