Tachyon (current)  Current Main Branch
box.c
Go to the documentation of this file.
1 /*
2  * box.c - This file contains the functions for dealing with boxes.
3  *
4  * (C) Copyright 1994-2022 John E. Stone
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * $Id: box.c,v 1.25 2022/02/18 17:55:28 johns Exp $
8  *
9  */
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <math.h>
15 
16 #define TACHYON_INTERNAL 1
17 #include "tachyon.h"
18 #include "macros.h"
19 #include "box.h"
20 #include "vector.h"
21 #include "intersect.h"
22 #include "util.h"
23 
24 int box_bbox(void * obj, vector * min, vector * max) {
25  box * b = (box *) obj;
26 
27  *min = b->min;
28  *max = b->max;
29 
30  return 1;
31 }
32 
33 static object_methods box_methods = {
34  (void (*)(const void *, void *))(box_intersect),
35  (void (*)(const void *, const void *, const void *, void *))(box_normal),
36  box_bbox,
37  free
38 };
39 
40 box * newbox(void * tex, vector min, vector max) {
41  box * b;
42 
43  b=(box *) malloc(sizeof(box));
44  memset(b, 0, sizeof(box));
45  b->methods = &box_methods;
46  b->tex = tex;
47  b->min = min;
48  b->max = max;
49 
50  return b;
51 }
52 
53 void box_intersect(const box * bx, ray * ry) {
54  flt a, tx1, tx2, ty1, ty2, tz1, tz2;
55  flt tnear, tfar;
56 
57  tnear= -FHUGE;
58  tfar= FHUGE;
59 
60  if (ry->d.x == 0.0) {
61  if ((ry->o.x < bx->min.x) || (ry->o.x > bx->max.x)) return;
62  }
63  else {
64  tx1 = (bx->min.x - ry->o.x) / ry->d.x;
65  tx2 = (bx->max.x - ry->o.x) / ry->d.x;
66  if (tx1 > tx2) { a=tx1; tx1=tx2; tx2=a; }
67  if (tx1 > tnear) tnear=tx1;
68  if (tx2 < tfar) tfar=tx2;
69  }
70  if (tnear > tfar) return;
71  if (tfar < 0.0) return;
72 
73  if (ry->d.y == 0.0) {
74  if ((ry->o.y < bx->min.y) || (ry->o.y > bx->max.y)) return;
75  }
76  else {
77  ty1 = (bx->min.y - ry->o.y) / ry->d.y;
78  ty2 = (bx->max.y - ry->o.y) / ry->d.y;
79  if (ty1 > ty2) { a=ty1; ty1=ty2; ty2=a; }
80  if (ty1 > tnear) tnear=ty1;
81  if (ty2 < tfar) tfar=ty2;
82  }
83  if (tnear > tfar) return;
84  if (tfar < 0.0) return;
85 
86  if (ry->d.z == 0.0) {
87  if ((ry->o.z < bx->min.z) || (ry->o.z > bx->max.z)) return;
88  }
89  else {
90  tz1 = (bx->min.z - ry->o.z) / ry->d.z;
91  tz2 = (bx->max.z - ry->o.z) / ry->d.z;
92  if (tz1 > tz2) { a=tz1; tz1=tz2; tz2=a; }
93  if (tz1 > tnear) tnear=tz1;
94  if (tz2 < tfar) tfar=tz2;
95  }
96  if (tnear > tfar) return;
97  if (tfar < 0.0) return;
98 
99  ry->add_intersection(tnear, (const object *) bx, ry);
100  ry->add_intersection(tfar, (object *) bx, ry);
101 }
102 
103 void box_normal(const box * bx, const vector * pnt, const ray * incident, vector * N) {
104  vector a, b, c;
105  flt t;
106 
107  c.x=(bx->max.x + bx->min.x) / 2.0;
108  c.y=(bx->max.y + bx->min.y) / 2.0;
109  c.z=(bx->max.z + bx->min.z) / 2.0;
110 
111  VSub((vector *) pnt, &c, N);
112  b=(*N);
113 
114 #if 1
115  /* arbitrary rectangular boxes */
116  a.x=FABS(N->x / (bx->max.x - bx->min.x));
117  a.y=FABS(N->y / (bx->max.y - bx->min.y));
118  a.z=FABS(N->z / (bx->max.z - bx->min.z));
119 #else
120  /* cubic boxes only */
121  a.x=FABS(N->x);
122  a.y=FABS(N->y);
123  a.z=FABS(N->z);
124 #endif
125 
126  N->x=0.0; N->y=0.0; N->z=0.0;
127 
128  t=MYMAX(a.x, MYMAX(a.y, a.z));
129 
130  if (t==a.x) N->x=b.x;
131 
132  if (t==a.y) N->y=b.y;
133 
134  if (t==a.z) N->z=b.z;
135 
136  VNorm(N);
137 
138  /* Flip surface normal to point toward the viewer if necessary */
139  if (VDot(N, &(incident->d)) > 0.0) {
140  N->x=-N->x;
141  N->y=-N->y;
142  N->z=-N->z;
143  }
144 }
145 
static object_methods box_methods
Definition: box.c:33
RT_OBJECT_HEAD vector min
minimum vertex coordinate
Definition: box.h:16
box * newbox(void *tex, vector min, vector max)
Definition: box.c:40
void box_intersect(const box *bx, ray *ry)
Definition: box.c:53
void VNorm(apivector *)
void VSub(apivector *a, apivector *b, apivector *c)
flt VDot(apivector *a, apivector *b)
vector max
maximum vertex coordinate
Definition: box.h:17
double flt
generic floating point number, using double
Definition: tachyon.h:47
Tachyon cross-platform timers, special math function wrappers, and RNGs.
int box_bbox(void *obj, vector *min, vector *max)
Definition: box.c:24
Tachyon public API function prototypes and declarations used to drive the ray tracing engine...
void box_normal(const box *bx, const vector *pnt, const ray *incident, vector *N)
Definition: box.c:103
#define FABS(x)
Definition: util.h:28
#define MYMAX(a, b)
Definition: macros.h:12
axis-aligned box definition
Definition: box.h:14