ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/oococt.h
(Generate patch)

Comparing ray/src/rt/oococt.h (file contents):
Revision 2.1 by greg, Tue Feb 24 19:39:26 2015 UTC vs.
Revision 2.4 by greg, Tue Sep 17 16:36:04 2024 UTC

# Line 1 | Line 1
1 #ifndef OOC_OCT_H
2 #define OOC_OCT_H
3
1   /*
2 <   ==================================================================
2 >   ======================================================================
3     Out-of-core octree data structure
4    
5     Roland Schregle (roland.schregle@{hslu.ch, gmail.com})
6 <   (c) Fraunhofer Institute for Solar Energy Systems,
7 <       Lucerne University of Applied Sciences & Arts  
8 <   ==================================================================
6 >   (c) Lucerne University of Applied Sciences and Arts,
7 >       supported by the Swiss National Science Foundation (SNSF, #147053)
8 >   ======================================================================
9    
10     $Id$
11   */
12  
13  
14 < #include "fvect.h"
14 > #ifndef OOC_OCT_H
15 > #define OOC_OCT_H
16  
17 +   #include "oocmorton.h"
18 +   #include "ooccache.h"
19 +   #include <stdint.h>
20 +   #include <stdio.h>
21  
20 /* Pointer to i-th record */
21 #define OOC_RECPTR(p,i) ((p) +
22  
23 < /* Default data block size (8k) */
24 < #define OOC_BLKBITS     13
25 < #define OOC_BLKSIZE     (1 << OOC_BLKBITS)
23 >   /* ===================================================================
24 >    * CONSTS
25 >    * =================================================================== */
26 >    
27 >   /* Octree index & data counter types */
28 >   typedef uint32_t           OOC_NodeIdx;
29 >   typedef uint32_t           OOC_DataIdx;  
30 >   typedef uint8_t            OOC_OctCnt;
31 >  
32 >   /* Octree node field sizes for above */  
33 >   #define OOC_NODEIDX_BITS   31
34 >   #define OOC_DATAIDX_BITS   32
35 >  
36 >   /* Limits for above */
37 >   #define OOC_NODEIDX_MAX    ((1L << OOC_NODEIDX_BITS) - 1)
38 >   #define OOC_DATAIDX_MAX    ((1L << OOC_DATAIDX_BITS) - 2)
39 >   #define OOC_OCTCNT_MAX     UINT8_MAX
40 >  
41 >   /* Reserved values for above */
42 >   #define OOC_DATAIDX_ERR    (OOC_DATAIDX_MAX + 1)
43 >  
44 >   /* Block size for node allocation (8k) */
45 >   #define OOC_BLKSIZE        (1L << 13)
46  
27 /* Index to data block and index within the block */
28 #define OOC_IDXTOBLK(i) ((i) >> OOC_BLKBITS)
29 #define OOC_IDXINBLK(i) ((i) & (1 << OOC_BLKBITS) - 1)
47  
31 /* Check for block overflow when adding node
32 #define OOC_BLKFULL(n)  ((!(n) * sizeof(OOC_Node) % OOC_BLKSIZE) */
48  
49 < /* Check for internal node, empty node, interior leaf, or terminal node
50 <   (8 leaves) */
51 < #define OOC_INTNODE(n)     ((n).num > 0 && (n).kid > 0)
37 < #define OOC_EMPTYNODE(n)   (!(n).num)
38 < #define OOC_INTLEAF(n)     ((n).kid < 0)
39 < #define OOC_TERMNODE(n)    ((n).num < 0)
49 >   /* ===================================================================
50 >    * UTILZ
51 >    * =================================================================== */  
52  
53 < /* Return record count and kid/leaf index for node */
54 < #define OOC_NUMREC(n)      abs((n).num)
55 < #define OOC_KID(n)         abs((n).kid)
53 >   /* Test/set leaf flag for node n */
54 >   #define OOC_ISLEAF(n)      ((n) -> node.type)
55 >   #define OOC_SETLEAF(n)     ((n) -> node.type = 1)
56 >  
57 >   /* Test/set branch bit for octant k in node n */
58 >   #define OOC_ISBRANCH(n,k)  (!OOC_ISLEAF(n) && (n) -> node.branch & 1 << (k))
59 >   #define OOC_SETBRANCH(n,k) ((n) -> node.branch |=  1 << (k))
60 >  
61 >   /* Return index to node's 1st kid */
62 >   #define OOC_KID1(o,n)      (!OOC_ISLEAF(n) ? (o)->nodes + (n)->node.kid \
63 >                                              : NULL)
64 >                                
65 >   /* Get index to last node in octree; -1 indicates empty octree */
66 >   #define OOC_ROOTIDX(o)     ((o) -> nodes && (o) -> numNodes > 0 \
67 >                                 ? (o) -> numNodes - 1 : -1)
68 >                                
69 >   /* Get octree root; this is at the *end* of the node array! */
70 >   #define OOC_ROOT(o)        (OOC_ROOTIDX(o) >= 0 \
71 >                                 ? (o) -> nodes + OOC_ROOTIDX(o) : NULL)
72 >  
73 >   /* Copy node to octree root */
74 >   #define OOC_SETROOT(o,n)   (memcpy(OOC_ROOT(o), (n), sizeof(OOC_Node)))
75  
76 < /* Check for loaded data block */
77 < #define OOC_LOADED(b)      ((b).dataBlk != NULL)
76 >   /* Set all node fields to 0 */  
77 >   #define OOC_CLEARNODE(n)   (memset((n), 0, sizeof(OOC_Node)))
78  
79 < /* (Mutually exclusive) operations on octree to be specified as flags */
80 < #define OOC_INSERT      1
81 < #define OOC_SEARCH      2
79 >   /* Modify origin o for octant k of size s */
80 >   #define OOC_OCTORIGIN(o,k,s)  ((o) [0] += (s) * ((k)      & 1), \
81 >                                  (o) [1] += (s) * ((k) >> 1 & 1), \
82 >                                  (o) [2] += (s) * ((k) >> 2 & 1))
83  
84 < /* Counter for records at leaves (2 bytes) */
85 < typedef unsigned short OOC_Leaf;
84 >   /* Get num records stored in node (also handles leaves and NULL pointer) */
85 >   #define OOC_DATACNT(n) \
86 >      ((n) ? OOC_ISLEAF(n) ? (n) -> leaf.num [0] + (n) -> leaf.num [1] + \
87 >                             (n) -> leaf.num [2] + (n) -> leaf.num [3] + \
88 >                             (n) -> leaf.num [4] + (n) -> leaf.num [5] + \
89 >                             (n) -> leaf.num [6] + (n) -> leaf.num [7]   \
90 >                           : (n) -> node.num \
91 >           : 0)
92  
93 < /* Node and record index type */
94 < typedef int OOC_Idx;
93 >   /* Shortcuts for morton code from key and data record */
94 >   #define OOC_KEY2MORTON(k, o)  OOC_Key2Morton((k), (o) -> org, \
95 >                                                (o) -> mortonScale)
96 >   #define OOC_REC2MORTON(r, o)  OOC_Key2Morton((o) -> key(r), (o) -> org, \
97 >                                                (o) -> mortonScale)
98  
58 /* Octree node */
59 typedef struct {
60   /*
61      For interior nodes (num > 0):
62         num = num records stored in this (sub)tree,
63         kid = index to 1st child node (immediately followed by its
64               siblings) in octree array.
65      
66      For interior leaves (kid < 0):
67         num = num records stored in leaf,
68         abs(kid) = index to single leaf, no siblings.
69        
70      For terminal nodes (num < 0):
71         abs(num) = num records stored in leaves,
72         kid = index to 1st of 8 leaves (immediately followed by its
73               siblings) in leaf array.
74   */
75   OOC_Idx        num, kid;
76 } OOC_Node;
99  
100  
101 < /* Load map entry; points to start of data block of size OOC_BLKSIZE, or
102 < * NULL if not loaded. LRU counter counts accesses for paging from disk */
103 < typedef struct {
104 <   void           *dataBlk;
105 <   unsigned long  lruCnt;
106 < } OOC_Load;
101 >   /* ===================================================================
102 >    * DATA TYPEZ
103 >    * =================================================================== */  
104 >                          
105 >   /* Octree node */
106 >   typedef struct {
107 >      union {
108 >         struct {
109 >            /* Interior node (node.type = 0) with:
110 >               node.kid    = index to 1st child node in octree array (a.k.a
111 >                             "Number One Son"), immediately followed by its
112 >                             nonzero siblings as indicated by branch
113 >               node.num    = num records stored in this subtree,
114 >               node.branch = branch bitmask indicating nonzero kid nodes */
115 >            char           type  : 1;
116 >            OOC_NodeIdx    kid   : OOC_NODEIDX_BITS;            
117 >            OOC_DataIdx    num   : OOC_DATAIDX_BITS;
118 >            uint8_t        branch;
119 >            
120 >            /* NOTE that we can't make the kid's index relative to parent
121 >             * (which would be more compact), since we don't know the
122 >             * parent's index a priori during the bottom-up construction! */
123 >         } node;
124  
125 +         struct {
126 +            /* Leaf node (leaf.type = node.type = 1 with:
127 +               leaf.num [k] = num records stored in octant k */
128 +            char           type  : 1;
129 +            OOC_OctCnt     num   [8];
130 +         } leaf;
131 +      };
132 +   } OOC_Node;
133  
87 /* Top level octree container */
88 typedef struct {
89   FVECT          org;        /* Cube origin (min. XYZ) and size */
90   RREAL          size;
91   OOC_Node       *root;      /* Pointer to node array */
92   OOC_Idx        maxNodes,   /* Num currently allocated nodes */
93                  numNodes;   /* Num used nodes (< maxNodes) */
94   OOC_Load       *loadMap;   /* Pointer to load map */
95   OOC_Leaf       *leaves;    /* Pointer to leaf array */
96   unsigned       recSize,    /* Size of data record in bytes */
97                  leafMax,    /* Max num records per leaf */
98                  maxDepth;   /* Max subdivision depth */
99 } OOC_Octree;
134  
135  
136 < /* Initialise octree for records of size recSize, return -1 on failure */
137 < int OOC_Init (OOC_Octree *oct, unsigned recSize, unsigned leafMax);
136 >   /* Top level octree container */
137 >   typedef struct {
138 >      FVECT          org, bound;    /* Cube origin (min. XYZ), size, and
139 >                                       resulting bounds (max. XYZ) */
140 >      RREAL          size,
141 >                     *(*key)(const void*); /* Callback for data rec coords */
142 >      RREAL          mortonScale;   /* Scale factor for generating Morton
143 >                                       codes from coords */
144 >      OOC_Node       *nodes;        /* Pointer to node array */
145 >                                    /* *************************************
146 >                                     * **** NODES ARE STORED IN POSTFIX ****
147 >                                     * **** ORDER, I.E. ROOT IS LAST!   ****
148 >                                     * *************************************/
149 >      OOC_DataIdx    numData;       /* Num records in leaves */
150 >      OOC_NodeIdx    maxNodes,      /* Num currently allocated nodes */
151 >                     numNodes;      /* Num used nodes (<= maxNodes) */
152 >      unsigned       recSize,       /* Size of data record in bytes */
153 >                     leafMax,       /* Max #records per leaf (for build) */
154 >                     maxDepth;      /* Max subdivision depth (for build) */
155 >      FILE           *leafFile;     /* File containing data in leaves */
156 >      OOC_Cache      *cache;        /* I/O cache for leafFile */
157 >   } OOC_Octree;
158  
159 < /* Return index of kid containing key, update origin and size accordingly */
106 < int OOC_Branch (FVECT key, FVECT org, RREAL *size);
159 >   /* DOAN' FORGET: NODES IN ***POSTFIX*** ORDAH!!! */
160  
161 < /* Return data index to leaf containing key, or -1 if not found */
162 < OOC_Idx OOC_Find (OOC_Octree *oct, FVECT key);
161 > #ifdef __cplusplus
162 > extern "C" {
163 > #endif
164  
111 #if 0
112 /* Return pointer to terminal node containing key */
113 OOC_Node *FindNode (OOC_Octree *oct, FVECT key);
165  
166 < /* Return index into data block for leaf containing key */
167 < OOC_Idx FindLeaf (OOC_Leaf *leaf, FVECT key);
166 >   /* ===================================================================
167 >    * FUNKZ
168 >    * =================================================================== */  
169 >
170 >   /* Init empty octree */
171 >   void OOC_Null (OOC_Octree *oct);
172 >
173 >    
174 >   /* Initialises octree for records of size recSize with 3D coordinates,
175 >    * accessed via key() callback.  The octree's bounding box is defined by
176 >    * its origin org and size per axis, and must contain all keys. The
177 >    * octree is associated with the specified leaf file containing the
178 >    * records in Morton order */
179 >   void OOC_Init (OOC_Octree *oct, unsigned recSize, FVECT org, RREAL size,
180 >                  RREAL *(*key)(const void*), FILE *leafFile);
181 >
182 >
183 >   /* Allocate new octree node, enlarge array if necessary.  Returns pointer
184 >      to new node or NULL if failed.  */
185 >   OOC_Node *NewNode (OOC_Octree *oct);
186 >
187 >
188 >   /* Reads indexed data record from leaf file and copies it to rec, else
189 >    * returns -1 on failure */
190 >   int OOC_GetData (OOC_Octree *oct, OOC_DataIdx idx, void *rec);
191 >  
192 >
193 >   /* Appends octree nodes to specified file along with metadata. Uses
194 >    * RADIANCE's portable I/O routines. Returns 0 on success, else -1. */
195 >   int OOC_SaveOctree (const OOC_Octree *oct, FILE *nodeFile);
196 >
197 >
198 >   /* Load octree nodes and metadata from nodeFile and associate with
199 >    * records in leafFile.  Uses RADIANCE's portable I/O routines.  Returns
200 >    * 0 on success, else -1.  */
201 >   int OOC_LoadOctree (OOC_Octree *oct, FILE *nodeFile,
202 >                       RREAL *(*key)(const void*), FILE *leafFile);
203 >
204 > #ifdef DEBUG_OOC
205 >   /* Traverse tree & check for valid nodes; oct -> leafFile must be open;
206 >    * return 0 if ok, otherwise -1 */
207 >   int OOC_Check (OOC_Octree *oct, const OOC_Node *node,
208 >                  FVECT org, RREAL size, OOC_DataIdx dataIdx);  
209   #endif
210  
211 +   /* Check whether key lies within bounding box defined by org and size */
212 +   int OOC_InBBox (const OOC_Octree *oct, const FVECT org, RREAL size,
213 +                   const FVECT key);
214 +
215 +   /* Return index of octant containing key and corresponding origin if
216 +    * nuOrg = NULL, or -1 if key lies outside all octants. Size is already
217 +    * assumed to be halved, i.e. corresponding to the length of an octant
218 +    * axis. */
219 +   int OOC_Branch (const OOC_Octree *oct, const FVECT org, RREAL size,
220 +                   const FVECT key, FVECT nuOrg);                  
221 +
222 +   /* Optimised version of OOC_Branch() with precomputed key Morton code */
223 +   int OOC_BranchZ (const OOC_Octree *oct, const FVECT org, RREAL size,
224 +                    OOC_MortonIdx keyZ, FVECT nuOrg);                  
225 +
226 +   /* For a given octree node, return the sum of the data counters for kids
227 +    * [0..k-1].  On return, the node either points to the k'th kid, or
228 +    * NULL if the kid is nonexistent or the node is a leaf */
229 +   OOC_DataIdx OOC_GetKid (const OOC_Octree *oct, OOC_Node **node,
230 +                           unsigned k);
231 +
232 +   /* Self-destruct */
233 +   void OOC_Delete (OOC_Octree *oct);
234 +
235 + #ifdef __cplusplus
236 + }
237 + #endif
238 +
239 +   /* DID WE MENTION NODES ARE IN POSTFIX ORDAH? */
240   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines