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:
authorBen Batt <benbatt@gmail.com>2006-08-28 05:12:36 +0400
committerBen Batt <benbatt@gmail.com>2006-08-28 05:12:36 +0400
commit433f6c7043c06d8d0330fa69f63d475549b48e91 (patch)
treed147f943e4cfcc2f0df50818e18f983772a52c22 /source/blender/src/booleanops.c
parent5dbc4c5f8fda61da055a2186a5080feec96828c0 (diff)
Integration of the Google Summer of Code Modifier Stack Upgrade project. The
main features are: * Modifiers can now be in any order in the modifier stack * DerivedMesh now has a standard framework for custom element data to be passed through the stack with mesh data (being copied and interpolated as appropriate), so modifiers can access whatever data they need * The modifier stack code has been refactored and a number of bugs have been removed * The EdgeSplit modifier has been added: http://mediawiki.blender.org/index.php/BlenderDev/EdgeSplitModifier * The DerivedMesh modifier has been added: http://mediawiki.blender.org/index.php/BlenderDev/DisplaceModifier * The UVProject modifier has been added: http://mediawiki.blender.org/index.php/BlenderDev/UVProjectModifier For more info, see: http://mediawiki.blender.org/index.php/User:Artificer/ModifierStackUpgrade (currently undergoing reorganisation)
Diffstat (limited to 'source/blender/src/booleanops.c')
-rw-r--r--source/blender/src/booleanops.c346
1 files changed, 346 insertions, 0 deletions
diff --git a/source/blender/src/booleanops.c b/source/blender/src/booleanops.c
index b38600d182b..8a2d6d4d7f9 100644
--- a/source/blender/src/booleanops.c
+++ b/source/blender/src/booleanops.c
@@ -46,8 +46,10 @@
#include "CSG_BooleanOps.h"
#include "BKE_booleanops.h"
+#include "BKE_cdderivedmesh.h"
#include "BKE_depsgraph.h"
#include "BKE_displist.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_material.h"
@@ -74,6 +76,12 @@ static void ConvertCSGDescriptorsToDLM(
CSG_VertexIteratorDescriptor *vertex_it,
float parinv[][4]);
+static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
+ Object *ob, CSG_MeshPropertyDescriptor *props,
+ CSG_FaceIteratorDescriptor *face_it,
+ CSG_VertexIteratorDescriptor *vertex_it,
+ float parinv[][4]);
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -571,6 +579,196 @@ DispListMesh *NewBooleanMeshDLM(Object *ob, Object *ob_select, int int_op_type)
return dlm;
}
+DerivedMesh *NewBooleanDerivedMesh(struct Object *ob, struct Object *ob_select,
+ int int_op_type)
+{
+ Mesh *me2 = get_mesh(ob_select);
+ Mesh *me = get_mesh(ob);
+ int free_tface1, free_tface2;
+ DerivedMesh *result;
+
+ float inv_mat[4][4];
+ int success = 0;
+ // build and fill new descriptors for these meshes
+ CSG_VertexIteratorDescriptor vd_1;
+ CSG_VertexIteratorDescriptor vd_2;
+ CSG_FaceIteratorDescriptor fd_1;
+ CSG_FaceIteratorDescriptor fd_2;
+
+ CSG_MeshPropertyDescriptor mpd1, mpd2;
+
+ // work out the operation they chose and pick the appropriate
+ // enum from the csg module.
+
+ CSG_OperationType op_type;
+
+ if(me == NULL || me2 == NULL) return 0;
+
+ if(!me->totface || !me2->totface) return 0;
+
+ success = 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;
+ }
+
+ // Here is the section where we describe the properties of
+ // both meshes to the bsp module.
+
+ if(me->mcol != NULL) {
+ // Then this mesh has vertex colors only
+ // well this is awkward because there is no equivalent
+ // test_index_mface just for vertex colors!
+ // as a temporary hack we can convert these vertex colors
+ // into tfaces do the operation and turn them back again.
+
+ // create some memory for the tfaces.
+ me->tface = (TFace *)MEM_callocN(sizeof(TFace) * me->totface,
+ "BooleanOps_TempTFace");
+ mcol_to_tface(me, 1);
+ free_tface1 = 1;
+ } else {
+ free_tface1 = 0;
+ }
+
+ mpd1.user_face_vertex_data_size = 0;
+ mpd1.user_data_size = sizeof(FaceData);
+
+ if(me->tface) {
+ mpd1.user_face_vertex_data_size = sizeof(FaceVertexData);
+ }
+
+ // same for mesh2
+
+ if(me2->mcol != NULL) {
+ // create some memory for the tfaces.
+ me2->tface = (TFace *)MEM_callocN(sizeof(TFace) * me2->totface,
+ "BooleanOps_TempTFace");
+ mcol_to_tface(me2, 1);
+ free_tface2 = 1;
+ } else {
+ free_tface2 = 0;
+ }
+
+ mpd2.user_face_vertex_data_size = 0;
+ mpd2.user_data_size = sizeof(FaceData);
+
+ if(me2->tface) {
+ mpd2.user_face_vertex_data_size = sizeof(FaceVertexData);
+ }
+
+ // we map the final object back into object 1's (ob)
+ // local coordinate space. For this we need to compute
+ // the inverse transform from global to local.
+
+ Mat4Invert(inv_mat, ob_select->obmat);
+
+ // make a boolean operation;
+ {
+ CSG_BooleanOperation *bool_op = CSG_NewBooleanFunction();
+ CSG_MeshPropertyDescriptor output_mpd = CSG_DescibeOperands(bool_op,
+ mpd1, mpd2);
+ // analyse the result and choose mesh descriptors accordingly
+ int output_type;
+ if(output_mpd. user_face_vertex_data_size) {
+ output_type = 1;
+ } else {
+ output_type = 0;
+ }
+
+ BuildMeshDescriptors(ob, &fd_1, &vd_1);
+ BuildMeshDescriptors(ob_select, &fd_2, &vd_2);
+
+ // perform the operation
+
+ if(output_type == 0) {
+ success = CSG_PerformBooleanOperation(bool_op, op_type,
+ fd_1, vd_1, fd_2, vd_2,
+ InterpNoUserData);
+ } else {
+ success = CSG_PerformBooleanOperation(bool_op, op_type,
+ fd_1, vd_1, fd_2, vd_2,
+ InterpFaceVertexData);
+ }
+
+ switch(success) {
+ case 1:
+ {
+ // descriptions of the output;
+ 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
+
+ result = ConvertCSGDescriptorsToDerivedMesh(
+ NULL, &output_mpd,
+ &fd_o, &vd_o, inv_mat);
+
+ // free up the memory
+
+ CSG_FreeVertexDescriptor(&vd_o);
+ CSG_FreeFaceDescriptor(&fd_o);
+ }
+ break;
+ case -1:
+ error("Selected meshes must have faces to perform "
+ "boolean operations");
+ break;
+ case -2:
+ error("Both meshes must be closed");
+ break;
+ default:
+ error("unknown internal error");
+ break;
+ }
+
+ CSG_FreeBooleanOperation(bool_op);
+ }
+
+ // We may need to map back the tfaces to mcols here.
+ if(free_tface1) {
+ tface_to_mcol(me);
+ MEM_freeN(me->tface);
+ me->tface = NULL;
+ }
+ if(free_tface2) {
+ tface_to_mcol(me2);
+ MEM_freeN(me2->tface);
+ me2->tface = NULL;
+ }
+
+ if(free_tface1 && free_tface2) {
+ // then we need to map the output tfaces into mcols
+ if(result && DM_get_vert_data(result, 0, LAYERTYPE_TFACE)) {
+ int i;
+ int maxFaces = result->getNumFaces(result);
+
+ if(!DM_get_vert_data(result, 0, LAYERTYPE_MCOL))
+ DM_add_vert_layer(result, LAYERTYPE_MCOL, 0, NULL);
+
+ for(i = 0; i < maxFaces; ++i) {
+ MCol *mcol = DM_get_vert_data(result, i, LAYERTYPE_MCOL);
+ TFace *tface = DM_get_vert_data(result, i, LAYERTYPE_TFACE);
+
+ memcpy(mcol, tface->col, sizeof(*mcol) * 4);
+ }
+ }
+ }
+
+ FreeMeshDescriptors(&fd_1, &vd_1);
+ FreeMeshDescriptors(&fd_2, &vd_2);
+
+ return result;
+}
+
int
NewBooleanMesh(
struct Base * base,
@@ -999,6 +1197,154 @@ ConvertCSGDescriptorsToDLM(
}
MEM_freeN(face.user_face_data);
}
+
+static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
+ Object *ob, CSG_MeshPropertyDescriptor *props,
+ CSG_FaceIteratorDescriptor *face_it,
+ CSG_VertexIteratorDescriptor *vertex_it,
+ float parinv[][4])
+{
+ FaceVertexData *user_face_vertex_data;
+ GHash *material_hash;
+ CSG_IVertex vert;
+ CSG_IFace face;
+ DerivedMesh *result;
+ int i;
+#if 0
+ MFace *mfaces;
+ TFace *tfaces;
+#endif
+ int fi_insert_pos, nmaterials;
+
+ // create some memory for the Iface according to output mesh props.
+
+ // initialize the face structure for readback
+
+ face.user_face_data = MEM_callocN(sizeof(FaceData),"BooleanOp_IFaceData");
+
+ if(props->user_face_vertex_data_size) {
+ user_face_vertex_data = MEM_callocN(sizeof(FaceVertexData) * 4,
+ "BooleanOp_IFaceData");
+ face.user_face_vertex_data[0] = &user_face_vertex_data[0];
+ face.user_face_vertex_data[1] = &user_face_vertex_data[1];
+ face.user_face_vertex_data[2] = &user_face_vertex_data[2];
+ face.user_face_vertex_data[3] = &user_face_vertex_data[3];
+ } else {
+ user_face_vertex_data = NULL;
+ }
+
+ // create memory for the vertex array.
+
+ result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements);
+
+ if(user_face_vertex_data)
+ DM_add_face_layer(result, LAYERTYPE_TFACE, 0, NULL);
+
+ // step through the iterators.
+
+ i = 0;
+ while(!vertex_it->Done(vertex_it->it)) {
+ MVert *insert_pos = CDDM_get_vert(result, i);
+ vertex_it->Fill(vertex_it->it, &vert);
+
+ // map output vertex into insert_pos
+ // and transform at by parinv at the same time.
+
+ VecMat4MulVecfl(insert_pos->co, parinv, vert.position);
+
+ vertex_it->Step(vertex_it->it);
+ i++;
+ }
+
+ // a hash table to remap materials to indices with
+ material_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ nmaterials = 0;
+
+ fi_insert_pos = 0;
+ while(!face_it->Done(face_it->it)) {
+ MFace *mface = CDDM_get_face(result, fi_insert_pos);
+ FaceData *fdata;
+
+ face_it->Fill(face_it->it, &face);
+ fdata = face.user_face_data;
+
+ // cheat CSG never dumps out quads.
+
+ if(face.vertex_number>3) {
+ // QUAD
+ mface->v1 = face.vertex_index[0];
+ mface->v2 = face.vertex_index[1];
+ mface->v3 = face.vertex_index[2];
+ mface->v4 = face.vertex_index[3];
+ } else {
+ // TRIANGLE
+ mface->v1 = face.vertex_index[0];
+ mface->v2 = face.vertex_index[1];
+ mface->v3 = face.vertex_index[2];
+ mface->v4 = 0;
+ }
+
+ mface->mat_nr = 0;
+ mface->flag = fdata->faceflag;
+
+ /* HACK, perform material to index mapping using a general
+ * hash table, just tuck the int into a void *.
+ */
+
+ if(ob && !BLI_ghash_haskey(material_hash, fdata->material)) {
+ int matnr = nmaterials++;
+ BLI_ghash_insert(material_hash, fdata->material, (void*)matnr);
+ assign_material(ob, fdata->material, matnr + 1);
+ }
+ mface->mat_nr = (int)BLI_ghash_lookup(material_hash, fdata->material);
+
+ // grab the vertex colors and texture cos and dump them into the tface.
+
+ if(user_face_vertex_data) {
+ TFace *tface = DM_get_face_data(result, fi_insert_pos,
+ LAYERTYPE_TFACE);
+
+ // copy all the tface settings back
+ tface->tpage = fdata->tpage;
+ tface->flag = fdata->flag;
+ tface->transp = fdata->transp;
+ tface->mode = fdata->mode;
+ tface->tile = fdata->tile;
+
+ for(i = 0; i < 4; i++) {
+ FaceVertexData *fvdata = face.user_face_vertex_data[i];
+ float *color = fvdata->color;
+
+ tface->uv[i][0] = fvdata->uv[0];
+ tface->uv[i][1] = fvdata->uv[1];
+ tface->col[i] =
+ ((((unsigned int)floor(color[0] + 0.5f)) & 0xff) << 24)
+ | ((((unsigned int)floor(color[1] + 0.5f)) & 0xff) << 16)
+ | ((((unsigned int)floor(color[2] + 0.5f)) & 0xff) << 8)
+ | ((((unsigned int)floor(color[3] + 0.5f)) & 0xff) << 0);
+ }
+
+ test_index_face(mface, NULL, tface, face.vertex_number);
+ } else {
+ test_index_face(mface, NULL, NULL, face.vertex_number);
+ }
+
+ fi_insert_pos++;
+ face_it->Step(face_it->it);
+ }
+
+ BLI_ghash_free(material_hash, NULL, NULL);
+
+ CDDM_calc_edges(result);
+
+ CDDM_calc_normals(result);
+
+ // thats it!
+ if(user_face_vertex_data) MEM_freeN(user_face_vertex_data);
+ MEM_freeN(face.user_face_data);
+
+ return result;
+}
void
BuildMeshDescriptors(