also rename mesh_getVertexCos() --> BKE_mesh_vertexCos_get() to match curve function.
170 lines
4.4 KiB
C++
170 lines
4.4 KiB
C++
/*
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
*
|
|
* This program 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 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* The Original Code is Copyright (C) 2009 Blender Foundation.
|
|
* All rights reserved.
|
|
*
|
|
* The Original Code is: all of this file.
|
|
*
|
|
* Contributor(s): André Pinto.
|
|
*
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
*/
|
|
|
|
/** \file blender/render/intern/raytrace/rayobject_blibvh.cpp
|
|
* \ingroup render
|
|
*/
|
|
|
|
#include <assert.h>
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
#include "BLI_kdopbvh.h"
|
|
#include "BLI_math.h"
|
|
#include "BLI_utildefines.h"
|
|
|
|
#include "rayintersection.h"
|
|
#include "rayobject.h"
|
|
|
|
static int RE_rayobject_blibvh_intersect(RayObject *o, Isect *isec);
|
|
static void RE_rayobject_blibvh_add(RayObject *o, RayObject *ob);
|
|
static void RE_rayobject_blibvh_done(RayObject *o);
|
|
static void RE_rayobject_blibvh_free(RayObject *o);
|
|
static void RE_rayobject_blibvh_bb(RayObject *o, float min[3], float max[3]);
|
|
|
|
static float RE_rayobject_blibvh_cost(RayObject *UNUSED(o))
|
|
{
|
|
//TODO calculate the expected cost to raycast on this structure
|
|
return 1.0;
|
|
}
|
|
|
|
static void RE_rayobject_blibvh_hint_bb(RayObject *UNUSED(o), RayHint *UNUSED(hint),
|
|
float *UNUSED(min), float *UNUSED(max))
|
|
{
|
|
return;
|
|
}
|
|
|
|
static RayObjectAPI bvh_api =
|
|
{
|
|
RE_rayobject_blibvh_intersect,
|
|
RE_rayobject_blibvh_add,
|
|
RE_rayobject_blibvh_done,
|
|
RE_rayobject_blibvh_free,
|
|
RE_rayobject_blibvh_bb,
|
|
RE_rayobject_blibvh_cost,
|
|
RE_rayobject_blibvh_hint_bb
|
|
};
|
|
|
|
typedef struct BVHObject {
|
|
RayObject rayobj;
|
|
RayObject **leafs, **next_leaf;
|
|
BVHTree *bvh;
|
|
float bb[2][3];
|
|
} BVHObject;
|
|
|
|
RayObject *RE_rayobject_blibvh_create(int size)
|
|
{
|
|
BVHObject *obj = (BVHObject *)MEM_callocN(sizeof(BVHObject), "BVHObject");
|
|
assert(RE_rayobject_isAligned(obj)); /* RayObject API assumes real data to be 4-byte aligned */
|
|
|
|
obj->rayobj.api = &bvh_api;
|
|
obj->bvh = BLI_bvhtree_new(size, 0.0, 4, 6);
|
|
obj->next_leaf = obj->leafs = (RayObject **)MEM_callocN(size * sizeof(RayObject *), "BVHObject leafs");
|
|
|
|
INIT_MINMAX(obj->bb[0], obj->bb[1]);
|
|
return RE_rayobject_unalignRayAPI((RayObject *) obj);
|
|
}
|
|
|
|
struct BVHCallbackUserData {
|
|
Isect *isec;
|
|
RayObject **leafs;
|
|
};
|
|
|
|
static void bvh_callback(void *userdata, int index, const BVHTreeRay *UNUSED(ray), BVHTreeRayHit *hit)
|
|
{
|
|
struct BVHCallbackUserData *data = (struct BVHCallbackUserData *)userdata;
|
|
Isect *isec = data->isec;
|
|
RayObject *face = data->leafs[index];
|
|
|
|
if (RE_rayobject_intersect(face, isec)) {
|
|
hit->index = index;
|
|
|
|
if (isec->mode == RE_RAY_SHADOW)
|
|
hit->dist = 0;
|
|
else
|
|
hit->dist = isec->dist;
|
|
}
|
|
}
|
|
|
|
static int RE_rayobject_blibvh_intersect(RayObject *o, Isect *isec)
|
|
{
|
|
BVHObject *obj = (BVHObject *)o;
|
|
BVHTreeRayHit hit;
|
|
float dir[3];
|
|
struct BVHCallbackUserData data;
|
|
data.isec = isec;
|
|
data.leafs = obj->leafs;
|
|
|
|
copy_v3_v3(dir, isec->dir);
|
|
|
|
hit.index = 0;
|
|
hit.dist = isec->dist;
|
|
|
|
return BLI_bvhtree_ray_cast(obj->bvh, isec->start, dir, 0.0, &hit, bvh_callback, (void *)&data);
|
|
}
|
|
|
|
static void RE_rayobject_blibvh_add(RayObject *o, RayObject *ob)
|
|
{
|
|
BVHObject *obj = (BVHObject *)o;
|
|
float min_max[6];
|
|
INIT_MINMAX(min_max, min_max + 3);
|
|
RE_rayobject_merge_bb(ob, min_max, min_max + 3);
|
|
|
|
DO_MIN(min_max, obj->bb[0]);
|
|
DO_MAX(min_max + 3, obj->bb[1]);
|
|
|
|
BLI_bvhtree_insert(obj->bvh, obj->next_leaf - obj->leafs, min_max, 2);
|
|
*(obj->next_leaf++) = ob;
|
|
}
|
|
|
|
static void RE_rayobject_blibvh_done(RayObject *o)
|
|
{
|
|
BVHObject *obj = (BVHObject *)o;
|
|
BLI_bvhtree_balance(obj->bvh);
|
|
}
|
|
|
|
static void RE_rayobject_blibvh_free(RayObject *o)
|
|
{
|
|
BVHObject *obj = (BVHObject *)o;
|
|
|
|
if (obj->bvh)
|
|
BLI_bvhtree_free(obj->bvh);
|
|
|
|
if (obj->leafs)
|
|
MEM_freeN(obj->leafs);
|
|
|
|
MEM_freeN(obj);
|
|
}
|
|
|
|
static void RE_rayobject_blibvh_bb(RayObject *o, float min[3], float max[3])
|
|
{
|
|
BVHObject *obj = (BVHObject *)o;
|
|
DO_MIN(obj->bb[0], min);
|
|
DO_MAX(obj->bb[1], max);
|
|
}
|
|
|