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)
This commit is contained in:
2006-08-28 01:12:36 +00:00
parent 5dbc4c5f8f
commit 433f6c7043
30 changed files with 7885 additions and 1290 deletions

View File

@@ -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(