-
Notifications
You must be signed in to change notification settings - Fork 3
/
SceneObjectTransform.c
78 lines (52 loc) · 2.47 KB
/
SceneObjectTransform.c
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
#include "SceneObjectTransform.h"
const SceneObjectVTable sceneObjectTransformVTable = (SceneObjectVTable) {
&sceneObjectTransformIntersectRay,
&sceneObjectTransformEmitPhotons,
&sceneObjectTransformRadiantFlux
};
SceneObjectTransform makeSceneObjectTransform (const Matrix transform, const SceneObject *subject) {
return (SceneObjectTransform) {makeSceneObject(&sceneObjectTransformVTable), subject, transform, mInversed(transform)};
}
defineAllocator(SceneObjectTransform)
Intersection sceneObjectTransformIntersectRay(const SceneObject *superobject, const Ray ray) {
const SceneObjectTransform *object = (SceneObjectTransform *) superobject;
// Inverse-transform the ray, so the subject appears transformed.
Ray transformedRay = mrMul(object->inversedTransform, ray);
// Forward the actual intersecting.
Intersection intersection = sceneObjectIntersectRay(object->subject, transformedRay);
// Transform the intersecion back into world space.
if (intersection.hitType) {
intersection.normal = mvMulDir(object->transform, intersection.normal );
intersection.position = mvMul (object->transform, intersection.position);
intersection.distance = intersection.distance * mScale(object->transform);
}
return intersection;
}
bool sceneObjectTransformEmitPhotons(const SceneObject *superobject, const int numPhotons, PhotonContainer *photons) {
const SceneObjectTransform *object = (SceneObjectTransform *) superobject;
// Save the new, local photons for processing.
PhotonContainer newPhotons = makePhotonContainer(numPhotons);
// Forward the actual creation of photons.
bool success = sceneObjectEmitPhotons(object->subject, numPhotons, &newPhotons);
if (success) {
// Transform the photons.
float scale = mScale(object->transform);
float areaScale = scale * scale;
containerForeach(Photon, photon, newPhotons) {
photon->heading = mrMul(object->transform, photon->heading);
photon->energy = csMul(photon->energy, areaScale);
}
// "Return" the new, transformed photons.
photonContainerAddValues(photons, newPhotons);
}
// Done with the local photons.
photonContainerDestroy(&newPhotons);
return success;
}
Color sceneObjectTransformRadiantFlux(const SceneObject *superobject) {
const SceneObjectTransform *object = (SceneObjectTransform *) superobject;
// Forward the flux calculation.
Color radiantFlux = sceneObjectRadiantFlux(object->subject);
float scale = mScale(object->transform);
return csMul(radiantFlux, scale * scale);
}