More files back in the 2.5 repo:
(Note, boolean stuff moved to blenkernel)
This commit is contained in:
Ton Roosendaal
2009-01-07 17:25:17 +00:00
parent 6bb75d2d19
commit 389dc100cc
7 changed files with 1536 additions and 3 deletions

View File

@@ -17,7 +17,7 @@
* 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) 2001-2002 by NaN Holding BV.
* The Original Code is Copyright (C) Blender Foundation.
* All rights reserved.
*
* The Original Code is: all of this file.
@@ -29,6 +29,7 @@
#ifndef BKE_BOOLEANOPS_H
#define BKE_BOOLEANOPS_H
struct Scene;
struct Object;
struct Base;
struct DerivedMesh;
@@ -36,7 +37,7 @@ struct DerivedMesh;
/* Performs a boolean between two mesh objects, it is assumed that both objects
are in fact a mesh object. On success returns 1 and creates a new mesh object
into blender data structures. On failure returns 0 and reports an error. */
int NewBooleanMesh(struct Base *base, struct Base *base_select, int op);
int NewBooleanMesh(struct Scene *scene, struct Base *base, struct Base *base_select, int op);
/* Performs a boolean between two mesh objects, it is assumed that both objects

View File

@@ -9,7 +9,7 @@ incs += ' ../imbuf ../avi #/intern/elbeem/extern ../nodes'
incs += ' #/intern/iksolver/extern ../blenloader'
incs += ' #/extern/bullet2/src'
incs += ' #/intern/bmfont'
incs += ' #/intern/opennl/extern'
incs += ' #/intern/opennl/extern #/intern/bsp/extern'
incs += ' ../gpu #/extern/glew/include'
incs += ' ' + env['BF_OPENGL_INC']

View File

@@ -69,6 +69,7 @@ CPPFLAGS += -I$(NAN_IKSOLVER)/include
CPPFLAGS += -I$(NAN_DECIMATION)/include
CPPFLAGS += -I$(NAN_ELBEEM)/include
CPPFLAGS += -I$(NAN_OPENNL)/include
CPPFLAGS += -I$(NAN_BSP)/include
# path to zlib
CPPFLAGS += -I$(NAN_ZLIB)/include

View File

@@ -0,0 +1,567 @@
/**
* $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) Blender Foundation
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
* CSG operations.
*/
#include <string.h>
#include <math.h>
#include "MEM_guardedalloc.h"
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "CSG_BooleanOps.h"
#include "BKE_booleanops.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_customdata.h"
#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_utildefines.h"
/**
* Here's the vertex iterator structure used to walk through
* the blender vertex structure.
*/
typedef struct {
Mesh *mesh;
Object *ob;
int pos;
} VertexIt;
/**
* Implementations of local vertex iterator functions.
* These describe a blender mesh to the CSG module.
*/
static void VertexIt_Destruct(CSG_VertexIteratorDescriptor * iterator)
{
if (iterator->it) {
// deallocate memory for iterator
MEM_freeN(iterator->it);
iterator->it = 0;
}
iterator->Done = NULL;
iterator->Fill = NULL;
iterator->Reset = NULL;
iterator->Step = NULL;
iterator->num_elements = 0;
}
static int VertexIt_Done(CSG_IteratorPtr it)
{
VertexIt * iterator = (VertexIt *)it;
return(iterator->pos >= iterator->mesh->totvert);
}
static void VertexIt_Fill(CSG_IteratorPtr it, CSG_IVertex *vert)
{
VertexIt * iterator = (VertexIt *)it;
MVert *verts = iterator->mesh->mvert;
float global_pos[3];
/* boolean happens in global space, transform both with obmat */
VecMat4MulVecfl(
global_pos,
iterator->ob->obmat,
verts[iterator->pos].co
);
vert->position[0] = global_pos[0];
vert->position[1] = global_pos[1];
vert->position[2] = global_pos[2];
}
static void VertexIt_Step(CSG_IteratorPtr it)
{
VertexIt * iterator = (VertexIt *)it;
iterator->pos ++;
}
static void VertexIt_Reset(CSG_IteratorPtr it)
{
VertexIt * iterator = (VertexIt *)it;
iterator->pos = 0;
}
static void VertexIt_Construct(CSG_VertexIteratorDescriptor *output, Object *ob)
{
VertexIt *it;
if (output == 0) return;
// allocate some memory for blender iterator
it = (VertexIt *)(MEM_mallocN(sizeof(VertexIt),"Boolean_VIt"));
if (it == 0) {
return;
}
// assign blender specific variables
it->ob = ob;
it->mesh = ob->data;
it->pos = 0;
// assign iterator function pointers.
output->Step = VertexIt_Step;
output->Fill = VertexIt_Fill;
output->Done = VertexIt_Done;
output->Reset = VertexIt_Reset;
output->num_elements = it->mesh->totvert;
output->it = it;
}
/**
* Blender Face iterator
*/
typedef struct {
Mesh *mesh;
int pos;
int offset;
} FaceIt;
static void FaceIt_Destruct(CSG_FaceIteratorDescriptor * iterator)
{
MEM_freeN(iterator->it);
iterator->Done = NULL;
iterator->Fill = NULL;
iterator->Reset = NULL;
iterator->Step = NULL;
iterator->num_elements = 0;
}
static int FaceIt_Done(CSG_IteratorPtr it)
{
// assume CSG_IteratorPtr is of the correct type.
FaceIt * iterator = (FaceIt *)it;
return(iterator->pos >= iterator->mesh->totface);
}
static void FaceIt_Fill(CSG_IteratorPtr it, CSG_IFace *face)
{
// assume CSG_IteratorPtr is of the correct type.
FaceIt *face_it = (FaceIt *)it;
MFace *mfaces = face_it->mesh->mface;
MFace *mface = &mfaces[face_it->pos];
face->vertex_index[0] = mface->v1;
face->vertex_index[1] = mface->v2;
face->vertex_index[2] = mface->v3;
if (mface->v4) {
face->vertex_index[3] = mface->v4;
face->vertex_number = 4;
} else {
face->vertex_number = 3;
}
face->orig_face = face_it->offset + face_it->pos;
}
static void FaceIt_Step(CSG_IteratorPtr it)
{
FaceIt * face_it = (FaceIt *)it;
face_it->pos ++;
}
static void FaceIt_Reset(CSG_IteratorPtr it)
{
FaceIt * face_it = (FaceIt *)it;
face_it->pos = 0;
}
static void FaceIt_Construct(
CSG_FaceIteratorDescriptor *output, Object *ob, int offset)
{
FaceIt *it;
if (output == 0) return;
// allocate some memory for blender iterator
it = (FaceIt *)(MEM_mallocN(sizeof(FaceIt),"Boolean_FIt"));
if (it == 0) {
return ;
}
// assign blender specific variables
it->mesh = ob->data;
it->offset = offset;
it->pos = 0;
// assign iterator function pointers.
output->Step = FaceIt_Step;
output->Fill = FaceIt_Fill;
output->Done = FaceIt_Done;
output->Reset = FaceIt_Reset;
output->num_elements = it->mesh->totface;
output->it = it;
}
static Object *AddNewBlenderMesh(Scene *scene, Base *base)
{
// This little function adds a new mesh object to the blender object list
// It uses ob to duplicate data as this seems to be easier than creating
// a new one. This new oject contains no faces nor vertices.
Mesh *old_me;
Base *basen;
Object *ob_new;
// now create a new blender object.
// duplicating all the settings from the previous object
// to the new one.
ob_new= copy_object(base->object);
// Ok we don't want to use the actual data from the
// last object, the above function incremented the
// number of users, so decrement it here.
old_me= ob_new->data;
old_me->id.us--;
// Now create a new base to add into the linked list of
// vase objects.
basen= MEM_mallocN(sizeof(Base), "duplibase");
*basen= *base;
BLI_addhead(&scene->base, basen); /* addhead: anders oneindige lus */
basen->object= ob_new;
basen->flag &= ~SELECT;
// Initialize the mesh data associated with this object.
ob_new->data= add_mesh("Mesh");
G.totmesh++;
// Finally assign the object type.
ob_new->type= OB_MESH;
return ob_new;
}
static void InterpCSGFace(
DerivedMesh *dm, Mesh *orig_me, int index, int orig_index, int nr,
float mapmat[][4])
{
float obco[3], *co[4], *orig_co[4], w[4][4];
MFace *mface, *orig_mface;
int j;
mface = CDDM_get_face(dm, index);
orig_mface = orig_me->mface + orig_index;
// get the vertex coordinates from the original mesh
orig_co[0] = (orig_me->mvert + orig_mface->v1)->co;
orig_co[1] = (orig_me->mvert + orig_mface->v2)->co;
orig_co[2] = (orig_me->mvert + orig_mface->v3)->co;
orig_co[3] = (orig_mface->v4)? (orig_me->mvert + orig_mface->v4)->co: NULL;
// get the vertex coordinates from the new derivedmesh
co[0] = CDDM_get_vert(dm, mface->v1)->co;
co[1] = CDDM_get_vert(dm, mface->v2)->co;
co[2] = CDDM_get_vert(dm, mface->v3)->co;
co[3] = (nr == 4)? CDDM_get_vert(dm, mface->v4)->co: NULL;
for (j = 0; j < nr; j++) {
// get coordinate into the space of the original mesh
if (mapmat)
VecMat4MulVecfl(obco, mapmat, co[j]);
else
VecCopyf(obco, co[j]);
InterpWeightsQ3Dfl(orig_co[0], orig_co[1], orig_co[2], orig_co[3], obco, w[j]);
}
CustomData_interp(&orig_me->fdata, &dm->faceData, &orig_index, NULL, (float*)w, 1, index);
}
/* Iterate over the CSG Output Descriptors and create a new DerivedMesh
from them */
static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
CSG_FaceIteratorDescriptor *face_it,
CSG_VertexIteratorDescriptor *vertex_it,
float parinv[][4],
float mapmat[][4],
Material **mat,
int *totmat,
Object *ob1,
Object *ob2)
{
DerivedMesh *dm;
GHash *material_hash = NULL;
Mesh *me1= (Mesh*)ob1->data;
Mesh *me2= (Mesh*)ob2->data;
int i;
// create a new DerivedMesh
dm = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements);
CustomData_merge(&me1->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
CD_DEFAULT, face_it->num_elements);
CustomData_merge(&me2->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
CD_DEFAULT, face_it->num_elements);
// step through the vertex iterators:
for (i = 0; !vertex_it->Done(vertex_it->it); i++) {
CSG_IVertex csgvert;
MVert *mvert = CDDM_get_vert(dm, i);
// retrieve a csg vertex from the boolean module
vertex_it->Fill(vertex_it->it, &csgvert);
vertex_it->Step(vertex_it->it);
// we have to map the vertex coordinates back in the coordinate frame
// of the resulting object, since it was computed in world space
VecMat4MulVecfl(mvert->co, parinv, csgvert.position);
}
// a hash table to remap materials to indices
if (mat) {
material_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
*totmat = 0;
}
// step through the face iterators
for(i = 0; !face_it->Done(face_it->it); i++) {
Mesh *orig_me;
Object *orig_ob;
Material *orig_mat;
CSG_IFace csgface;
MFace *mface;
int orig_index, mat_nr;
// retrieve a csg face from the boolean module
face_it->Fill(face_it->it, &csgface);
face_it->Step(face_it->it);
// find the original mesh and data
orig_ob = (csgface.orig_face < me1->totface)? ob1: ob2;
orig_me = (orig_ob == ob1)? me1: me2;
orig_index = (orig_ob == ob1)? csgface.orig_face: csgface.orig_face - me1->totface;
// copy all face layers, including mface
CustomData_copy_data(&orig_me->fdata, &dm->faceData, orig_index, i, 1);
// set mface
mface = CDDM_get_face(dm, i);
mface->v1 = csgface.vertex_index[0];
mface->v2 = csgface.vertex_index[1];
mface->v3 = csgface.vertex_index[2];
mface->v4 = (csgface.vertex_number == 4)? csgface.vertex_index[3]: 0;
// set material, based on lookup in hash table
orig_mat= give_current_material(orig_ob, mface->mat_nr+1);
if (mat && orig_mat) {
if (!BLI_ghash_haskey(material_hash, orig_mat)) {
mat[*totmat] = orig_mat;
mat_nr = mface->mat_nr = (*totmat)++;
BLI_ghash_insert(material_hash, orig_mat, SET_INT_IN_POINTER(mat_nr));
}
else
mface->mat_nr = GET_INT_FROM_POINTER(BLI_ghash_lookup(material_hash, orig_mat));
}
else
mface->mat_nr = 0;
InterpCSGFace(dm, orig_me, i, orig_index, csgface.vertex_number,
(orig_me == me2)? mapmat: NULL);
test_index_face(mface, &dm->faceData, i, csgface.vertex_number);
}
if (material_hash)
BLI_ghash_free(material_hash, NULL, NULL);
CDDM_calc_edges(dm);
CDDM_calc_normals(dm);
return dm;
}
static void BuildMeshDescriptors(
struct Object *ob,
int face_offset,
struct CSG_FaceIteratorDescriptor * face_it,
struct CSG_VertexIteratorDescriptor * vertex_it)
{
VertexIt_Construct(vertex_it,ob);
FaceIt_Construct(face_it,ob,face_offset);
}
static void FreeMeshDescriptors(
struct CSG_FaceIteratorDescriptor *face_it,
struct CSG_VertexIteratorDescriptor *vertex_it)
{
VertexIt_Destruct(vertex_it);
FaceIt_Destruct(face_it);
}
DerivedMesh *NewBooleanDerivedMesh_intern(
struct Object *ob, struct Object *ob_select,
int int_op_type, Material **mat, int *totmat)
{
float inv_mat[4][4];
float map_mat[4][4];
DerivedMesh *dm = NULL;
Mesh *me1 = get_mesh(ob_select);
Mesh *me2 = get_mesh(ob);
if (me1 == NULL || me2 == NULL) return 0;
if (!me1->totface || !me2->totface) return 0;
// we map the final object back into ob's local coordinate space. For this
// we need to compute the inverse transform from global to ob (inv_mat),
// and the transform from ob to ob_select for use in interpolation (map_mat)
Mat4Invert(inv_mat, ob->obmat);
Mat4MulMat4(map_mat, ob_select->obmat, inv_mat);
Mat4Invert(inv_mat, ob_select->obmat);
{
// interface with the boolean module:
//
// the idea is, we pass the boolean module verts and faces using the
// provided descriptors. once the boolean operation is performed, we
// get back output descriptors, from which we then build a DerivedMesh
CSG_VertexIteratorDescriptor vd_1, vd_2;
CSG_FaceIteratorDescriptor fd_1, fd_2;
CSG_OperationType op_type;
CSG_BooleanOperation *bool_op;
// work out the operation they chose and pick the appropriate
// enum from the csg module.
switch (int_op_type) {
case 1 : op_type = e_csg_intersection; break;
case 2 : op_type = e_csg_union; break;
case 3 : op_type = e_csg_difference; break;
case 4 : op_type = e_csg_classify; break;
default : op_type = e_csg_intersection;
}
BuildMeshDescriptors(ob_select, 0, &fd_1, &vd_1);
BuildMeshDescriptors(ob, me1->totface, &fd_2, &vd_2);
bool_op = CSG_NewBooleanFunction();
// perform the operation
if (CSG_PerformBooleanOperation(bool_op, op_type, fd_1, vd_1, fd_2, vd_2)) {
CSG_VertexIteratorDescriptor vd_o;
CSG_FaceIteratorDescriptor fd_o;
CSG_OutputFaceDescriptor(bool_op, &fd_o);
CSG_OutputVertexDescriptor(bool_op, &vd_o);
// iterate through results of operation and insert
// into new object
dm = ConvertCSGDescriptorsToDerivedMesh(
&fd_o, &vd_o, inv_mat, map_mat, mat, totmat, ob_select, ob);
// free up the memory
CSG_FreeVertexDescriptor(&vd_o);
CSG_FreeFaceDescriptor(&fd_o);
}
// else
// XXX error("Unknown internal error in boolean");
CSG_FreeBooleanOperation(bool_op);
FreeMeshDescriptors(&fd_1, &vd_1);
FreeMeshDescriptors(&fd_2, &vd_2);
}
return dm;
}
int NewBooleanMesh(Scene *scene, Base *base, Base *base_select, int int_op_type)
{
Mesh *me_new;
int a, maxmat, totmat= 0;
Object *ob_new, *ob, *ob_select;
Material **mat;
DerivedMesh *dm;
ob= base->object;
ob_select= base_select->object;
maxmat= ob->totcol + ob_select->totcol;
mat= (Material**)MEM_mallocN(sizeof(Material*)*maxmat, "NewBooleanMeshMat");
/* put some checks in for nice user feedback */
if((!(get_mesh(ob)->totface)) || (!(get_mesh(ob_select)->totface)))
{
MEM_freeN(mat);
return -1;
}
dm= NewBooleanDerivedMesh_intern(ob, ob_select, int_op_type, mat, &totmat);
if (dm == NULL) {
MEM_freeN(mat);
return 0;
}
/* create a new blender mesh object - using 'base' as a template */
ob_new= AddNewBlenderMesh(scene, base_select);
me_new= ob_new->data;
DM_to_mesh(dm, me_new);
dm->release(dm);
/* add materials to object */
for (a = 0; a < totmat; a++)
assign_material(ob_new, mat[a], a+1);
MEM_freeN(mat);
/* update dag */
DAG_object_flush_update(scene, ob_new, OB_RECALC_DATA);
return 1;
}
DerivedMesh *NewBooleanDerivedMesh(struct Object *ob, struct Object *ob_select,
int int_op_type)
{
return NewBooleanDerivedMesh_intern(ob, ob_select, int_op_type, NULL, NULL);
}

