2009-05-29 22:55:06 +00:00
|
|
|
/**
|
|
|
|
|
* $Id$
|
|
|
|
|
*
|
|
|
|
|
* ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 *****
|
|
|
|
|
*/
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
#include "BKE_utildefines.h"
|
|
|
|
|
#include "BLI_kdopbvh.h"
|
|
|
|
|
#include "BLI_arithb.h"
|
|
|
|
|
#include "RE_raytrace.h"
|
|
|
|
|
#include "render_types.h"
|
|
|
|
|
#include "rayobject.h"
|
|
|
|
|
|
2009-08-25 20:26:50 +00:00
|
|
|
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, float *max);
|
2009-05-29 22:55:06 +00:00
|
|
|
|
|
|
|
|
static RayObjectAPI bvh_api =
|
|
|
|
|
{
|
2009-08-25 20:26:50 +00:00
|
|
|
RE_rayobject_blibvh_intersect,
|
|
|
|
|
RE_rayobject_blibvh_add,
|
|
|
|
|
RE_rayobject_blibvh_done,
|
|
|
|
|
RE_rayobject_blibvh_free,
|
|
|
|
|
RE_rayobject_blibvh_bb
|
2009-05-29 22:55:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef struct BVHObject
|
|
|
|
|
{
|
|
|
|
|
RayObject rayobj;
|
|
|
|
|
BVHTree *bvh;
|
2009-06-05 14:44:54 +00:00
|
|
|
float bb[2][3];
|
2009-05-29 22:55:06 +00:00
|
|
|
|
|
|
|
|
} BVHObject;
|
|
|
|
|
|
|
|
|
|
|
2009-06-30 22:07:42 +00:00
|
|
|
RayObject *RE_rayobject_blibvh_create(int size)
|
2009-05-29 22:55:06 +00:00
|
|
|
{
|
|
|
|
|
BVHObject *obj= (BVHObject*)MEM_callocN(sizeof(BVHObject), "BVHObject");
|
2009-08-25 20:26:50 +00:00
|
|
|
assert( RE_rayobject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */
|
2009-05-29 22:55:06 +00:00
|
|
|
|
|
|
|
|
obj->rayobj.api = &bvh_api;
|
2009-07-06 13:27:40 +00:00
|
|
|
obj->bvh = BLI_bvhtree_new(size, 0.0, 4, 6);
|
2009-05-29 22:55:06 +00:00
|
|
|
|
2009-06-05 14:44:54 +00:00
|
|
|
INIT_MINMAX(obj->bb[0], obj->bb[1]);
|
2009-08-25 20:26:50 +00:00
|
|
|
return RE_rayobject_unalignRayAPI((RayObject*) obj);
|
2009-05-29 22:55:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
|
|
|
|
|
{
|
2009-06-05 14:44:54 +00:00
|
|
|
Isect *isec = (Isect*)userdata;
|
2009-05-29 22:55:06 +00:00
|
|
|
RayObject *face = (RayObject*)index;
|
|
|
|
|
|
2009-06-05 14:44:54 +00:00
|
|
|
if(RE_rayobject_intersect(face,isec))
|
2009-05-29 22:55:06 +00:00
|
|
|
{
|
|
|
|
|
hit->index = index;
|
2009-05-31 02:35:58 +00:00
|
|
|
|
2009-06-05 14:44:54 +00:00
|
|
|
if(isec->mode == RE_RAY_SHADOW)
|
2009-05-31 02:35:58 +00:00
|
|
|
hit->dist = 0;
|
2009-06-11 16:44:01 +00:00
|
|
|
else
|
|
|
|
|
hit->dist = isec->labda*isec->dist;
|
2009-05-29 22:55:06 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-25 20:26:50 +00:00
|
|
|
static int RE_rayobject_blibvh_intersect(RayObject *o, Isect *isec)
|
2009-05-29 22:55:06 +00:00
|
|
|
{
|
|
|
|
|
BVHObject *obj = (BVHObject*)o;
|
2009-05-31 02:35:58 +00:00
|
|
|
BVHTreeRayHit hit;
|
2009-06-05 14:44:54 +00:00
|
|
|
float dir[3];
|
|
|
|
|
|
|
|
|
|
VECCOPY(dir, isec->vec);
|
|
|
|
|
Normalize(dir);
|
|
|
|
|
|
2009-05-31 02:35:58 +00:00
|
|
|
hit.index = 0;
|
2009-06-11 16:44:01 +00:00
|
|
|
hit.dist = isec->labda*isec->dist;
|
2009-05-29 22:55:06 +00:00
|
|
|
|
2009-06-05 14:44:54 +00:00
|
|
|
return BLI_bvhtree_ray_cast(obj->bvh, isec->start, dir, 0.0, &hit, bvh_callback, isec);
|
2009-05-29 22:55:06 +00:00
|
|
|
}
|
|
|
|
|
|
2009-08-25 20:26:50 +00:00
|
|
|
static void RE_rayobject_blibvh_add(RayObject *o, RayObject *ob)
|
2009-05-29 22:55:06 +00:00
|
|
|
{
|
|
|
|
|
BVHObject *obj = (BVHObject*)o;
|
|
|
|
|
float min_max[6];
|
|
|
|
|
INIT_MINMAX(min_max, min_max+3);
|
2009-06-05 14:44:54 +00:00
|
|
|
RE_rayobject_merge_bb(ob, min_max, min_max+3);
|
|
|
|
|
|
2009-07-07 19:07:53 +00:00
|
|
|
DO_MIN(min_max , obj->bb[0]);
|
|
|
|
|
DO_MAX(min_max+3, obj->bb[1]);
|
2009-06-05 14:44:54 +00:00
|
|
|
|
|
|
|
|
BLI_bvhtree_insert(obj->bvh, (int)ob, min_max, 2 );
|
2009-05-29 22:55:06 +00:00
|
|
|
}
|
|
|
|
|
|
2009-08-25 20:26:50 +00:00
|
|
|
static void RE_rayobject_blibvh_done(RayObject *o)
|
2009-05-29 22:55:06 +00:00
|
|
|
{
|
|
|
|
|
BVHObject *obj = (BVHObject*)o;
|
|
|
|
|
BLI_bvhtree_balance(obj->bvh);
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-25 20:26:50 +00:00
|
|
|
static void RE_rayobject_blibvh_free(RayObject *o)
|
2009-05-29 22:55:06 +00:00
|
|
|
{
|
|
|
|
|
BVHObject *obj = (BVHObject*)o;
|
|
|
|
|
|
|
|
|
|
if(obj->bvh)
|
|
|
|
|
BLI_bvhtree_free(obj->bvh);
|
|
|
|
|
|
|
|
|
|
MEM_freeN(obj);
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-25 20:26:50 +00:00
|
|
|
static void RE_rayobject_blibvh_bb(RayObject *o, float *min, float *max)
|
2009-05-29 22:55:06 +00:00
|
|
|
{
|
2009-06-05 14:44:54 +00:00
|
|
|
BVHObject *obj = (BVHObject*)o;
|
2009-07-07 19:07:53 +00:00
|
|
|
DO_MIN( obj->bb[0], min );
|
|
|
|
|
DO_MAX( obj->bb[1], max );
|
2009-05-29 22:55:06 +00:00
|
|
|
}
|