Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F100423243
srcobstr.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Thu, Jan 30, 17:20
Size
10 KB
Mime Type
text/x-c
Expires
Sat, Feb 1, 17:20 (2 d)
Engine
blob
Format
Raw Data
Handle
23811387
Attached To
R10977 RADIANCE Photon Map
srcobstr.c
View Options
#ifndef lint
static
const
char
RCSid
[]
=
"$Id: srcobstr.c,v 2.19 2017/02/22 03:16:20 greg Exp $"
;
#endif
/*
* Source occlusion caching routines
*/
#include "ray.h"
#include "otypes.h"
#include "otspecial.h"
#include "rtotypes.h"
#include "source.h"
#if SHADCACHE
/* preemptive shadow checking */
#ifndef MAX2SHADE
#define MAX2SHADE 200
/* limit # of sources to precheck */
#endif
#define ABS(x) ((x)>0 ? (x) : -(x))
OBJECT
*
antimodlist
=
NULL
;
/* set of clipped materials */
static
int
/* cast source ray to first blocker */
castshadow
(
int
sn
,
FVECT
rorg
,
FVECT
rdir
)
{
RAY
rt
;
VCOPY
(
rt
.
rorg
,
rorg
);
VCOPY
(
rt
.
rdir
,
rdir
);
rt
.
rmax
=
0
;
rayorigin
(
&
rt
,
PRIMARY
,
NULL
,
NULL
);
/* check for intersection */
while
(
localhit
(
&
rt
,
&
thescene
))
{
RAY
rt1
=
rt
;
/* pretend we were aimed at source */
rt1
.
crtype
|=
rt1
.
rtype
=
SHADOW
;
rt1
.
rdir
[
0
]
=
-
rt
.
rdir
[
0
];
rt1
.
rdir
[
1
]
=
-
rt
.
rdir
[
1
];
rt1
.
rdir
[
2
]
=
-
rt
.
rdir
[
2
];
rt1
.
rod
=
-
rt
.
rod
;
VSUB
(
rt1
.
rorg
,
rt
.
rop
,
rt
.
rdir
);
rt1
.
rot
=
1.
;
rt1
.
rsrc
=
sn
;
/* record blocker */
if
(
srcblocker
(
&
rt1
))
return
(
1
);
/* move past failed blocker */
VSUM
(
rt
.
rorg
,
rt
.
rop
,
rt
.
rdir
,
FTINY
);
rayclear
(
&
rt
);
/* & try again... */
}
return
(
0
);
/* found no blockers */
}
void
/* initialize occlusion cache */
initobscache
(
int
sn
)
{
SRCREC
*
srcp
=
&
source
[
sn
];
int
cachelen
;
FVECT
rorg
,
rdir
;
RREAL
d
;
int
i
,
j
,
k
;
int
ax
=
0
,
ax1
=
1
,
ax2
=
2
;
if
(
srcp
->
sflags
&
(
SSKIP
|
SPROX
|
SSPOT
|
SVIRTUAL
))
return
;
/* don't cache these */
if
(
srcp
->
sflags
&
SDISTANT
)
cachelen
=
4
*
SHADCACHE
*
SHADCACHE
;
else
if
(
srcp
->
sflags
&
SFLAT
)
cachelen
=
SHADCACHE
*
SHADCACHE
*
3
+
(
SHADCACHE
&
1
)
*
SHADCACHE
*
4
;
else
/* spherical distribution */
cachelen
=
SHADCACHE
*
SHADCACHE
*
6
;
/* allocate cache */
srcp
->
obscache
=
(
OBSCACHE
*
)
malloc
(
sizeof
(
OBSCACHE
)
+
sizeof
(
OBJECT
)
*
(
cachelen
-
1
));
if
(
srcp
->
obscache
==
NULL
)
error
(
SYSTEM
,
"out of memory in initobscache()"
);
/* set parameters */
if
(
srcp
->
sflags
&
SDISTANT
)
{
RREAL
amax
=
0
;
for
(
ax1
=
3
;
ax1
--
;
)
if
(
ABS
(
srcp
->
sloc
[
ax1
])
>
amax
)
{
amax
=
ABS
(
srcp
->
sloc
[
ax1
]);
ax
=
ax1
;
}
srcp
->
obscache
->
p
.
d
.
ax
=
ax
;
ax1
=
(
ax
+
1
)
%
3
;
ax2
=
(
ax
+
2
)
%
3
;
VCOPY
(
srcp
->
obscache
->
p
.
d
.
o
,
thescene
.
cuorg
);
if
(
srcp
->
sloc
[
ax
]
>
0
)
srcp
->
obscache
->
p
.
d
.
o
[
ax
]
+=
thescene
.
cusize
;
if
(
srcp
->
sloc
[
ax1
]
<
0
)
srcp
->
obscache
->
p
.
d
.
o
[
ax1
]
+=
thescene
.
cusize
*
srcp
->
sloc
[
ax1
]
/
amax
;
if
(
srcp
->
sloc
[
ax2
]
<
0
)
srcp
->
obscache
->
p
.
d
.
o
[
ax2
]
+=
thescene
.
cusize
*
srcp
->
sloc
[
ax2
]
/
amax
;
srcp
->
obscache
->
p
.
d
.
e1
=
1.
/
(
thescene
.
cusize
*
(
1.
+
fabs
(
srcp
->
sloc
[
ax1
])
/
amax
));
srcp
->
obscache
->
p
.
d
.
e2
=
1.
/
(
thescene
.
cusize
*
(
1.
+
fabs
(
srcp
->
sloc
[
ax2
])
/
amax
));
}
else
if
(
srcp
->
sflags
&
SFLAT
)
{
VCOPY
(
srcp
->
obscache
->
p
.
f
.
u
,
srcp
->
ss
[
SU
]);
normalize
(
srcp
->
obscache
->
p
.
f
.
u
);
fcross
(
srcp
->
obscache
->
p
.
f
.
v
,
srcp
->
snorm
,
srcp
->
obscache
->
p
.
f
.
u
);
}
/* clear cache */
for
(
i
=
cachelen
;
i
--
;
)
srcp
->
obscache
->
obs
[
i
]
=
OVOID
;
#if (MAX2SHADE >= 0)
if
(
sn
>=
MAX2SHADE
)
/* limit on prechecking */
return
;
#endif
/* cast shadow rays */
if
(
srcp
->
sflags
&
SDISTANT
)
{
for
(
k
=
3
;
k
--
;
)
rdir
[
k
]
=
-
srcp
->
sloc
[
k
];
for
(
i
=
2
*
SHADCACHE
;
i
--
;
)
for
(
j
=
2
*
SHADCACHE
;
j
--
;
)
{
VCOPY
(
rorg
,
srcp
->
obscache
->
p
.
d
.
o
);
rorg
[
ax1
]
+=
(
i
+
.5
)
/
(
2
*
SHADCACHE
*
srcp
->
obscache
->
p
.
d
.
e1
);
rorg
[
ax2
]
+=
(
j
+
.5
)
/
(
2
*
SHADCACHE
*
srcp
->
obscache
->
p
.
d
.
e2
);
castshadow
(
sn
,
rorg
,
rdir
);
}
}
else
if
(
srcp
->
sflags
&
SFLAT
)
{
d
=
0.01
*
srcp
->
srad
;
VSUM
(
rorg
,
srcp
->
sloc
,
srcp
->
snorm
,
d
);
for
(
i
=
SHADCACHE
;
i
--
;
)
for
(
j
=
SHADCACHE
;
j
--
;
)
{
d
=
2.
/
SHADCACHE
*
(
i
+
.5
)
-
1.
;
VSUM
(
rdir
,
srcp
->
snorm
,
srcp
->
obscache
->
p
.
f
.
u
,
d
);
d
=
2.
/
SHADCACHE
*
(
j
+
.5
)
-
1.
;
VSUM
(
rdir
,
rdir
,
srcp
->
obscache
->
p
.
f
.
v
,
d
);
normalize
(
rdir
);
castshadow
(
sn
,
rorg
,
rdir
);
}
for
(
k
=
2
;
k
--
;
)
for
(
i
=
SHADCACHE
;
i
--
;
)
for
(
j
=
SHADCACHE
>>
1
;
j
--
;
)
{
d
=
2.
/
SHADCACHE
*
(
i
+
.5
)
-
1.
;
if
(
k
)
VSUM
(
rdir
,
srcp
->
obscache
->
p
.
f
.
u
,
srcp
->
obscache
->
p
.
f
.
v
,
d
);
else
VSUM
(
rdir
,
srcp
->
obscache
->
p
.
f
.
v
,
srcp
->
obscache
->
p
.
f
.
u
,
d
);
d
=
1.
-
2.
/
SHADCACHE
*
(
j
+
.5
);
VSUM
(
rdir
,
rdir
,
srcp
->
snorm
,
d
);
normalize
(
rdir
);
castshadow
(
sn
,
rorg
,
rdir
);
d
=
2.
*
DOT
(
rdir
,
srcp
->
snorm
);
rdir
[
0
]
=
d
*
srcp
->
snorm
[
0
]
-
rdir
[
0
];
rdir
[
1
]
=
d
*
srcp
->
snorm
[
1
]
-
rdir
[
1
];
rdir
[
2
]
=
d
*
srcp
->
snorm
[
2
]
-
rdir
[
2
];
castshadow
(
sn
,
rorg
,
rdir
);
}
}
else
/* spherical distribution */
for
(
k
=
6
;
k
--
;
)
{
ax
=
k
%
3
;
ax1
=
(
k
+
1
)
%
3
;
ax2
=
(
k
+
2
)
%
3
;
for
(
i
=
SHADCACHE
;
i
--
;
)
for
(
j
=
SHADCACHE
;
j
--
;
)
{
rdir
[
0
]
=
rdir
[
1
]
=
rdir
[
2
]
=
0.
;
rdir
[
ax
]
=
k
<
3
?
1.
:
-
1.
;
rdir
[
ax1
]
=
2.
/
SHADCACHE
*
(
i
+
.5
)
-
1.
;
rdir
[
ax2
]
=
2.
/
SHADCACHE
*
(
j
+
.5
)
-
1.
;
normalize
(
rdir
);
d
=
1.05
*
srcp
->
srad
;
VSUM
(
rorg
,
srcp
->
sloc
,
rdir
,
d
);
castshadow
(
sn
,
rorg
,
rdir
);
}
}
}
static
OBJECT
*
/* return occluder cache entry */
srcobstructp
(
RAY
*
r
)
{
static
RNUMBER
lastrno
=
~
0
;
static
OBJECT
noobs
;
static
OBJECT
*
lastobjp
;
SRCREC
*
srcp
;
int
ondx
;
noobs
=
OVOID
;
if
(
r
->
rno
==
lastrno
)
return
lastobjp
;
/* just recall last pointer */
DCHECK
(
r
->
rsrc
<
0
,
CONSISTENCY
,
"srcobstructp() called with unaimed ray"
);
lastrno
=
r
->
rno
;
lastobjp
=
&
noobs
;
srcp
=
&
source
[
r
->
rsrc
];
if
(
srcp
->
sflags
&
(
SSKIP
|
SPROX
|
SSPOT
|
SVIRTUAL
))
return
(
&
noobs
);
/* don't cache these */
if
(
srcp
->
obscache
==
NULL
)
/* initialize cache */
initobscache
(
r
->
rsrc
);
/* compute cache index */
if
(
srcp
->
sflags
&
SDISTANT
)
{
int
ax
=
0
,
ax1
=
1
,
ax2
=
2
;
double
t
;
ax
=
srcp
->
obscache
->
p
.
d
.
ax
;
if
((
ax1
=
ax
+
1
)
>=
3
)
ax1
-=
3
;
if
((
ax2
=
ax
+
2
)
>=
3
)
ax2
-=
3
;
t
=
(
srcp
->
obscache
->
p
.
d
.
o
[
ax
]
-
r
->
rorg
[
ax
])
/
srcp
->
sloc
[
ax
];
if
(
t
<=
FTINY
)
return
(
&
noobs
);
/* could happen if ray is outside */
ondx
=
2
*
SHADCACHE
*
(
int
)(
2
*
SHADCACHE
*
srcp
->
obscache
->
p
.
d
.
e1
*
(
r
->
rorg
[
ax1
]
+
t
*
srcp
->
sloc
[
ax1
]
-
srcp
->
obscache
->
p
.
d
.
o
[
ax1
]));
ondx
+=
(
int
)(
2
*
SHADCACHE
*
srcp
->
obscache
->
p
.
d
.
e2
*
(
r
->
rorg
[
ax2
]
+
t
*
srcp
->
sloc
[
ax2
]
-
srcp
->
obscache
->
p
.
d
.
o
[
ax2
]));
if
((
ondx
<
0
)
|
(
ondx
>=
4
*
SHADCACHE
*
SHADCACHE
))
return
(
&
noobs
);
/* could happen if ray is outside */
}
else
if
(
srcp
->
sflags
&
SFLAT
)
{
FVECT
sd
;
RREAL
sd0m
,
sd1m
;
sd
[
0
]
=
-
DOT
(
r
->
rdir
,
srcp
->
obscache
->
p
.
f
.
u
);
sd
[
1
]
=
-
DOT
(
r
->
rdir
,
srcp
->
obscache
->
p
.
f
.
v
);
sd
[
2
]
=
-
DOT
(
r
->
rdir
,
srcp
->
snorm
);
if
(
sd
[
2
]
<
0
)
return
(
&
noobs
);
/* shouldn't happen */
sd0m
=
ABS
(
sd
[
0
]);
sd1m
=
ABS
(
sd
[
1
]);
if
(
sd
[
2
]
>=
sd0m
&&
sd
[
2
]
>=
sd1m
)
{
ondx
=
SHADCACHE
*
(
int
)(
SHADCACHE
*
(
.5
-
FTINY
)
*
(
1.
+
sd
[
0
]
/
sd
[
2
]));
ondx
+=
(
int
)(
SHADCACHE
*
(
.5
-
FTINY
)
*
(
1.
+
sd
[
1
]
/
sd
[
2
]));
}
else
if
(
sd0m
>=
sd1m
)
{
ondx
=
SHADCACHE
*
SHADCACHE
;
if
(
sd
[
0
]
<
0
)
ondx
+=
((
SHADCACHE
+
1
)
>>
1
)
*
SHADCACHE
;
ondx
+=
SHADCACHE
*
(
int
)(
SHADCACHE
*
(
.5
-
FTINY
)
*
(
1.
-
sd
[
2
]
/
sd0m
));
ondx
+=
(
int
)(
SHADCACHE
*
(
.5
-
FTINY
)
*
(
1.
+
sd
[
1
]
/
sd0m
));
}
else
/* sd1m > sd0m */
{
ondx
=
SHADCACHE
*
SHADCACHE
+
((
SHADCACHE
+
1
)
>>
1
)
*
SHADCACHE
*
2
;
if
(
sd
[
1
]
<
0
)
ondx
+=
((
SHADCACHE
+
1
)
>>
1
)
*
SHADCACHE
;
ondx
+=
SHADCACHE
*
(
int
)(
SHADCACHE
*
(
.5
-
FTINY
)
*
(
1.
-
sd
[
2
]
/
sd1m
));
ondx
+=
(
int
)(
SHADCACHE
*
(
.5
-
FTINY
)
*
(
1.
+
sd
[
0
]
/
sd1m
));
}
DCHECK
((
ondx
<
0
)
|
(
ondx
>=
SHADCACHE
*
SHADCACHE
*
3
+
(
SHADCACHE
&
1
)
*
SHADCACHE
*
4
),
CONSISTENCY
,
"flat source cache index out of bounds"
);
}
else
/* spherical distribution */
{
int
ax
,
ax1
,
ax2
;
RREAL
amax
=
0
;
for
(
ax1
=
3
;
ax1
--
;
)
if
(
ABS
(
r
->
rdir
[
ax1
])
>
amax
)
{
amax
=
ABS
(
r
->
rdir
[
ax1
]);
ax
=
ax1
;
}
if
((
ax1
=
ax
+
1
)
>=
3
)
ax1
-=
3
;
if
((
ax2
=
ax
+
2
)
>=
3
)
ax2
-=
3
;
ondx
=
2
*
SHADCACHE
*
SHADCACHE
*
ax
;
if
(
r
->
rdir
[
ax
]
<
0
)
ondx
+=
SHADCACHE
*
SHADCACHE
;
ondx
+=
SHADCACHE
*
(
int
)(
SHADCACHE
*
(
.5
-
FTINY
)
*
(
1.
+
r
->
rdir
[
ax1
]
/
amax
));
ondx
+=
(
int
)(
SHADCACHE
*
(
.5
-
FTINY
)
*
(
1.
+
r
->
rdir
[
ax2
]
/
amax
));
DCHECK
((
ondx
<
0
)
|
(
ondx
>=
SHADCACHE
*
SHADCACHE
*
6
),
CONSISTENCY
,
"radial source cache index out of bounds"
);
}
/* return cache pointer */
return
(
lastobjp
=
&
srcp
->
obscache
->
obs
[
ondx
]);
}
void
/* free obstruction cache */
freeobscache
(
SRCREC
*
srcp
)
{
if
(
srcp
->
obscache
==
NULL
)
return
;
free
((
void
*
)
srcp
->
obscache
);
srcp
->
obscache
=
NULL
;
}
int
/* record a source blocker */
srcblocker
(
RAY
*
r
)
{
OBJREC
*
m
;
if
(
r
->
robj
==
OVOID
||
objptr
(
r
->
robj
)
!=
r
->
ro
||
isvolume
(
r
->
ro
->
otype
))
return
(
0
);
/* don't record complex blockers */
if
(
r
->
rsrc
<
0
||
source
[
r
->
rsrc
].
so
==
r
->
ro
)
return
(
0
);
/* just a mistake, that's all */
if
(
antimodlist
!=
NULL
&&
inset
(
antimodlist
,
r
->
ro
->
omod
))
return
(
0
);
/* could be clipped */
m
=
findmaterial
(
r
->
ro
);
if
(
m
==
NULL
)
return
(
0
);
/* no material?! */
if
(
!
isopaque
(
m
->
otype
))
return
(
0
);
/* material not a reliable blocker */
*
srcobstructp
(
r
)
=
r
->
robj
;
/* else record obstructor */
return
(
1
);
}
int
/* check ray against cached blocker */
srcblocked
(
RAY
*
r
)
{
OBJECT
obs
=
*
srcobstructp
(
r
);
OBJREC
*
op
;
if
(
obs
==
OVOID
)
return
(
0
);
op
=
objptr
(
obs
);
/* check blocker intersection */
if
(
!
(
*
ofun
[
op
->
otype
].
funp
)(
op
,
r
))
return
(
0
);
if
(
source
[
r
->
rsrc
].
sflags
&
SDISTANT
)
return
(
1
);
op
=
source
[
r
->
rsrc
].
so
;
/* check source intersection */
if
(
!
(
*
ofun
[
op
->
otype
].
funp
)(
op
,
r
))
return
(
1
);
rayclear
(
r
);
return
(
0
);
/* source in front */
}
void
/* record potentially clipped materials */
markclip
(
OBJREC
*
m
)
{
OBJECT
*
set2add
,
*
oldset
;
if
(
m
==
NULL
)
{
/* starting over */
if
(
antimodlist
!=
NULL
)
free
((
void
*
)
antimodlist
);
antimodlist
=
NULL
;
return
;
}
m_clip
(
m
,
NULL
);
/* initialize modifier list */
if
((
set2add
=
(
OBJECT
*
)
m
->
os
)
==
NULL
||
!
set2add
[
0
])
return
;
if
(
antimodlist
==
NULL
)
{
/* start of list */
antimodlist
=
setsave
(
set2add
);
return
;
}
/* else add to previous list */
oldset
=
antimodlist
;
antimodlist
=
(
OBJECT
*
)
malloc
((
oldset
[
0
]
+
set2add
[
0
]
+
1
)
*
sizeof
(
OBJECT
));
if
(
antimodlist
==
NULL
)
error
(
SYSTEM
,
"out of memory in markclip"
);
setunion
(
antimodlist
,
oldset
,
set2add
);
free
((
void
*
)
oldset
);
}
#else
/* SHADCACHE */
void
/* no-op also avoids linker warning */
markclip
(
OBJREC
*
m
)
{
(
void
)
m
;
}
#endif
/* SHADCACHE */
Event Timeline
Log In to Comment