View File

@@ -0,0 +1,293 @@
#if 0
/**
* $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) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "CSG_BooleanOps.h"
#include "BKE_booleanops.h"
#include "BKE_booleanops_mesh.h"
#include "MEM_guardedalloc.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_displist.h"
#include "BKE_object.h"
#include "BKE_utildefines.h"
#include "BKE_library.h"
#include "BKE_material.h"
#include "BLI_arithb.h"
/**
* Implementation of boolean ops mesh interface.
*/
void
CSG_DestroyMeshDescriptor(
CSG_MeshDescriptor *mesh
){
// Call mesh descriptors destroy function....
mesh->m_destroy_func(mesh);
}
// Destroy function for blender mesh internals.
static
void
CSG_DestroyBlenderMeshInternals(
CSG_MeshDescriptor *mesh
) {
// Free face and vertex iterators.
FreeMeshDescriptors(&(mesh->m_face_iterator),&(mesh->m_vertex_iterator));
}
static
void
CSG_DestroyCSGMeshInternals(
CSG_MeshDescriptor *mesh
){
CSG_FreeVertexDescriptor(&(mesh->m_vertex_iterator));
CSG_FreeFaceDescriptor(&(mesh->m_face_iterator));
}
static
int
MakeCSGMeshFromBlenderBase(
Base * base,
CSG_MeshDescriptor * output
) {
Mesh *me;
if (output == NULL || base == NULL) return 0;
me = get_mesh(base->object);
output->m_descriptor.user_face_vertex_data_size = 0;
output->m_descriptor.user_data_size = sizeof(FaceData);
output->base = base;
BuildMeshDescriptors(
base->object,
&(output->m_face_iterator),
&(output->m_vertex_iterator)
);
output->m_destroy_func = CSG_DestroyBlenderMeshInternals;
return 1;
}
int
CSG_LoadBlenderMesh(
Object * obj,
CSG_MeshDescriptor *output
){
Mesh *me;
if (output == NULL || obj == NULL) return 0;
me = get_mesh(obj);
output->m_descriptor.user_face_vertex_data_size = 0;
output->m_descriptor.user_data_size = sizeof(FaceData);
output->base = NULL;
BuildMeshDescriptors(
obj,
&(output->m_face_iterator),
&(output->m_vertex_iterator)
);
output->m_destroy_func = CSG_DestroyBlenderMeshInternals;
output->base = NULL;
return 1;
}
int
CSG_AddMeshToBlender(
CSG_MeshDescriptor *mesh
){
Mesh *me_new = NULL;
Object *ob_new = NULL;
float inv_mat[4][4];
if (mesh == NULL) return 0;
if (mesh->base == NULL) return 0;
Mat4Invert(inv_mat,mesh->base->object->obmat);
// Create a new blender mesh object - using 'base' as
// a template for the new object.
ob_new= AddNewBlenderMesh(mesh->base);
me_new = ob_new->data;
// make sure the iterators are reset.
mesh->m_face_iterator.Reset(mesh->m_face_iterator.it);
mesh->m_vertex_iterator.Reset(mesh->m_vertex_iterator.it);
// iterate through results of operation and insert into new object
// see subsurf.c
ConvertCSGDescriptorsToMeshObject(
ob_new,
&(mesh->m_descriptor),
&(mesh->m_face_iterator),
&(mesh->m_vertex_iterator),
inv_mat
);
return 1;
}
int
CSG_PerformOp(
CSG_MeshDescriptor *mesh1,
CSG_MeshDescriptor *mesh2,
int int_op_type,
CSG_MeshDescriptor *output
){
CSG_OperationType op_type;
CSG_BooleanOperation * bool_op = CSG_NewBooleanFunction();
int success = 0;
if (bool_op == NULL) return 0;
if ((mesh1 == NULL) || (mesh2 == NULL) || (output == NULL)) {
return 0;
}
if ((int_op_type < 1) || (int_op_type > 3)) return 0;
switch (int_op_type) {
case 1 : op_type = e_csg_intersection; break;
case 2 : op_type = e_csg_union; break;
case 3 : op_type = e_csg_difference; break;
case 4 : op_type = e_csg_classify; break;
default : op_type = e_csg_intersection;
}
output->m_descriptor = CSG_DescibeOperands(bool_op,mesh1->m_descriptor,mesh2->m_descriptor);
output->base = mesh1->base;
if (output->m_descriptor.user_face_vertex_data_size) {
// Then use the only interp function supported
success =
CSG_PerformBooleanOperation(
bool_op,
op_type,
mesh1->m_face_iterator,
mesh1->m_vertex_iterator,
mesh2->m_face_iterator,
mesh2->m_vertex_iterator,
InterpFaceVertexData
);
} else {
success =
CSG_PerformBooleanOperation(
bool_op,
op_type,
mesh1->m_face_iterator,
mesh1->m_vertex_iterator,
mesh2->m_face_iterator,
mesh2->m_vertex_iterator,
InterpNoUserData
);
}
if (!success) {
CSG_FreeBooleanOperation(bool_op);
bool_op = NULL;
return 0;
}
// get the ouput mesh descriptors.
CSG_OutputFaceDescriptor(bool_op,&(output->m_face_iterator));
CSG_OutputVertexDescriptor(bool_op,&(output->m_vertex_iterator));
output->m_destroy_func = CSG_DestroyCSGMeshInternals;
return 1;
}
int
NewBooleanMeshTest(
struct Base * base,
struct Base * base_select,
int op_type
){
CSG_MeshDescriptor m1,m2,output;
CSG_MeshDescriptor output2,output3;
if (!MakeCSGMeshFromBlenderBase(base,&m1)) {
return 0;
}
if (!MakeCSGMeshFromBlenderBase(base_select,&m2)) {
return 0;
}
CSG_PerformOp(&m1,&m2,1,&output);
CSG_PerformOp(&m1,&m2,2,&output2);
CSG_PerformOp(&m1,&m2,3,&output3);
if (!CSG_AddMeshToBlender(&output)) {
return 0;
}
if (!CSG_AddMeshToBlender(&output2)) {
return 0;
}
if (!CSG_AddMeshToBlender(&output3)) {
return 0;
}
CSG_DestroyMeshDescriptor(&m1);
CSG_DestroyMeshDescriptor(&m2);
CSG_DestroyMeshDescriptor(&output);
CSG_DestroyMeshDescriptor(&output2);
CSG_DestroyMeshDescriptor(&output3);
return 1;
}
#endif

