Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/render/camera.cpp')
-rw-r--r--intern/cycles/render/camera.cpp114
1 files changed, 114 insertions, 0 deletions
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index bb0fec759a9..4c73726ba33 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -15,14 +15,43 @@
*/
#include "camera.h"
+#include "mesh.h"
+#include "object.h"
#include "scene.h"
#include "device.h"
+#include "util_foreach.h"
#include "util_vector.h"
CCL_NAMESPACE_BEGIN
+namespace {
+
+bool object_has_volume(Scene *scene, Object *object)
+{
+ Mesh *mesh = object->mesh;
+ foreach(uint shader, mesh->used_shaders) {
+ if(scene->shaders[shader]->has_volume) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool scene_has_volume(Scene *scene)
+{
+ for(size_t i = 0; i < scene->objects.size(); ++i) {
+ Object *object = scene->objects[i];
+ if(object_has_volume(scene, object)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
+
Camera::Camera()
{
shuttertime = 1.0f;
@@ -270,6 +299,40 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
need_device_update = false;
previous_need_motion = need_motion;
+
+ /* Camera in volume. */
+ kcam->is_inside_volume = 0;
+ if(use_camera_in_volume) {
+ if(type == CAMERA_PANORAMA) {
+ /* It's not clear how to do viewplace->object intersection for
+ * panoramic cameras, for now let's just check for whether there
+ * are any volumes in the scene.
+ */
+ kcam->is_inside_volume = scene_has_volume(scene);
+ }
+ else {
+ /* TODO(sergey): Whole bunch of stuff here actually:
+ * - We do rather stupid check with object AABB to camera viewplane
+ * AABB intersection, which is quite fast to perform, but which
+ * could give some false-positives checks here, More grained check
+ * would help avoiding time wasted n the kernel to initialize the
+ * volume stack.
+ * - We could cache has_volume in the cache, would save quite a few
+ * CPU ticks when having loads of instanced meshes.
+ */
+ BoundBox viewplane_boundbox = viewplane_bounds_get();
+ for(size_t i = 0; i < scene->objects.size(); ++i) {
+ Object *object = scene->objects[i];
+ if(object_has_volume(scene, object)) {
+ if(viewplane_boundbox.intersects(object->bounds)) {
+ /* TODO(sergey): Consider adding more grained check. */
+ kcam->is_inside_volume = 1;
+ break;
+ }
+ }
+ }
+ }
+ }
}
void Camera::device_free(Device *device, DeviceScene *dscene)
@@ -313,5 +376,56 @@ void Camera::tag_update()
need_update = true;
}
+float3 Camera::transform_raster_to_world(float raster_x, float raster_y)
+{
+ float3 D, P;
+ if(type == CAMERA_PERSPECTIVE) {
+ D = transform_perspective(&rastertocamera,
+ make_float3(raster_x, raster_y, 0.0f));
+ P = make_float3(0.0f, 0.0f, 0.0f);
+ /* TODO(sergey): Aperture support? */
+ P = transform_point(&cameratoworld, P);
+ D = normalize(transform_direction(&cameratoworld, D));
+ /* TODO(sergey): Clipping is conditional in kernel, and hence it could
+ * be mistakes in here, currently leading to wrong camera-in-volume
+ * detection.
+ */
+ P += nearclip * D;
+ }
+ else if (type == CAMERA_ORTHOGRAPHIC) {
+ D = make_float3(0.0f, 0.0f, 1.0f);
+ /* TODO(sergey): Aperture support? */
+ P = transform_perspective(&rastertocamera,
+ make_float3(raster_x, raster_y, 0.0f));
+ P = transform_point(&cameratoworld, P);
+ D = normalize(transform_direction(&cameratoworld, D));
+ }
+ else {
+ assert(!"unsupported camera type");
+ }
+ return P;
+}
+
+BoundBox Camera::viewplane_bounds_get()
+{
+ assert(type != CAMERA_PANORAMA);
+
+ /* TODO(sergey): This is all rather stupid, but is there a way to perform
+ * checks we need in a more clear and smart fasion?
+ */
+ BoundBox bounds = BoundBox::empty;
+ bounds.grow(transform_raster_to_world(0.0f, 0.0f));
+ bounds.grow(transform_raster_to_world(0.0f, (float)height));
+ bounds.grow(transform_raster_to_world((float)width, (float)height));
+ bounds.grow(transform_raster_to_world((float)width, 0.0f));
+ if(type == CAMERA_PERSPECTIVE) {
+ /* Center point has the most distancei in local Z axis,
+ * use it to construct bounding box/
+ */
+ bounds.grow(transform_raster_to_world(0.5f*width, 0.5f*height));
+ }
+ return bounds;
+}
+
CCL_NAMESPACE_END