Cycles: Move object culling helper to own files
This is a stand-alone logic, which becomes quite comprehensive now.
This commit is contained in:
parent
893aa1cae3
commit
d8a8f69c98
|
@ -25,6 +25,7 @@ set(SRC
|
|||
blender_camera.cpp
|
||||
blender_mesh.cpp
|
||||
blender_object.cpp
|
||||
blender_object_cull.cpp
|
||||
blender_particles.cpp
|
||||
blender_curves.cpp
|
||||
blender_logging.cpp
|
||||
|
@ -35,6 +36,7 @@ set(SRC
|
|||
blender_texture.cpp
|
||||
|
||||
CCL_api.h
|
||||
blender_object_cull.h
|
||||
blender_sync.h
|
||||
blender_session.h
|
||||
blender_texture.h
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "particles.h"
|
||||
#include "shader.h"
|
||||
|
||||
#include "blender_object_cull.h"
|
||||
#include "blender_sync.h"
|
||||
#include "blender_util.h"
|
||||
|
||||
|
@ -88,143 +89,6 @@ static uint object_ray_visibility(BL::Object& b_ob)
|
|||
return flag;
|
||||
}
|
||||
|
||||
/* Culling */
|
||||
|
||||
class BlenderObjectCulling
|
||||
{
|
||||
public:
|
||||
BlenderObjectCulling(Scene *scene, BL::Scene& b_scene)
|
||||
: use_scene_camera_cull(false),
|
||||
use_camera_cull(false),
|
||||
camera_cull_margin(0.0f),
|
||||
use_scene_distance_cull(false),
|
||||
use_distance_cull(false),
|
||||
distance_cull_margin(0.0f)
|
||||
{
|
||||
if(b_scene.render().use_simplify()) {
|
||||
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
|
||||
|
||||
use_scene_camera_cull = scene->camera->type != CAMERA_PANORAMA &&
|
||||
!b_scene.render().use_multiview() &&
|
||||
get_boolean(cscene, "use_camera_cull");
|
||||
use_scene_distance_cull = scene->camera->type != CAMERA_PANORAMA &&
|
||||
!b_scene.render().use_multiview() &&
|
||||
get_boolean(cscene, "use_distance_cull");
|
||||
|
||||
camera_cull_margin = get_float(cscene, "camera_cull_margin");
|
||||
distance_cull_margin = get_float(cscene, "distance_cull_margin");
|
||||
|
||||
if (distance_cull_margin == 0.0f) {
|
||||
use_scene_distance_cull = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void init_object(Scene *scene, BL::Object& b_ob)
|
||||
{
|
||||
if(!use_scene_camera_cull && !use_scene_distance_cull) {
|
||||
return;
|
||||
}
|
||||
|
||||
PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
|
||||
|
||||
use_camera_cull = use_scene_camera_cull && get_boolean(cobject, "use_camera_cull");
|
||||
use_distance_cull = use_scene_distance_cull && get_boolean(cobject, "use_distance_cull");
|
||||
|
||||
if(use_camera_cull || use_distance_cull) {
|
||||
/* Need to have proper projection matrix. */
|
||||
scene->camera->update();
|
||||
}
|
||||
}
|
||||
|
||||
bool test(Scene *scene, BL::Object& b_ob, Transform& tfm)
|
||||
{
|
||||
if(!use_camera_cull && !use_distance_cull) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Compute world space bounding box corners. */
|
||||
float3 bb[8];
|
||||
BL::Array<float, 24> boundbox = b_ob.bound_box();
|
||||
for(int i = 0; i < 8; ++i) {
|
||||
float3 p = make_float3(boundbox[3 * i + 0],
|
||||
boundbox[3 * i + 1],
|
||||
boundbox[3 * i + 2]);
|
||||
bb[i] = transform_point(&tfm, p);
|
||||
}
|
||||
|
||||
bool camera_culled = use_camera_cull && test_camera(scene, bb);
|
||||
bool distance_culled = use_distance_cull && test_distance(scene, bb);
|
||||
|
||||
return ((camera_culled && distance_culled) ||
|
||||
(camera_culled && !use_distance_cull) ||
|
||||
(distance_culled && !use_camera_cull));
|
||||
}
|
||||
|
||||
private:
|
||||
/* TODO(sergey): Not really optimal, consider approaches based on k-DOP in order
|
||||
* to reduce number of objects which are wrongly considered visible.
|
||||
*/
|
||||
bool test_camera(Scene *scene, float3 bb[8])
|
||||
{
|
||||
Camera *cam = scene->camera;
|
||||
Transform& worldtondc = cam->worldtondc;
|
||||
float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
|
||||
bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||
bool all_behind = true;
|
||||
for(int i = 0; i < 8; ++i) {
|
||||
float3 p = bb[i];
|
||||
float4 b = make_float4(p.x, p.y, p.z, 1.0f);
|
||||
float4 c = make_float4(dot(worldtondc.x, b),
|
||||
dot(worldtondc.y, b),
|
||||
dot(worldtondc.z, b),
|
||||
dot(worldtondc.w, b));
|
||||
p = float4_to_float3(c / c.w);
|
||||
if(c.z < 0.0f) {
|
||||
p.x = 1.0f - p.x;
|
||||
p.y = 1.0f - p.y;
|
||||
}
|
||||
if(c.z >= -camera_cull_margin) {
|
||||
all_behind = false;
|
||||
}
|
||||
bb_min = min(bb_min, p);
|
||||
bb_max = max(bb_max, p);
|
||||
}
|
||||
if(all_behind) {
|
||||
return true;
|
||||
}
|
||||
return (bb_min.x >= 1.0f + camera_cull_margin ||
|
||||
bb_min.y >= 1.0f + camera_cull_margin ||
|
||||
bb_max.x <= -camera_cull_margin ||
|
||||
bb_max.y <= -camera_cull_margin);
|
||||
}
|
||||
|
||||
bool test_distance(Scene *scene, float3 bb[8])
|
||||
{
|
||||
float3 camera_position = transform_get_column(&scene->camera->matrix, 3);
|
||||
float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
|
||||
bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||
|
||||
/* Find min & max points for x & y & z on bounding box */
|
||||
for(int i = 0; i < 8; ++i) {
|
||||
float3 p = bb[i];
|
||||
bb_min = min(bb_min, p);
|
||||
bb_max = max(bb_max, p);
|
||||
}
|
||||
|
||||
float3 closest_point = max(min(bb_max,camera_position),bb_min);
|
||||
return (len_squared(camera_position - closest_point) >
|
||||
distance_cull_margin * distance_cull_margin);
|
||||
}
|
||||
|
||||
bool use_scene_camera_cull;
|
||||
bool use_camera_cull;
|
||||
float camera_cull_margin;
|
||||
bool use_scene_distance_cull;
|
||||
bool use_distance_cull;
|
||||
float distance_cull_margin;
|
||||
};
|
||||
|
||||
/* Light */
|
||||
|
||||
void BlenderSync::sync_light(BL::Object& b_parent,
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright 2011-2016 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "camera.h"
|
||||
|
||||
#include "blender_object_cull.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
BlenderObjectCulling::BlenderObjectCulling(Scene *scene, BL::Scene& b_scene)
|
||||
: use_scene_camera_cull_(false),
|
||||
use_camera_cull_(false),
|
||||
camera_cull_margin_(0.0f),
|
||||
use_scene_distance_cull_(false),
|
||||
use_distance_cull_(false),
|
||||
distance_cull_margin_(0.0f)
|
||||
{
|
||||
if(b_scene.render().use_simplify()) {
|
||||
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
|
||||
|
||||
use_scene_camera_cull_ = scene->camera->type != CAMERA_PANORAMA &&
|
||||
!b_scene.render().use_multiview() &&
|
||||
get_boolean(cscene, "use_camera_cull");
|
||||
use_scene_distance_cull_ = scene->camera->type != CAMERA_PANORAMA &&
|
||||
!b_scene.render().use_multiview() &&
|
||||
get_boolean(cscene, "use_distance_cull");
|
||||
|
||||
camera_cull_margin_ = get_float(cscene, "camera_cull_margin");
|
||||
distance_cull_margin_ = get_float(cscene, "distance_cull_margin");
|
||||
|
||||
if (distance_cull_margin_ == 0.0f) {
|
||||
use_scene_distance_cull_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BlenderObjectCulling::init_object(Scene *scene, BL::Object& b_ob)
|
||||
{
|
||||
if(!use_scene_camera_cull_ && !use_scene_distance_cull_) {
|
||||
return;
|
||||
}
|
||||
|
||||
PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
|
||||
|
||||
use_camera_cull_ = use_scene_camera_cull_ && get_boolean(cobject, "use_camera_cull");
|
||||
use_distance_cull_ = use_scene_distance_cull_ && get_boolean(cobject, "use_distance_cull");
|
||||
|
||||
if(use_camera_cull_ || use_distance_cull_) {
|
||||
/* Need to have proper projection matrix. */
|
||||
scene->camera->update();
|
||||
}
|
||||
}
|
||||
|
||||
bool BlenderObjectCulling::test(Scene *scene, BL::Object& b_ob, Transform& tfm)
|
||||
{
|
||||
if(!use_camera_cull_ && !use_distance_cull_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Compute world space bounding box corners. */
|
||||
float3 bb[8];
|
||||
BL::Array<float, 24> boundbox = b_ob.bound_box();
|
||||
for(int i = 0; i < 8; ++i) {
|
||||
float3 p = make_float3(boundbox[3 * i + 0],
|
||||
boundbox[3 * i + 1],
|
||||
boundbox[3 * i + 2]);
|
||||
bb[i] = transform_point(&tfm, p);
|
||||
}
|
||||
|
||||
bool camera_culled = use_camera_cull_ && test_camera(scene, bb);
|
||||
bool distance_culled = use_distance_cull_ && test_distance(scene, bb);
|
||||
|
||||
return ((camera_culled && distance_culled) ||
|
||||
(camera_culled && !use_distance_cull_) ||
|
||||
(distance_culled && !use_camera_cull_));
|
||||
}
|
||||
|
||||
/* TODO(sergey): Not really optimal, consider approaches based on k-DOP in order
|
||||
* to reduce number of objects which are wrongly considered visible.
|
||||
*/
|
||||
bool BlenderObjectCulling::test_camera(Scene *scene, float3 bb[8])
|
||||
{
|
||||
Camera *cam = scene->camera;
|
||||
Transform& worldtondc = cam->worldtondc;
|
||||
float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
|
||||
bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||
bool all_behind = true;
|
||||
for(int i = 0; i < 8; ++i) {
|
||||
float3 p = bb[i];
|
||||
float4 b = make_float4(p.x, p.y, p.z, 1.0f);
|
||||
float4 c = make_float4(dot(worldtondc.x, b),
|
||||
dot(worldtondc.y, b),
|
||||
dot(worldtondc.z, b),
|
||||
dot(worldtondc.w, b));
|
||||
p = float4_to_float3(c / c.w);
|
||||
if(c.z < 0.0f) {
|
||||
p.x = 1.0f - p.x;
|
||||
p.y = 1.0f - p.y;
|
||||
}
|
||||
if(c.z >= -camera_cull_margin_) {
|
||||
all_behind = false;
|
||||
}
|
||||
bb_min = min(bb_min, p);
|
||||
bb_max = max(bb_max, p);
|
||||
}
|
||||
if(all_behind) {
|
||||
return true;
|
||||
}
|
||||
return (bb_min.x >= 1.0f + camera_cull_margin_ ||
|
||||
bb_min.y >= 1.0f + camera_cull_margin_ ||
|
||||
bb_max.x <= -camera_cull_margin_ ||
|
||||
bb_max.y <= -camera_cull_margin_);
|
||||
}
|
||||
|
||||
bool BlenderObjectCulling::test_distance(Scene *scene, float3 bb[8])
|
||||
{
|
||||
float3 camera_position = transform_get_column(&scene->camera->matrix, 3);
|
||||
float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
|
||||
bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||
|
||||
/* Find min & max points for x & y & z on bounding box */
|
||||
for(int i = 0; i < 8; ++i) {
|
||||
float3 p = bb[i];
|
||||
bb_min = min(bb_min, p);
|
||||
bb_max = max(bb_max, p);
|
||||
}
|
||||
|
||||
float3 closest_point = max(min(bb_max,camera_position),bb_min);
|
||||
return (len_squared(camera_position - closest_point) >
|
||||
distance_cull_margin_ * distance_cull_margin_);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2011-2016 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __BLENDER_OBJECT_CULL_H__
|
||||
#define __BLENDER_OBJECT_CULL_H__
|
||||
|
||||
#include "blender_sync.h"
|
||||
#include "util_types.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class Scene;
|
||||
|
||||
class BlenderObjectCulling
|
||||
{
|
||||
public:
|
||||
BlenderObjectCulling(Scene *scene, BL::Scene& b_scene);
|
||||
|
||||
void init_object(Scene *scene, BL::Object& b_ob);
|
||||
bool test(Scene *scene, BL::Object& b_ob, Transform& tfm);
|
||||
|
||||
private:
|
||||
bool test_camera(Scene *scene, float3 bb[8]);
|
||||
bool test_distance(Scene *scene, float3 bb[8]);
|
||||
|
||||
bool use_scene_camera_cull_;
|
||||
bool use_camera_cull_;
|
||||
float camera_cull_margin_;
|
||||
bool use_scene_distance_cull_;
|
||||
bool use_distance_cull_;
|
||||
float distance_cull_margin_;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BLENDER_OBJECT_CULL_H__ */
|
Loading…
Reference in New Issue