View File

@@ -0,0 +1,540 @@
/**
* $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) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "stdio.h"
#include "ctype.h"
#include "string.h"
#include "BKE_global.h"
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "WM_types.h"
char *key_event_to_string(unsigned short event)
{
switch(event) {
case AKEY:
return "A";
break;
case BKEY:
return "B";
break;
case CKEY:
return "C";
break;
case DKEY:
return "D";
break;
case EKEY:
return "E";
break;
case FKEY:
return "F";
break;
case GKEY:
return "G";
break;
case HKEY:
return "H";
break;
case IKEY:
return "I";
break;
case JKEY:
return "J";
break;
case KKEY:
return "K";
break;
case LKEY:
return "L";
break;
case MKEY:
return "M";
break;
case NKEY:
return "N";
break;
case OKEY:
return "O";
break;
case PKEY:
return "P";
break;
case QKEY:
return "Q";
break;
case RKEY:
return "R";
break;
case SKEY:
return "S";
break;
case TKEY:
return "T";
break;
case UKEY:
return "U";
break;
case VKEY:
return "V";
break;
case WKEY:
return "W";
break;
case XKEY:
return "X";
break;
case YKEY:
return "Y";
break;
case ZKEY:
return "Z";
break;
case ZEROKEY:
return "Zero";
break;
case ONEKEY:
return "One";
break;
case TWOKEY:
return "Two";
break;
case THREEKEY:
return "Three";
break;
case FOURKEY:
return "Four";
break;
case FIVEKEY:
return "Five";
break;
case SIXKEY:
return "Six";
break;
case SEVENKEY:
return "Seven";
break;
case EIGHTKEY:
return "Eight";
break;
case NINEKEY:
return "Nine";
break;
case LEFTCTRLKEY:
return "Leftctrl";
break;
case LEFTALTKEY:
return "Leftalt";
break;
case RIGHTALTKEY:
return "Rightalt";
break;
case RIGHTCTRLKEY:
return "Rightctrl";
break;
case RIGHTSHIFTKEY:
return "Rightshift";
break;
case LEFTSHIFTKEY:
return "Leftshift";
break;
case ESCKEY:
return "Esc";
break;
case TABKEY:
return "Tab";
break;
case RETKEY:
return "Ret";
break;
case SPACEKEY:
return "Space";
break;
case LINEFEEDKEY:
return "Linefeed";
break;
case BACKSPACEKEY:
return "Backspace";
break;
case DELKEY:
return "Del";
break;
case SEMICOLONKEY:
return "Semicolon";
break;
case PERIODKEY:
return "Period";
break;
case COMMAKEY:
return "Comma";
break;
case QUOTEKEY:
return "Quote";
break;
case ACCENTGRAVEKEY:
return "Accentgrave";
break;
case MINUSKEY:
return "Minus";
break;
case SLASHKEY:
return "Slash";
break;
case BACKSLASHKEY:
return "Backslash";
break;
case EQUALKEY:
return "Equal";
break;
case LEFTBRACKETKEY:
return "Leftbracket";
break;
case RIGHTBRACKETKEY:
return "Rightbracket";
break;
case LEFTARROWKEY:
return "Leftarrow";
break;
case DOWNARROWKEY:
return "Downarrow";
break;
case RIGHTARROWKEY:
return "Rightarrow";
break;
case UPARROWKEY:
return "Uparrow";
break;
case PAD2:
return "Pad2";
break;
case PAD4:
return "Pad4";
break;
case PAD6:
return "Pad6";
break;
case PAD8:
return "Pad8";
break;
case PAD1:
return "Pad1";
break;
case PAD3:
return "Pad3";
break;
case PAD5:
return "Pad5";
break;
case PAD7:
return "Pad7";
break;
case PAD9:
return "Pad9";
break;
case PADPERIOD:
return "Padperiod";
break;
case PADSLASHKEY:
return "Padslash";
break;
case PADASTERKEY:
return "Padaster";
break;
case PAD0:
return "Pad0";
break;
case PADMINUS:
return "Padminus";
break;
case PADENTER:
return "Padenter";
break;
case PADPLUSKEY:
return "Padplus";
break;
case F1KEY:
return "F1";
break;
case F2KEY:
return "F2";
break;
case F3KEY:
return "F3";
break;
case F4KEY:
return "F4";
break;
case F5KEY:
return "F5";
break;
case F6KEY:
return "F6";
break;
case F7KEY:
return "F7";
break;
case F8KEY:
return "F8";
break;
case F9KEY:
return "F9";
break;
case F10KEY:
return "F10";
break;
case F11KEY:
return "F11";
break;
case F12KEY:
return "F12";
break;
case PAUSEKEY:
return "Pause";
break;
case INSERTKEY:
return "Insert";
break;
case HOMEKEY:
return "Home";
break;
case PAGEUPKEY:
return "Pageup";
break;
case PAGEDOWNKEY:
return "Pagedown";
break;
case ENDKEY:
return "End";
break;
}
return "";
}
/*
* Decodes key combination strings [qual1+[qual2+[...]]]keyname
* The '+'s may be replaced by '-' or ' ' characters to support different
* formats. No additional whitespace is allowed. The keyname may be an internal
* name, like "RETKEY", or a more common name, like "Return". Decoding is case-
* insensitive.
*
* Example strings: "Ctrl+L", "ALT-ESC", "Shift A"
*
* Returns 1 if successful.
*/
int decode_key_string(char *str, unsigned short *key, unsigned short *qual)
{
int i, prev, len, invalid=0;
len= strlen(str);
*key= *qual= 0;
/* Convert to upper case */
for (i=0; i<len; i++) {
str[i]= toupper(str[i]);
}
/* Handle modifiers */
for (prev=i=0; i<len; i++) {
if (str[i]==' ' || str[i]=='+' || str[i]=='-') {
// XXX if (!strncmp(str+prev, "CTRL", i-prev)) *qual |= LR_CTRLKEY;
// else if (!strncmp(str+prev, "ALT", i-prev)) *qual |= LR_ALTKEY;
// else if (!strncmp(str+prev, "SHIFT", i-prev)) *qual |= LR_SHIFTKEY;
// else if (!strncmp(str+prev, "COMMAND", i-prev)) *qual |= LR_COMMANDKEY;
prev=i+1;
}
}
/* Compare last part against key names */
if ((len-prev==1) || ((len-prev==4) && !strncmp(str+prev, "KEY", 3))) {
if (str[prev]>='A' && str[prev]<='Z') {
*key= str[prev]-'A'+AKEY;
} else if (str[prev]>='0' && str[prev]<='9') {
*key= str[prev]-'0'+ZEROKEY;
} else {
invalid= 1;
}
} else if (!strncmp(str+prev, "ZEROKEY", len-prev) || !strncmp(str+prev, "ZERO", len-prev)) {
*key= ZEROKEY;
} else if (!strncmp(str+prev, "ONEKEY", len-prev) || !strncmp(str+prev, "ONE", len-prev)) {
*key= ONEKEY;
} else if (!strncmp(str+prev, "TWOKEY", len-prev) || !strncmp(str+prev, "TWO", len-prev)) {
*key= TWOKEY;
} else if (!strncmp(str+prev, "THREEKEY", len-prev) || !strncmp(str+prev, "THREE", len-prev)) {
*key= THREEKEY;
} else if (!strncmp(str+prev, "FOURKEY", len-prev) || !strncmp(str+prev, "FOUR", len-prev)) {
*key= FOURKEY;
} else if (!strncmp(str+prev, "FIVEKEY", len-prev) || !strncmp(str+prev, "FIVE", len-prev)) {
*key= FIVEKEY;
} else if (!strncmp(str+prev, "SIZEKEY", len-prev) || !strncmp(str+prev, "SIX", len-prev)) {
*key= SIXKEY;
} else if (!strncmp(str+prev, "SEVENKEY", len-prev) || !strncmp(str+prev, "SEVEN", len-prev)) {
*key= SEVENKEY;
} else if (!strncmp(str+prev, "EIGHTKEY", len-prev) || !strncmp(str+prev, "EIGHT", len-prev)) {
*key= EIGHTKEY;
} else if (!strncmp(str+prev, "NINEKEY", len-prev) || !strncmp(str+prev, "NINE", len-prev)) {
*key= NINEKEY;
} else if (!strncmp(str+prev, "ESCKEY", len-prev) || !strncmp(str+prev, "ESC", len-prev)) {
*key= ESCKEY;
} else if (!strncmp(str+prev, "TABKEY", len-prev) || !strncmp(str+prev, "TAB", len-prev)) {
*key= TABKEY;
} else if (!strncmp(str+prev, "RETKEY", len-prev) || !strncmp(str+prev, "RETURN", len-prev) || !strncmp(str+prev, "ENTER", len-prev)) {
*key= RETKEY;
} else if (!strncmp(str+prev, "SPACEKEY", len-prev) || !strncmp(str+prev, "SPACE", len-prev)) {
*key= SPACEKEY;
} else if (!strncmp(str+prev, "LINEFEEDKEY", len-prev) || !strncmp(str+prev, "LINEFEED", len-prev)) {
*key= LINEFEEDKEY;
} else if (!strncmp(str+prev, "BACKSPACEKEY", len-prev) || !strncmp(str+prev, "BACKSPACE", len-prev)) {
*key= BACKSPACEKEY;
} else if (!strncmp(str+prev, "DELKEY", len-prev) || !strncmp(str+prev, "DELETE", len-prev)) {
*key= DELKEY;
} else if (!strncmp(str+prev, "SEMICOLONKEY", len-prev) || !strncmp(str+prev, "SEMICOLON", len-prev)) {
*key= SEMICOLONKEY;
} else if (!strncmp(str+prev, "PERIODKEY", len-prev) || !strncmp(str+prev, "PERIOD", len-prev)) {
*key= PERIODKEY;
} else if (!strncmp(str+prev, "COMMAKEY", len-prev) || !strncmp(str+prev, "COMMA", len-prev)) {
*key= COMMAKEY;
} else if (!strncmp(str+prev, "QUOTEKEY", len-prev) || !strncmp(str+prev, "QUOTE", len-prev)) {
*key= QUOTEKEY;
} else if (!strncmp(str+prev, "ACCENTGRAVEKEY", len-prev) || !strncmp(str+prev, "ACCENTGRAVE", len-prev)) {
*key= ACCENTGRAVEKEY;
} else if (!strncmp(str+prev, "MINUSKEY", len-prev) || !strncmp(str+prev, "MINUS", len-prev)) {
*key= MINUSKEY;
} else if (!strncmp(str+prev, "SLASHKEY", len-prev) || !strncmp(str+prev, "SLASH", len-prev)) {
*key= SLASHKEY;
} else if (!strncmp(str+prev, "BACKSLASHKEY", len-prev) || !strncmp(str+prev, "BACKSLASH", len-prev)) {
*key= BACKSLASHKEY;
} else if (!strncmp(str+prev, "EQUALKEY", len-prev) || !strncmp(str+prev, "EQUAL", len-prev)) {
*key= EQUALKEY;
} else if (!strncmp(str+prev, "LEFTBRACKETKEY", len-prev) || !strncmp(str+prev, "LEFTBRACKET", len-prev)) {
*key= LEFTBRACKETKEY;
} else if (!strncmp(str+prev, "RIGHTBRACKETKEY", len-prev) || !strncmp(str+prev, "RIGHTBRACKET", len-prev)) {
*key= RIGHTBRACKETKEY;
} else if (!strncmp(str+prev, "DELKEY", len-prev) || !strncmp(str+prev, "DELETE", len-prev)) {
*key= DELKEY;
} else if (!strncmp(str+prev, "LEFTARROWKEY", len-prev) || !strncmp(str+prev, "LEFTARROW", len-prev)) {
*key= LEFTARROWKEY;
} else if (!strncmp(str+prev, "DOWNARROWKEY", len-prev) || !strncmp(str+prev, "DOWNARROW", len-prev)) {
*key= DOWNARROWKEY;
} else if (!strncmp(str+prev, "RIGHTARROWKEY", len-prev) || !strncmp(str+prev, "RIGHTARROW", len-prev)) {
*key= RIGHTARROWKEY;
} else if (!strncmp(str+prev, "UPARROWKEY", len-prev) || !strncmp(str+prev, "UPARROW", len-prev)) {
*key= UPARROWKEY;
} else if (!strncmp(str+prev, "PAD", 3)) {
if (len-prev<=4) {
if (str[prev]>='0' && str[prev]<='9') {
*key= str[prev]-'0'+ZEROKEY;
} else {
invalid= 1;
}
} else if (!strncmp(str+prev+3, "PERIODKEY", len-prev-3) || !strncmp(str+prev+3, "PERIOD", len-prev-3)) {
*key= PADPERIOD;
} else if (!strncmp(str+prev+3, "SLASHKEY", len-prev-3) || !strncmp(str+prev+3, "SLASH", len-prev-3)) {
*key= PADSLASHKEY;
} else if (!strncmp(str+prev+3, "ASTERKEY", len-prev-3) || !strncmp(str+prev+3, "ASTERISK", len-prev-3)) {
*key= PADASTERKEY;
} else if (!strncmp(str+prev+3, "MINUSKEY", len-prev-3) || !strncmp(str+prev+3, "MINUS", len-prev-3)) {
*key= PADMINUS;
} else if (!strncmp(str+prev+3, "ENTERKEY", len-prev-3) || !strncmp(str+prev+3, "ENTER", len-prev-3)) {
*key= PADENTER;
} else if (!strncmp(str+prev+3, "PLUSKEY", len-prev-3) || !strncmp(str+prev+3, "PLUS", len-prev-3)) {
*key= PADPLUSKEY;
} else {
invalid= 1;
}
} else if (!strncmp(str+prev, "F1KEY", len-prev) || !strncmp(str+prev, "F1", len-prev)) {
*key= F1KEY;
} else if (!strncmp(str+prev, "F2KEY", len-prev) || !strncmp(str+prev, "F2", len-prev)) {
*key= F2KEY;
} else if (!strncmp(str+prev, "F3KEY", len-prev) || !strncmp(str+prev, "F3", len-prev)) {
*key= F3KEY;
} else if (!strncmp(str+prev, "F4KEY", len-prev) || !strncmp(str+prev, "F4", len-prev)) {
*key= F4KEY;
} else if (!strncmp(str+prev, "F5KEY", len-prev) || !strncmp(str+prev, "F5", len-prev)) {
*key= F5KEY;
} else if (!strncmp(str+prev, "F6KEY", len-prev) || !strncmp(str+prev, "F6", len-prev)) {
*key= F6KEY;
} else if (!strncmp(str+prev, "F7KEY", len-prev) || !strncmp(str+prev, "F7", len-prev)) {
*key= F7KEY;
} else if (!strncmp(str+prev, "F8KEY", len-prev) || !strncmp(str+prev, "F8", len-prev)) {
*key= F8KEY;
} else if (!strncmp(str+prev, "F9KEY", len-prev) || !strncmp(str+prev, "F9", len-prev)) {
*key= F9KEY;
} else if (!strncmp(str+prev, "F10KEY", len-prev) || !strncmp(str+prev, "F10", len-prev)) {
*key= F10KEY;
} else if (!strncmp(str+prev, "F11KEY", len-prev) || !strncmp(str+prev, "F11", len-prev)) {
*key= F11KEY;
} else if (!strncmp(str+prev, "F12KEY", len-prev) || !strncmp(str+prev, "F12", len-prev)) {
*key= F12KEY;
} else if (!strncmp(str+prev, "PAUSEKEY", len-prev) || !strncmp(str+prev, "PAUSE", len-prev)) {
*key= PAUSEKEY;
} else if (!strncmp(str+prev, "INSERTKEY", len-prev) || !strncmp(str+prev, "INSERT", len-prev)) {
*key= INSERTKEY;
} else if (!strncmp(str+prev, "HOMEKEY", len-prev) || !strncmp(str+prev, "HOME", len-prev)) {
*key= HOMEKEY;
} else if (!strncmp(str+prev, "PAGEUPKEY", len-prev) || !strncmp(str+prev, "PAGEUP", len-prev)) {
*key= PAGEUPKEY;
} else if (!strncmp(str+prev, "PAGEDOWNKEY", len-prev) || !strncmp(str+prev, "PAGEDOWN", len-prev)) {
*key= PAGEDOWNKEY;
} else if (!strncmp(str+prev, "ENDKEY", len-prev) || !strncmp(str+prev, "END", len-prev)) {
*key= ENDKEY;
} else {
invalid= 1;
}
if (!invalid && *key) {
return 1;
}
return 0;
}

