-
Notifications
You must be signed in to change notification settings - Fork 3
/
surface.cc
101 lines (83 loc) · 2.71 KB
/
surface.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// surface.cc -- Physical surface
//
// Copyright (C) 2005-2012 Miles Bader <miles@gnu.org>
//
// This source code is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 3, or (at
// your option) any later version. See the file COPYING for more details.
//
// Written by Miles Bader <miles@gnu.org>
//
#include <stdexcept>
#include "surface.h"
#include "space.h"
#include "space-builder.h"
using namespace snogray;
// Add this (or some other) surfaces to the space being built by
// SPACE_BUILDER.
//
void
Surface::add_to_space (SpaceBuilder &space_builder) const
{
space_builder.add (this);
}
// Surface::Sampler
// This constructor can be used to convert from an area-based
// sample to an angular sample from a specific viewpoint.
//
// If AREA_SAMPLE's normal points away from VIEWPOINT, meaning only the
// back-surface of the surface is visible from VIEWPOINT at that
// point, then the PDF of the angular sample will be set to zero.
//
Surface::Sampler::AngularSample::AngularSample (const AreaSample &area_sample,
const Pos &viewpoint)
: normal (area_sample.normal), pdf (0)
{
Vec view_vec = area_sample.pos - viewpoint;
// Distance to the sample.
//
dist = view_vec.length ();
if (dist > 0)
{
dist_t inv_dist = 1 / dist;
// DIR is a unit vector pointing towards the sample in normal-space.
//
dir = view_vec * inv_dist;
// PDF_COS_ADJ is a "cosine factor":
//
// cos (angle_between (-sample_normal, sample_dir))
// = dot (-sample_normal, sample_dir)
//
// It adjusts for the surface normal not being parallel to DIR.
// As the normal rotates away from DIR, the samples get
// scrunched up, so the PDF goes up.
//
float pdf_cos_adj = cos_angle (-normal, dir);
// If PDF_COS_ADJ is negative then the light points away from
// ISEC, and so can have no effect.
//
if (pdf_cos_adj > 0)
{
// Area to solid-angle conversion, dw/dA, where w is a solid
// angle in the hemisphere visible from the origin of VIEW_VEC.
//
float dw_dA = pdf_cos_adj * float (inv_dist * inv_dist);
pdf = area_sample.pdf / dw_dA;
}
}
}
// Return a sample of this surface from VIEWPOINT, based on the
// parameter PARAM.
//
// This method is optional; the default implementation calls the
// Surface::Sampler::sample method, and converts the result to an
// AngularSample.
//
Surface::Sampler::AngularSample
Surface::Sampler::sample_from_viewpoint (const Pos &viewpoint, const UV ¶m)
const
{
return AngularSample (sample (param), viewpoint);
}
// arch-tag: a62e1854-d7ca-4cb3-a8dc-9be328c53430