View File

@@ -0,0 +1,131 @@
/**
* $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) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
* Making screendumps.
*/
#include <string.h>
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_utildefines.h"
#include "BIF_gl.h"
#include "WM_types.h"
#include "WM_api.h"
static unsigned int *dumprect= NULL;
static int dumpsx, dumpsy;
/* XXX */
static int saveover() {return 0;}
/* Callback */
void write_screendump(bContext *C, char *name)
{
Scene *scene= CTX_data_scene(C);
ImBuf *ibuf;
if(dumprect) {
strcpy(G.ima, name);
BLI_convertstringcode(name, G.sce);
BLI_convertstringframe(name, scene->r.cfra); /* TODO - is this ever used? */
/* BKE_add_image_extension() checks for if extension was already set */
if(scene->r.scemode & R_EXTENSION)
if(strlen(name)<FILE_MAXDIR+FILE_MAXFILE-5)
BKE_add_image_extension(scene, name, scene->r.imtype);
if(saveover(name)) {
// waitcursor(1);
ibuf= IMB_allocImBuf(dumpsx, dumpsy, 24, 0, 0);
ibuf->rect= dumprect;
if(scene->r.planes == 8) IMB_cspace(ibuf, rgb_to_bw);
BKE_write_ibuf(scene, ibuf, name, scene->r.imtype, scene->r.subimtype, scene->r.quality);
IMB_freeImBuf(ibuf);
// waitcursor(0);
}
MEM_freeN(dumprect);
dumprect= NULL;
}
}
/* get dump from frontbuffer */
void ED_screendump(bContext *C, int fscreen)
{
wmWindow *win= CTX_wm_window(C);
ScrArea *curarea= CTX_wm_area(C);
int x=0, y=0;
// char imstr[64];
if(dumprect) MEM_freeN(dumprect);
dumprect= NULL;
if(fscreen) { /* full screen */
x= 0;
y= 0;
dumpsx= win->sizex;
dumpsy= win->sizey;
}
else {
x= curarea->totrct.xmin;
y= curarea->totrct.ymin;
dumpsx= curarea->totrct.xmax-x;
dumpsy= curarea->totrct.ymax-y;
}
if (dumpsx && dumpsy) {
dumprect= MEM_mallocN(sizeof(int)*dumpsx*dumpsy, "dumprect");
glReadBuffer(GL_FRONT);
glReadPixels(x, y, dumpsx, dumpsy, GL_RGBA, GL_UNSIGNED_BYTE, dumprect);
glFinish();
glReadBuffer(GL_BACK);
// save_image_filesel_str(imstr);
// activate_fileselect(FILE_SPECIAL, imstr, G.ima, write_screendump);
}
}