2.5
Two more files, vpaint.c and editdeform.c No functionality working related to this yet, tomorrow! (Added editdeform.c in mesh after all, it's doing hardly no lattice stuff, and it seems out of place in anim_api)
This commit is contained in:
@@ -38,6 +38,9 @@ struct bContext;
|
||||
struct wmWindowManager;
|
||||
struct EditSelection;
|
||||
struct ViewContext;
|
||||
struct bDeformGroup;
|
||||
struct MDeformWeight;
|
||||
struct MDeformVert;
|
||||
|
||||
// edge and face flag both
|
||||
#define EM_FGON 2
|
||||
@@ -64,6 +67,7 @@ struct ViewContext;
|
||||
|
||||
intptr_t mesh_octree_table(Object *ob, struct EditMesh *em, float *co, char mode);
|
||||
struct EditVert *editmesh_get_x_mirror_vert(Object *ob, struct EditMesh *em, float *co);
|
||||
int mesh_get_x_mirror_vert(Object *ob, int index);
|
||||
|
||||
/* mesh_ops.c */
|
||||
void ED_operatortypes_mesh(void);
|
||||
@@ -119,6 +123,20 @@ void EM_free_backbuf(void);
|
||||
int EM_init_backbuf_border(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
|
||||
int EM_init_backbuf_circle(struct ViewContext *vc, short xs, short ys, short rads);
|
||||
|
||||
/* editdeform.c XXX rename functions? */
|
||||
|
||||
#define WEIGHT_REPLACE 1
|
||||
#define WEIGHT_ADD 2
|
||||
#define WEIGHT_SUBTRACT 3
|
||||
|
||||
void add_defgroup (Object *ob);
|
||||
void remove_vert_defgroup (Object *ob, struct bDeformGroup *dg, int vertnum);
|
||||
void remove_verts_defgroup (Object *obedit, int allverts);
|
||||
struct bDeformGroup *add_defgroup_name (Object *ob, char *name);
|
||||
struct MDeformWeight *verify_defweight (struct MDeformVert *dv, int defgroup);
|
||||
struct MDeformWeight *get_defweight (struct MDeformVert *dv, int defgroup);
|
||||
bDeformGroup *add_defgroup_name (Object *ob, char *name);
|
||||
|
||||
|
||||
#endif /* ED_MESH_H */
|
||||
|
||||
|
||||
1063
source/blender/editors/mesh/editdeform.c
Normal file
1063
source/blender/editors/mesh/editdeform.c
Normal file
@@ -0,0 +1,1063 @@
|
||||
/**
|
||||
* $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 *****
|
||||
* Creator-specific support for vertex deformation groups
|
||||
* Added: apply deform function (ton)
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_cloth_types.h"
|
||||
#include "DNA_curve_types.h"
|
||||
#include "DNA_lattice_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_particle_types.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_editVert.h"
|
||||
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_displist.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_lattice.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "ED_mesh.h"
|
||||
#include "ED_view3d.h"
|
||||
#include "mesh_intern.h"
|
||||
|
||||
/* XXX */
|
||||
static void BIF_undo_push() {}
|
||||
static void error() {}
|
||||
|
||||
/* only in editmode */
|
||||
void sel_verts_defgroup (Object *obedit, int select)
|
||||
{
|
||||
EditVert *eve;
|
||||
Object *ob;
|
||||
int i;
|
||||
MDeformVert *dvert;
|
||||
|
||||
ob= obedit;
|
||||
|
||||
if (!ob)
|
||||
return;
|
||||
|
||||
switch (ob->type){
|
||||
case OB_MESH:
|
||||
{
|
||||
Mesh *me= ob->data;
|
||||
|
||||
for (eve=me->edit_mesh->verts.first; eve; eve=eve->next){
|
||||
dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT);
|
||||
|
||||
if (dvert && dvert->totweight){
|
||||
for (i=0; i<dvert->totweight; i++){
|
||||
if (dvert->dw[i].def_nr == (ob->actdef-1)){
|
||||
if (select) eve->f |= SELECT;
|
||||
else eve->f &= ~SELECT;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* this has to be called, because this function operates on vertices only */
|
||||
if(select) EM_select_flush(me->edit_mesh); // vertices to edges/faces
|
||||
else EM_deselect_flush(me->edit_mesh);
|
||||
}
|
||||
break;
|
||||
case OB_LATTICE:
|
||||
if(editLatt->dvert) {
|
||||
BPoint *bp;
|
||||
int a, tot;
|
||||
|
||||
dvert= editLatt->dvert;
|
||||
|
||||
tot= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
|
||||
for(a=0, bp= editLatt->def; a<tot; a++, bp++, dvert++) {
|
||||
for (i=0; i<dvert->totweight; i++){
|
||||
if (dvert->dw[i].def_nr == (ob->actdef-1)) {
|
||||
if(select) bp->f1 |= SELECT;
|
||||
else bp->f1 &= ~SELECT;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if deform vertex has defgroup index */
|
||||
MDeformWeight *get_defweight (MDeformVert *dv, int defgroup)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!dv || defgroup<0)
|
||||
return NULL;
|
||||
|
||||
for (i=0; i<dv->totweight; i++){
|
||||
if (dv->dw[i].def_nr == defgroup)
|
||||
return dv->dw+i;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Ensures that mv has a deform weight entry for
|
||||
the specified defweight group */
|
||||
/* Note this function is mirrored in editmesh_tools.c, for use for editvertices */
|
||||
MDeformWeight *verify_defweight (MDeformVert *dv, int defgroup)
|
||||
{
|
||||
MDeformWeight *newdw;
|
||||
|
||||
/* do this check always, this function is used to check for it */
|
||||
if (!dv || defgroup<0)
|
||||
return NULL;
|
||||
|
||||
newdw = get_defweight (dv, defgroup);
|
||||
if (newdw)
|
||||
return newdw;
|
||||
|
||||
newdw = MEM_callocN (sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight");
|
||||
if (dv->dw){
|
||||
memcpy (newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
|
||||
MEM_freeN (dv->dw);
|
||||
}
|
||||
dv->dw=newdw;
|
||||
|
||||
dv->dw[dv->totweight].weight=0.0f;
|
||||
dv->dw[dv->totweight].def_nr=defgroup;
|
||||
/* Group index */
|
||||
|
||||
dv->totweight++;
|
||||
|
||||
return dv->dw+(dv->totweight-1);
|
||||
}
|
||||
|
||||
bDeformGroup *add_defgroup_name (Object *ob, char *name)
|
||||
{
|
||||
bDeformGroup *defgroup;
|
||||
|
||||
if (!ob)
|
||||
return NULL;
|
||||
|
||||
defgroup = MEM_callocN (sizeof(bDeformGroup), "add deformGroup");
|
||||
|
||||
BLI_strncpy (defgroup->name, name, 32);
|
||||
|
||||
BLI_addtail(&ob->defbase, defgroup);
|
||||
unique_vertexgroup_name(defgroup, ob);
|
||||
|
||||
ob->actdef = BLI_countlist(&ob->defbase);
|
||||
|
||||
return defgroup;
|
||||
}
|
||||
|
||||
void add_defgroup (Object *ob)
|
||||
{
|
||||
add_defgroup_name (ob, "Group");
|
||||
}
|
||||
|
||||
|
||||
void duplicate_defgroup ( Object *ob )
|
||||
{
|
||||
bDeformGroup *dg, *cdg;
|
||||
char name[32], s[32];
|
||||
MDeformWeight *org, *cpy;
|
||||
MDeformVert *dvert;
|
||||
Mesh *me;
|
||||
int i, idg, icdg;
|
||||
|
||||
if (ob->type != OB_MESH)
|
||||
return;
|
||||
|
||||
dg = BLI_findlink (&ob->defbase, (ob->actdef-1));
|
||||
if (!dg)
|
||||
return;
|
||||
|
||||
if (strstr(dg->name, "_copy")) {
|
||||
BLI_strncpy (name, dg->name, 32); /* will be renamed _copy.001... etc */
|
||||
} else {
|
||||
BLI_snprintf (name, 32, "%s_copy", dg->name);
|
||||
while (get_named_vertexgroup (ob, name)) {
|
||||
if ((strlen (name) + 6) > 32) {
|
||||
error ("Error: the name for the new group is > 32 characters");
|
||||
return;
|
||||
}
|
||||
strcpy (s, name);
|
||||
BLI_snprintf (name, 32, "%s_copy", s);
|
||||
}
|
||||
}
|
||||
|
||||
cdg = copy_defgroup (dg);
|
||||
strcpy (cdg->name, name);
|
||||
unique_vertexgroup_name(cdg, ob);
|
||||
|
||||
BLI_addtail (&ob->defbase, cdg);
|
||||
|
||||
idg = (ob->actdef-1);
|
||||
ob->actdef = BLI_countlist (&ob->defbase);
|
||||
icdg = (ob->actdef-1);
|
||||
|
||||
me = get_mesh (ob);
|
||||
if (!me->dvert)
|
||||
return;
|
||||
|
||||
for (i = 0; i < me->totvert; i++) {
|
||||
dvert = me->dvert+i;
|
||||
org = get_defweight (dvert, idg);
|
||||
if (org) {
|
||||
cpy = verify_defweight (dvert, icdg);
|
||||
cpy->weight = org->weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void del_defgroup_update_users(Object *ob, int id)
|
||||
{
|
||||
ExplodeModifierData *emd;
|
||||
ModifierData *md;
|
||||
ParticleSystem *psys;
|
||||
ClothModifierData *clmd;
|
||||
ClothSimSettings *clsim;
|
||||
int a;
|
||||
|
||||
/* these cases don't use names to refer to vertex groups, so when
|
||||
* they get deleted the numbers get out of sync, this corrects that */
|
||||
|
||||
if(ob->soft) {
|
||||
if(ob->soft->vertgroup == id)
|
||||
ob->soft->vertgroup= 0;
|
||||
else if(ob->soft->vertgroup > id)
|
||||
ob->soft->vertgroup--;
|
||||
}
|
||||
|
||||
for(md=ob->modifiers.first; md; md=md->next) {
|
||||
if(md->type == eModifierType_Explode) {
|
||||
emd= (ExplodeModifierData*)md;
|
||||
|
||||
if(emd->vgroup == id)
|
||||
emd->vgroup= 0;
|
||||
else if(emd->vgroup > id)
|
||||
emd->vgroup--;
|
||||
}
|
||||
else if(md->type == eModifierType_Cloth) {
|
||||
clmd= (ClothModifierData*)md;
|
||||
clsim= clmd->sim_parms;
|
||||
|
||||
if(clsim) {
|
||||
if(clsim->vgroup_mass == id)
|
||||
clsim->vgroup_mass= 0;
|
||||
else if(clsim->vgroup_mass > id)
|
||||
clsim->vgroup_mass--;
|
||||
|
||||
if(clsim->vgroup_bend == id)
|
||||
clsim->vgroup_bend= 0;
|
||||
else if(clsim->vgroup_bend > id)
|
||||
clsim->vgroup_bend--;
|
||||
|
||||
if(clsim->vgroup_struct == id)
|
||||
clsim->vgroup_struct= 0;
|
||||
else if(clsim->vgroup_struct > id)
|
||||
clsim->vgroup_struct--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(psys=ob->particlesystem.first; psys; psys=psys->next) {
|
||||
for(a=0; a<PSYS_TOT_VG; a++)
|
||||
if(psys->vgroup[a] == id)
|
||||
psys->vgroup[a]= 0;
|
||||
else if(psys->vgroup[a] > id)
|
||||
psys->vgroup[a]--;
|
||||
}
|
||||
}
|
||||
|
||||
void del_defgroup_in_object_mode ( Object *ob )
|
||||
{
|
||||
bDeformGroup *dg;
|
||||
MDeformVert *dvert;
|
||||
Mesh *me;
|
||||
int i, e;
|
||||
|
||||
if ((!ob) || (ob->type != OB_MESH))
|
||||
return;
|
||||
|
||||
dg = BLI_findlink (&ob->defbase, (ob->actdef-1));
|
||||
if (!dg)
|
||||
return;
|
||||
|
||||
me = get_mesh (ob);
|
||||
if (me->dvert) {
|
||||
for (i = 0; i < me->totvert; i++) {
|
||||
dvert = me->dvert + i;
|
||||
if (dvert) {
|
||||
if (get_defweight (dvert, (ob->actdef-1)))
|
||||
remove_vert_defgroup (ob, dg, i);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < me->totvert; i++) {
|
||||
dvert = me->dvert+i;
|
||||
if (dvert) {
|
||||
for (e = 0; e < dvert->totweight; e++) {
|
||||
if (dvert->dw[e].def_nr > (ob->actdef-1))
|
||||
dvert->dw[e].def_nr--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
del_defgroup_update_users(ob, ob->actdef);
|
||||
|
||||
/* Update the active deform index if necessary */
|
||||
if (ob->actdef == BLI_countlist(&ob->defbase))
|
||||
ob->actdef--;
|
||||
|
||||
/* Remove the group */
|
||||
BLI_freelinkN (&ob->defbase, dg);
|
||||
}
|
||||
|
||||
void del_defgroup (Object *ob)
|
||||
{
|
||||
bDeformGroup *defgroup;
|
||||
int i;
|
||||
|
||||
if (!ob)
|
||||
return;
|
||||
|
||||
if (!ob->actdef)
|
||||
return;
|
||||
|
||||
defgroup = BLI_findlink(&ob->defbase, ob->actdef-1);
|
||||
if (!defgroup)
|
||||
return;
|
||||
|
||||
/* Make sure that no verts are using this group */
|
||||
remove_verts_defgroup(ob, 1);
|
||||
|
||||
/* Make sure that any verts with higher indices are adjusted accordingly */
|
||||
if(ob->type==OB_MESH) {
|
||||
Mesh *me= ob->data;
|
||||
EditMesh *em = me->edit_mesh;
|
||||
EditVert *eve;
|
||||
MDeformVert *dvert;
|
||||
|
||||
for (eve=em->verts.first; eve; eve=eve->next){
|
||||
dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT);
|
||||
|
||||
if (dvert)
|
||||
for (i=0; i<dvert->totweight; i++)
|
||||
if (dvert->dw[i].def_nr > (ob->actdef-1))
|
||||
dvert->dw[i].def_nr--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
BPoint *bp;
|
||||
MDeformVert *dvert= editLatt->dvert;
|
||||
int a, tot;
|
||||
|
||||
if (dvert) {
|
||||
tot= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
|
||||
for(a=0, bp= editLatt->def; a<tot; a++, bp++, dvert++) {
|
||||
for (i=0; i<dvert->totweight; i++){
|
||||
if (dvert->dw[i].def_nr > (ob->actdef-1))
|
||||
dvert->dw[i].def_nr--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
del_defgroup_update_users(ob, ob->actdef);
|
||||
|
||||
/* Update the active deform index if necessary */
|
||||
if (ob->actdef==BLI_countlist(&ob->defbase))
|
||||
ob->actdef--;
|
||||
|
||||
/* Remove the group */
|
||||
BLI_freelinkN (&ob->defbase, defgroup);
|
||||
|
||||
/* remove all dverts */
|
||||
if(ob->actdef==0) {
|
||||
if(ob->type==OB_MESH) {
|
||||
Mesh *me= ob->data;
|
||||
CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
|
||||
me->dvert= NULL;
|
||||
}
|
||||
else {
|
||||
if (editLatt->dvert) {
|
||||
MEM_freeN(editLatt->dvert);
|
||||
editLatt->dvert= NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void del_all_defgroups (Object *ob)
|
||||
{
|
||||
/* Sanity check */
|
||||
if (ob == NULL)
|
||||
return;
|
||||
|
||||
/* Remove all DVerts */
|
||||
if (ob->type==OB_MESH) {
|
||||
Mesh *me= ob->data;
|
||||
CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
|
||||
me->dvert= NULL;
|
||||
}
|
||||
else {
|
||||
if (editLatt->dvert) {
|
||||
MEM_freeN(editLatt->dvert);
|
||||
editLatt->dvert= NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove all DefGroups */
|
||||
BLI_freelistN(&ob->defbase);
|
||||
|
||||
/* Fix counters/indices */
|
||||
ob->actdef= 0;
|
||||
}
|
||||
|
||||
void create_dverts(ID *id)
|
||||
{
|
||||
/* create deform verts
|
||||
*/
|
||||
|
||||
if( GS(id->name)==ID_ME) {
|
||||
Mesh *me= (Mesh *)id;
|
||||
me->dvert= CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert);
|
||||
}
|
||||
else if( GS(id->name)==ID_LT) {
|
||||
Lattice *lt= (Lattice *)id;
|
||||
lt->dvert= MEM_callocN(sizeof(MDeformVert)*lt->pntsu*lt->pntsv*lt->pntsw, "lattice deformVert");
|
||||
}
|
||||
}
|
||||
|
||||
/* for mesh in object mode
|
||||
lattice can be in editmode */
|
||||
void remove_vert_def_nr (Object *ob, int def_nr, int vertnum)
|
||||
{
|
||||
/* This routine removes the vertex from the deform
|
||||
* group with number def_nr.
|
||||
*
|
||||
* This routine is meant to be fast, so it is the
|
||||
* responsibility of the calling routine to:
|
||||
* a) test whether ob is non-NULL
|
||||
* b) test whether ob is a mesh
|
||||
* c) calculate def_nr
|
||||
*/
|
||||
|
||||
MDeformWeight *newdw;
|
||||
MDeformVert *dvert= NULL;
|
||||
int i;
|
||||
|
||||
/* get the deform vertices corresponding to the
|
||||
* vertnum
|
||||
*/
|
||||
if(ob->type==OB_MESH) {
|
||||
if( ((Mesh*)ob->data)->dvert )
|
||||
dvert = ((Mesh*)ob->data)->dvert + vertnum;
|
||||
}
|
||||
else if(ob->type==OB_LATTICE) {
|
||||
Lattice *lt= ob->data;
|
||||
|
||||
if(lt->editlatt) lt= lt->editlatt;
|
||||
if(lt->dvert)
|
||||
dvert = lt->dvert + vertnum;
|
||||
}
|
||||
|
||||
if(dvert==NULL)
|
||||
return;
|
||||
|
||||
/* for all of the deform weights in the
|
||||
* deform vert
|
||||
*/
|
||||
for (i=dvert->totweight - 1 ; i>=0 ; i--){
|
||||
|
||||
/* if the def_nr is the same as the one
|
||||
* for our weight group then remove it
|
||||
* from this deform vert.
|
||||
*/
|
||||
if (dvert->dw[i].def_nr == def_nr) {
|
||||
dvert->totweight--;
|
||||
|
||||
/* if there are still other deform weights
|
||||
* attached to this vert then remove this
|
||||
* deform weight, and reshuffle the others
|
||||
*/
|
||||
if (dvert->totweight) {
|
||||
newdw = MEM_mallocN (sizeof(MDeformWeight)*(dvert->totweight),
|
||||
"deformWeight");
|
||||
if (dvert->dw){
|
||||
memcpy (newdw, dvert->dw, sizeof(MDeformWeight)*i);
|
||||
memcpy (newdw+i, dvert->dw+i+1,
|
||||
sizeof(MDeformWeight)*(dvert->totweight-i));
|
||||
MEM_freeN (dvert->dw);
|
||||
}
|
||||
dvert->dw=newdw;
|
||||
}
|
||||
/* if there are no other deform weights
|
||||
* left then just remove the deform weight
|
||||
*/
|
||||
else {
|
||||
MEM_freeN (dvert->dw);
|
||||
dvert->dw = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* for Mesh in Object mode */
|
||||
/* allows editmode for Lattice */
|
||||
void add_vert_defnr (Object *ob, int def_nr, int vertnum,
|
||||
float weight, int assignmode)
|
||||
{
|
||||
/* add the vert to the deform group with the
|
||||
* specified number
|
||||
*/
|
||||
MDeformVert *dv= NULL;
|
||||
MDeformWeight *newdw;
|
||||
int i;
|
||||
|
||||
/* get the vert */
|
||||
if(ob->type==OB_MESH) {
|
||||
if(((Mesh*)ob->data)->dvert)
|
||||
dv = ((Mesh*)ob->data)->dvert + vertnum;
|
||||
}
|
||||
else if(ob->type==OB_LATTICE) {
|
||||
Lattice *lt= ob->data;
|
||||
|
||||
if(lt->editlatt) lt= lt->editlatt;
|
||||
|
||||
if(lt->dvert)
|
||||
dv = lt->dvert + vertnum;
|
||||
}
|
||||
|
||||
if(dv==NULL)
|
||||
return;
|
||||
|
||||
/* Lets first check to see if this vert is
|
||||
* already in the weight group -- if so
|
||||
* lets update it
|
||||
*/
|
||||
for (i=0; i<dv->totweight; i++){
|
||||
|
||||
/* if this weight cooresponds to the
|
||||
* deform group, then add it using
|
||||
* the assign mode provided
|
||||
*/
|
||||
if (dv->dw[i].def_nr == def_nr){
|
||||
|
||||
switch (assignmode) {
|
||||
case WEIGHT_REPLACE:
|
||||
dv->dw[i].weight=weight;
|
||||
break;
|
||||
case WEIGHT_ADD:
|
||||
dv->dw[i].weight+=weight;
|
||||
if (dv->dw[i].weight >= 1.0)
|
||||
dv->dw[i].weight = 1.0;
|
||||
break;
|
||||
case WEIGHT_SUBTRACT:
|
||||
dv->dw[i].weight-=weight;
|
||||
/* if the weight is zero or less then
|
||||
* remove the vert from the deform group
|
||||
*/
|
||||
if (dv->dw[i].weight <= 0.0)
|
||||
remove_vert_def_nr(ob, def_nr, vertnum);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* if the vert wasn't in the deform group then
|
||||
* we must take a different form of action ...
|
||||
*/
|
||||
|
||||
switch (assignmode) {
|
||||
case WEIGHT_SUBTRACT:
|
||||
/* if we are subtracting then we don't
|
||||
* need to do anything
|
||||
*/
|
||||
return;
|
||||
|
||||
case WEIGHT_REPLACE:
|
||||
case WEIGHT_ADD:
|
||||
/* if we are doing an additive assignment, then
|
||||
* we need to create the deform weight
|
||||
*/
|
||||
newdw = MEM_callocN (sizeof(MDeformWeight)*(dv->totweight+1),
|
||||
"deformWeight");
|
||||
if (dv->dw){
|
||||
memcpy (newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
|
||||
MEM_freeN (dv->dw);
|
||||
}
|
||||
dv->dw=newdw;
|
||||
|
||||
dv->dw[dv->totweight].weight=weight;
|
||||
dv->dw[dv->totweight].def_nr=def_nr;
|
||||
|
||||
dv->totweight++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* called while not in editmode */
|
||||
void add_vert_to_defgroup (Object *ob, bDeformGroup *dg, int vertnum,
|
||||
float weight, int assignmode)
|
||||
{
|
||||
/* add the vert to the deform group with the
|
||||
* specified assign mode
|
||||
*/
|
||||
int def_nr;
|
||||
|
||||
/* get the deform group number, exit if
|
||||
* it can't be found
|
||||
*/
|
||||
def_nr = get_defgroup_num(ob, dg);
|
||||
if (def_nr < 0) return;
|
||||
|
||||
/* if there's no deform verts then
|
||||
* create some
|
||||
*/
|
||||
if(ob->type==OB_MESH) {
|
||||
if (!((Mesh*)ob->data)->dvert)
|
||||
create_dverts(ob->data);
|
||||
}
|
||||
else if(ob->type==OB_LATTICE) {
|
||||
if (!((Lattice*)ob->data)->dvert)
|
||||
create_dverts(ob->data);
|
||||
}
|
||||
|
||||
/* call another function to do the work
|
||||
*/
|
||||
add_vert_defnr (ob, def_nr, vertnum, weight, assignmode);
|
||||
}
|
||||
|
||||
/* Only available in editmode */
|
||||
void assign_verts_defgroup (Object *obedit)
|
||||
{
|
||||
float editbutvweight; /* XXX */
|
||||
Object *ob;
|
||||
EditVert *eve;
|
||||
bDeformGroup *dg, *eg;
|
||||
MDeformWeight *newdw;
|
||||
MDeformVert *dvert;
|
||||
int i, done;
|
||||
|
||||
// XXX if(multires_level1_test()) return;
|
||||
|
||||
ob= obedit;
|
||||
|
||||
if (!ob)
|
||||
return;
|
||||
|
||||
dg=BLI_findlink(&ob->defbase, ob->actdef-1);
|
||||
if (!dg){
|
||||
error ("No vertex group is active");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ob->type){
|
||||
case OB_MESH:
|
||||
{
|
||||
Mesh *me= ob->data;
|
||||
|
||||
if (!CustomData_has_layer(&me->edit_mesh->vdata, CD_MDEFORMVERT))
|
||||
EM_add_data_layer(me->edit_mesh, &me->edit_mesh->vdata, CD_MDEFORMVERT);
|
||||
|
||||
/* Go through the list of editverts and assign them */
|
||||
for (eve=me->edit_mesh->verts.first; eve; eve=eve->next){
|
||||
dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT);
|
||||
|
||||
if (dvert && (eve->f & 1)){
|
||||
done=0;
|
||||
/* See if this vert already has a reference to this group */
|
||||
/* If so: Change its weight */
|
||||
done=0;
|
||||
for (i=0; i<dvert->totweight; i++){
|
||||
eg = BLI_findlink (&ob->defbase, dvert->dw[i].def_nr);
|
||||
/* Find the actual group */
|
||||
if (eg==dg){
|
||||
dvert->dw[i].weight=editbutvweight;
|
||||
done=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* If not: Add the group and set its weight */
|
||||
if (!done){
|
||||
newdw = MEM_callocN (sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight");
|
||||
if (dvert->dw){
|
||||
memcpy (newdw, dvert->dw, sizeof(MDeformWeight)*dvert->totweight);
|
||||
MEM_freeN (dvert->dw);
|
||||
}
|
||||
dvert->dw=newdw;
|
||||
|
||||
dvert->dw[dvert->totweight].weight= editbutvweight;
|
||||
dvert->dw[dvert->totweight].def_nr= ob->actdef-1;
|
||||
|
||||
dvert->totweight++;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OB_LATTICE:
|
||||
{
|
||||
BPoint *bp;
|
||||
int a, tot;
|
||||
|
||||
if(editLatt->dvert==NULL)
|
||||
create_dverts(&editLatt->id);
|
||||
|
||||
tot= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
|
||||
for(a=0, bp= editLatt->def; a<tot; a++, bp++) {
|
||||
if(bp->f1 & SELECT)
|
||||
add_vert_defnr (ob, ob->actdef-1, a, editbutvweight, WEIGHT_REPLACE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf ("Assigning deformation groups to unknown object type\n");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* mesh object mode, lattice can be in editmode */
|
||||
void remove_vert_defgroup (Object *ob, bDeformGroup *dg, int vertnum)
|
||||
{
|
||||
/* This routine removes the vertex from the specified
|
||||
* deform group.
|
||||
*/
|
||||
|
||||
int def_nr;
|
||||
|
||||
/* if the object is NULL abort
|
||||
*/
|
||||
if (!ob)
|
||||
return;
|
||||
|
||||
/* get the deform number that cooresponds
|
||||
* to this deform group, and abort if it
|
||||
* can not be found.
|
||||
*/
|
||||
def_nr = get_defgroup_num(ob, dg);
|
||||
if (def_nr < 0) return;
|
||||
|
||||
/* call another routine to do the work
|
||||
*/
|
||||
remove_vert_def_nr (ob, def_nr, vertnum);
|
||||
}
|
||||
|
||||
/* for mesh in object mode lattice can be in editmode */
|
||||
static float get_vert_def_nr (Object *ob, int def_nr, int vertnum)
|
||||
{
|
||||
MDeformVert *dvert= NULL;
|
||||
int i;
|
||||
|
||||
/* get the deform vertices corresponding to the
|
||||
* vertnum
|
||||
*/
|
||||
if(ob->type==OB_MESH) {
|
||||
if( ((Mesh*)ob->data)->dvert )
|
||||
dvert = ((Mesh*)ob->data)->dvert + vertnum;
|
||||
}
|
||||
else if(ob->type==OB_LATTICE) {
|
||||
Lattice *lt= ob->data;
|
||||
|
||||
if(lt->editlatt) lt= lt->editlatt;
|
||||
|
||||
if(lt->dvert)
|
||||
dvert = lt->dvert + vertnum;
|
||||
}
|
||||
|
||||
if(dvert==NULL)
|
||||
return 0.0f;
|
||||
|
||||
for(i=dvert->totweight-1 ; i>=0 ; i--)
|
||||
if(dvert->dw[i].def_nr == def_nr)
|
||||
return dvert->dw[i].weight;
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/* mesh object mode, lattice can be in editmode */
|
||||
float get_vert_defgroup (Object *ob, bDeformGroup *dg, int vertnum)
|
||||
{
|
||||
int def_nr;
|
||||
|
||||
if(!ob)
|
||||
return 0.0f;
|
||||
|
||||
def_nr = get_defgroup_num(ob, dg);
|
||||
if(def_nr < 0) return 0.0f;
|
||||
|
||||
return get_vert_def_nr (ob, def_nr, vertnum);
|
||||
}
|
||||
|
||||
/* Only available in editmode */
|
||||
/* removes from active defgroup, if allverts==0 only selected vertices */
|
||||
void remove_verts_defgroup (Object *obedit, int allverts)
|
||||
{
|
||||
Object *ob;
|
||||
EditVert *eve;
|
||||
MDeformVert *dvert;
|
||||
MDeformWeight *newdw;
|
||||
bDeformGroup *dg, *eg;
|
||||
int i;
|
||||
|
||||
// XXX if(multires_level1_test()) return;
|
||||
|
||||
ob= obedit;
|
||||
|
||||
if (!ob)
|
||||
return;
|
||||
|
||||
dg=BLI_findlink(&ob->defbase, ob->actdef-1);
|
||||
if (!dg){
|
||||
error ("No vertex group is active");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ob->type){
|
||||
case OB_MESH:
|
||||
{
|
||||
Mesh *me= ob->data;
|
||||
|
||||
for (eve=me->edit_mesh->verts.first; eve; eve=eve->next){
|
||||
dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT);
|
||||
|
||||
if (dvert && dvert->dw && ((eve->f & 1) || allverts)){
|
||||
for (i=0; i<dvert->totweight; i++){
|
||||
/* Find group */
|
||||
eg = BLI_findlink (&ob->defbase, dvert->dw[i].def_nr);
|
||||
if (eg == dg){
|
||||
dvert->totweight--;
|
||||
if (dvert->totweight){
|
||||
newdw = MEM_mallocN (sizeof(MDeformWeight)*(dvert->totweight), "deformWeight");
|
||||
|
||||
if (dvert->dw){
|
||||
memcpy (newdw, dvert->dw, sizeof(MDeformWeight)*i);
|
||||
memcpy (newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i));
|
||||
MEM_freeN (dvert->dw);
|
||||
}
|
||||
dvert->dw=newdw;
|
||||
}
|
||||
else{
|
||||
MEM_freeN (dvert->dw);
|
||||
dvert->dw=NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OB_LATTICE:
|
||||
|
||||
if(editLatt->dvert) {
|
||||
BPoint *bp;
|
||||
int a, tot= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
|
||||
|
||||
for(a=0, bp= editLatt->def; a<tot; a++, bp++) {
|
||||
if(allverts || (bp->f1 & SELECT))
|
||||
remove_vert_defgroup (ob, dg, a);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("Removing deformation groups from unknown object type\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Only available in editmode */
|
||||
/* removes from all defgroup, if allverts==0 only selected vertices */
|
||||
void remove_verts_defgroups(Object *obedit, int allverts)
|
||||
{
|
||||
Object *ob;
|
||||
int actdef, defCount;
|
||||
|
||||
// XXX if (multires_level1_test()) return;
|
||||
|
||||
ob= obedit;
|
||||
if (ob == NULL) return;
|
||||
|
||||
actdef= ob->actdef;
|
||||
defCount= BLI_countlist(&ob->defbase);
|
||||
|
||||
if (defCount == 0) {
|
||||
error("Object has no vertex groups");
|
||||
return;
|
||||
}
|
||||
|
||||
/* To prevent code redundancy, we just use remove_verts_defgroup, but that
|
||||
* only operates on the active vgroup. So we iterate through all groups, by changing
|
||||
* active group index
|
||||
*/
|
||||
for (ob->actdef= 1; ob->actdef <= defCount; ob->actdef++)
|
||||
remove_verts_defgroup(ob, allverts);
|
||||
|
||||
ob->actdef= actdef;
|
||||
}
|
||||
|
||||
void vertexgroup_select_by_name(Object *ob, char *name)
|
||||
{
|
||||
bDeformGroup *curdef;
|
||||
int actdef= 1;
|
||||
|
||||
if(ob==NULL) return;
|
||||
|
||||
for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++){
|
||||
if (!strcmp(curdef->name, name)) {
|
||||
ob->actdef= actdef;
|
||||
return;
|
||||
}
|
||||
}
|
||||
ob->actdef=0; // this signals on painting to create a new one, if a bone in posemode is selected */
|
||||
}
|
||||
|
||||
/* This function provides a shortcut for adding/removing verts from
|
||||
* vertex groups. It is called by the Ctrl-G hotkey in EditMode for Meshes
|
||||
* and Lattices. (currently only restricted to those two)
|
||||
* It is only responsible for
|
||||
*/
|
||||
void vgroup_assign_with_menu(Object *ob)
|
||||
{
|
||||
int defCount;
|
||||
int mode;
|
||||
|
||||
/* prevent crashes */
|
||||
if (ob==NULL) return;
|
||||
|
||||
defCount= BLI_countlist(&ob->defbase);
|
||||
|
||||
/* give user choices of adding to current/new or removing from current */
|
||||
// XXX if (defCount && ob->actdef)
|
||||
// mode = pupmenu("Vertex Groups %t|Add Selected to New Group %x1|Add Selected to Active Group %x2|Remove Selected from Active Group %x3|Remove Selected from All Groups %x4");
|
||||
// else
|
||||
// mode= pupmenu("Vertex Groups %t|Add Selected to New Group %x1");
|
||||
|
||||
/* handle choices */
|
||||
switch (mode) {
|
||||
case 1: /* add to new group */
|
||||
add_defgroup(ob);
|
||||
assign_verts_defgroup(ob);
|
||||
BIF_undo_push("Assign to vertex group");
|
||||
break;
|
||||
case 2: /* add to current group */
|
||||
assign_verts_defgroup(ob);
|
||||
BIF_undo_push("Assign to vertex group");
|
||||
break;
|
||||
case 3: /* remove from current group */
|
||||
remove_verts_defgroup(ob, 0);
|
||||
BIF_undo_push("Remove from vertex group");
|
||||
break;
|
||||
case 4: /* remove from all groups */
|
||||
remove_verts_defgroups(ob, 0);
|
||||
BIF_undo_push("Remove from all vertex groups");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function provides a shortcut for commonly used vertex group
|
||||
* functions - change weight (not implemented), change active group, delete active group,
|
||||
* when Ctrl-Shift-G is used in EditMode, for Meshes and Lattices (only for now).
|
||||
*/
|
||||
void vgroup_operation_with_menu(Object *ob)
|
||||
{
|
||||
int defCount;
|
||||
int mode;
|
||||
|
||||
/* prevent crashes and useless cases */
|
||||
if (ob==NULL) return;
|
||||
|
||||
defCount= BLI_countlist(&ob->defbase);
|
||||
if (defCount == 0) return;
|
||||
|
||||
/* give user choices of adding to current/new or removing from current */
|
||||
// XXX if (ob->actdef)
|
||||
// mode = pupmenu("Vertex Groups %t|Change Active Group%x1|Delete Active Group%x2|Delete All Groups%x3");
|
||||
// else
|
||||
// mode= pupmenu("Vertex Groups %t|Change Active Group%x1|Delete All Groups%x3");
|
||||
|
||||
/* handle choices */
|
||||
switch (mode) {
|
||||
case 1: /* change active group*/
|
||||
{
|
||||
char *menustr= NULL; // XXX get_vertexgroup_menustr(ob);
|
||||
short nr;
|
||||
|
||||
if (menustr) {
|
||||
// XXX nr= pupmenu(menustr);
|
||||
|
||||
if ((nr >= 1) && (nr <= defCount))
|
||||
ob->actdef= nr;
|
||||
|
||||
MEM_freeN(menustr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2: /* delete active group */
|
||||
{
|
||||
del_defgroup(ob);
|
||||
BIF_undo_push("Delete vertex group");
|
||||
}
|
||||
break;
|
||||
case 3: /* delete all groups */
|
||||
{
|
||||
del_all_defgroups(ob);
|
||||
BIF_undo_push("Delete all vertex groups");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source, EditEdge
|
||||
|
||||
/* ******************* meshtools.c */
|
||||
|
||||
int mesh_get_x_mirror_vert(Object *ob, int index);
|
||||
|
||||
/* XXX move to uv editor? */
|
||||
enum {
|
||||
|
||||
1584
source/blender/editors/space_view3d/vpaint.c
Normal file
1584
source/blender/editors/space_view3d/vpaint.c
Normal file
@@ -0,0 +1,1584 @@
|
||||
/**
|
||||
* $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 <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_arithb.h"
|
||||
#include "MTC_matrixops.h"
|
||||
|
||||
#include "DNA_action_types.h"
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_brush_types.h"
|
||||
#include "DNA_cloth_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_particle_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "BKE_armature.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_cloth.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_displist.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_multires.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
#include "BIF_gl.h"
|
||||
|
||||
#include "ED_mesh.h"
|
||||
#include "ED_object.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
#include "view3d_intern.h"
|
||||
|
||||
/* Gvp.mode */
|
||||
#define VP_MIX 0
|
||||
#define VP_ADD 1
|
||||
#define VP_SUB 2
|
||||
#define VP_MUL 3
|
||||
#define VP_BLUR 4
|
||||
#define VP_LIGHTEN 5
|
||||
#define VP_DARKEN 6
|
||||
|
||||
#define MAXINDEX 512000
|
||||
|
||||
/* XXX */
|
||||
static void BIF_undo_push() {}
|
||||
static void error() {}
|
||||
static int get_mbut() {return 0;}
|
||||
|
||||
VPaint Gvp= {1.0, 1.0, 1.0, 0.2, 25.0, 1.0, 1.0, 0, VP_AREA+VP_SOFT+VP_SPRAY, 0};
|
||||
VPaint Gwp= {1.0, 1.0, 1.0, 1.0, 25.0, 1.0, 1.0, 0, VP_AREA+VP_SOFT, 0};
|
||||
|
||||
static int *get_indexarray(void)
|
||||
{
|
||||
return MEM_mallocN(sizeof(int)*MAXINDEX + 2, "vertexpaint");
|
||||
}
|
||||
|
||||
void free_vertexpaint()
|
||||
{
|
||||
|
||||
if(Gvp.vpaint_prev) MEM_freeN(Gvp.vpaint_prev);
|
||||
Gvp.vpaint_prev= NULL;
|
||||
|
||||
mesh_octree_table(NULL, NULL, NULL, 'e');
|
||||
}
|
||||
|
||||
/* in contradiction to cpack drawing colors, the MCOL colors (vpaint colors) are per byte!
|
||||
so not endian sensitive. Mcol = ABGR!!! so be cautious with cpack calls */
|
||||
|
||||
unsigned int rgba_to_mcol(float r, float g, float b, float a)
|
||||
{
|
||||
int ir, ig, ib, ia;
|
||||
unsigned int col;
|
||||
char *cp;
|
||||
|
||||
ir= floor(255.0*r);
|
||||
if(ir<0) ir= 0; else if(ir>255) ir= 255;
|
||||
ig= floor(255.0*g);
|
||||
if(ig<0) ig= 0; else if(ig>255) ig= 255;
|
||||
ib= floor(255.0*b);
|
||||
if(ib<0) ib= 0; else if(ib>255) ib= 255;
|
||||
ia= floor(255.0*a);
|
||||
if(ia<0) ia= 0; else if(ia>255) ia= 255;
|
||||
|
||||
cp= (char *)&col;
|
||||
cp[0]= ia;
|
||||
cp[1]= ib;
|
||||
cp[2]= ig;
|
||||
cp[3]= ir;
|
||||
|
||||
return col;
|
||||
|
||||
}
|
||||
|
||||
static unsigned int vpaint_get_current_col(VPaint *vp)
|
||||
{
|
||||
return rgba_to_mcol(vp->r, vp->g, vp->b, 1.0f);
|
||||
}
|
||||
|
||||
void do_shared_vertexcol(Mesh *me)
|
||||
{
|
||||
/* if no mcol: do not do */
|
||||
/* if tface: only the involved faces, otherwise all */
|
||||
MFace *mface;
|
||||
MTFace *tface;
|
||||
int a;
|
||||
short *scolmain, *scol;
|
||||
char *mcol;
|
||||
|
||||
if(me->mcol==0 || me->totvert==0 || me->totface==0) return;
|
||||
|
||||
scolmain= MEM_callocN(4*sizeof(short)*me->totvert, "colmain");
|
||||
|
||||
tface= me->mtface;
|
||||
mface= me->mface;
|
||||
mcol= (char *)me->mcol;
|
||||
for(a=me->totface; a>0; a--, mface++, mcol+=16) {
|
||||
if((tface && tface->mode & TF_SHAREDCOL) || (G.f & G_FACESELECT)==0) {
|
||||
scol= scolmain+4*mface->v1;
|
||||
scol[0]++; scol[1]+= mcol[1]; scol[2]+= mcol[2]; scol[3]+= mcol[3];
|
||||
scol= scolmain+4*mface->v2;
|
||||
scol[0]++; scol[1]+= mcol[5]; scol[2]+= mcol[6]; scol[3]+= mcol[7];
|
||||
scol= scolmain+4*mface->v3;
|
||||
scol[0]++; scol[1]+= mcol[9]; scol[2]+= mcol[10]; scol[3]+= mcol[11];
|
||||
if(mface->v4) {
|
||||
scol= scolmain+4*mface->v4;
|
||||
scol[0]++; scol[1]+= mcol[13]; scol[2]+= mcol[14]; scol[3]+= mcol[15];
|
||||
}
|
||||
}
|
||||
if(tface) tface++;
|
||||
}
|
||||
|
||||
a= me->totvert;
|
||||
scol= scolmain;
|
||||
while(a--) {
|
||||
if(scol[0]>1) {
|
||||
scol[1]/= scol[0];
|
||||
scol[2]/= scol[0];
|
||||
scol[3]/= scol[0];
|
||||
}
|
||||
scol+= 4;
|
||||
}
|
||||
|
||||
tface= me->mtface;
|
||||
mface= me->mface;
|
||||
mcol= (char *)me->mcol;
|
||||
for(a=me->totface; a>0; a--, mface++, mcol+=16) {
|
||||
if((tface && tface->mode & TF_SHAREDCOL) || (G.f & G_FACESELECT)==0) {
|
||||
scol= scolmain+4*mface->v1;
|
||||
mcol[1]= scol[1]; mcol[2]= scol[2]; mcol[3]= scol[3];
|
||||
scol= scolmain+4*mface->v2;
|
||||
mcol[5]= scol[1]; mcol[6]= scol[2]; mcol[7]= scol[3];
|
||||
scol= scolmain+4*mface->v3;
|
||||
mcol[9]= scol[1]; mcol[10]= scol[2]; mcol[11]= scol[3];
|
||||
if(mface->v4) {
|
||||
scol= scolmain+4*mface->v4;
|
||||
mcol[13]= scol[1]; mcol[14]= scol[2]; mcol[15]= scol[3];
|
||||
}
|
||||
}
|
||||
if(tface) tface++;
|
||||
}
|
||||
|
||||
MEM_freeN(scolmain);
|
||||
}
|
||||
|
||||
void make_vertexcol(Scene *scene, int shade) /* single ob */
|
||||
{
|
||||
Object *ob;
|
||||
Mesh *me;
|
||||
|
||||
if(scene->obedit) {
|
||||
error("Unable to perform function in Edit Mode");
|
||||
return;
|
||||
}
|
||||
|
||||
ob= OBACT;
|
||||
if(!ob || ob->id.lib) return;
|
||||
me= get_mesh(ob);
|
||||
if(me==0) return;
|
||||
|
||||
/* copies from shadedisplist to mcol */
|
||||
if(!me->mcol) {
|
||||
CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface);
|
||||
mesh_update_customdata_pointers(me);
|
||||
}
|
||||
|
||||
if(shade)
|
||||
shadeMeshMCol(scene, ob, me);
|
||||
else
|
||||
memset(me->mcol, 255, 4*sizeof(MCol)*me->totface);
|
||||
|
||||
// XXX if (me->mr) multires_load_cols(me);
|
||||
|
||||
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
||||
|
||||
}
|
||||
|
||||
static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot)
|
||||
{
|
||||
if(vp->vpaint_prev) {
|
||||
MEM_freeN(vp->vpaint_prev);
|
||||
vp->vpaint_prev= NULL;
|
||||
}
|
||||
vp->tot= tot;
|
||||
|
||||
if(mcol==NULL || tot==0) return;
|
||||
|
||||
vp->vpaint_prev= MEM_mallocN(4*sizeof(int)*tot, "vpaint_prev");
|
||||
memcpy(vp->vpaint_prev, mcol, 4*sizeof(int)*tot);
|
||||
|
||||
}
|
||||
|
||||
static void copy_wpaint_prev (VPaint *vp, MDeformVert *dverts, int dcount)
|
||||
{
|
||||
if (vp->wpaint_prev) {
|
||||
free_dverts(vp->wpaint_prev, vp->tot);
|
||||
vp->wpaint_prev= NULL;
|
||||
}
|
||||
|
||||
if(dverts && dcount) {
|
||||
|
||||
vp->wpaint_prev = MEM_mallocN (sizeof(MDeformVert)*dcount, "wpaint prev");
|
||||
vp->tot = dcount;
|
||||
copy_dverts (vp->wpaint_prev, dverts, dcount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void clear_vpaint(Scene *scene)
|
||||
{
|
||||
Mesh *me;
|
||||
Object *ob;
|
||||
unsigned int *to, paintcol;
|
||||
int a;
|
||||
|
||||
if((G.f & G_VERTEXPAINT)==0) return;
|
||||
|
||||
ob= OBACT;
|
||||
me= get_mesh(ob);
|
||||
if(!ob || ob->id.lib) return;
|
||||
|
||||
if(me==0 || me->mcol==0 || me->totface==0) return;
|
||||
|
||||
paintcol= vpaint_get_current_col(&Gvp);
|
||||
|
||||
to= (unsigned int *)me->mcol;
|
||||
a= 4*me->totface;
|
||||
while(a--) {
|
||||
*to= paintcol;
|
||||
to++;
|
||||
}
|
||||
BIF_undo_push("Clear vertex colors");
|
||||
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
||||
|
||||
}
|
||||
|
||||
void clear_vpaint_selectedfaces(Scene *scene)
|
||||
{
|
||||
Mesh *me;
|
||||
MFace *mf;
|
||||
Object *ob;
|
||||
unsigned int paintcol, *mcol;
|
||||
int i;
|
||||
|
||||
ob= OBACT;
|
||||
me= get_mesh(ob);
|
||||
if(me==0 || me->totface==0) return;
|
||||
|
||||
if(!me->mcol)
|
||||
make_vertexcol(scene, 0);
|
||||
|
||||
paintcol= vpaint_get_current_col(&Gvp);
|
||||
|
||||
mf = me->mface;
|
||||
mcol = (unsigned int*)me->mcol;
|
||||
for (i = 0; i < me->totface; i++, mf++, mcol+=4) {
|
||||
if (mf->flag & ME_FACE_SEL) {
|
||||
mcol[0] = paintcol;
|
||||
mcol[1] = paintcol;
|
||||
mcol[2] = paintcol;
|
||||
mcol[3] = paintcol;
|
||||
}
|
||||
}
|
||||
|
||||
BIF_undo_push("Clear vertex colors");
|
||||
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
||||
}
|
||||
|
||||
|
||||
/* fills in the selected faces with the current weight and vertex group */
|
||||
void clear_wpaint_selectedfaces(Scene *scene)
|
||||
{
|
||||
extern float editbutvweight;
|
||||
float paintweight= editbutvweight;
|
||||
Mesh *me;
|
||||
MFace *mface;
|
||||
Object *ob;
|
||||
MDeformWeight *dw, *uw;
|
||||
int *indexar;
|
||||
int index, vgroup;
|
||||
unsigned int faceverts[5]={0,0,0,0,0};
|
||||
unsigned char i;
|
||||
int vgroup_mirror= -1;
|
||||
|
||||
ob= OBACT;
|
||||
me= ob->data;
|
||||
if(me==0 || me->totface==0 || me->dvert==0 || !me->mface) return;
|
||||
|
||||
indexar= get_indexarray();
|
||||
for(index=0, mface=me->mface; index<me->totface; index++, mface++) {
|
||||
if((mface->flag & ME_FACE_SEL)==0)
|
||||
indexar[index]= 0;
|
||||
else
|
||||
indexar[index]= index+1;
|
||||
}
|
||||
|
||||
vgroup= ob->actdef-1;
|
||||
|
||||
/* directly copied from weight_paint, should probaby split into a seperate function */
|
||||
/* if mirror painting, find the other group */
|
||||
if(Gwp.flag & VP_MIRROR_X) {
|
||||
bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1);
|
||||
if(defgroup) {
|
||||
bDeformGroup *curdef;
|
||||
int actdef= 0;
|
||||
char name[32];
|
||||
|
||||
BLI_strncpy(name, defgroup->name, 32);
|
||||
bone_flip_name(name, 0); /* 0 = don't strip off number extensions */
|
||||
|
||||
for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++)
|
||||
if (!strcmp(curdef->name, name))
|
||||
break;
|
||||
if(curdef==NULL) {
|
||||
int olddef= ob->actdef; /* tsk, add_defgroup sets the active defgroup */
|
||||
curdef= add_defgroup_name (ob, name);
|
||||
ob->actdef= olddef;
|
||||
}
|
||||
|
||||
if(curdef && curdef!=defgroup)
|
||||
vgroup_mirror= actdef;
|
||||
}
|
||||
}
|
||||
/* end copy from weight_paint*/
|
||||
|
||||
copy_wpaint_prev(&Gwp, me->dvert, me->totvert);
|
||||
|
||||
for(index=0; index<me->totface; index++) {
|
||||
if(indexar[index] && indexar[index]<=me->totface) {
|
||||
mface= me->mface + (indexar[index]-1);
|
||||
/* just so we can loop through the verts */
|
||||
faceverts[0]= mface->v1;
|
||||
faceverts[1]= mface->v2;
|
||||
faceverts[2]= mface->v3;
|
||||
faceverts[3]= mface->v4;
|
||||
for (i=0; i<3 || faceverts[i]; i++) {
|
||||
if(!((me->dvert+faceverts[i])->flag)) {
|
||||
dw= verify_defweight(me->dvert+faceverts[i], vgroup);
|
||||
if(dw) {
|
||||
uw= verify_defweight(Gwp.wpaint_prev+faceverts[i], vgroup);
|
||||
uw->weight= dw->weight; /* set the undio weight */
|
||||
dw->weight= paintweight;
|
||||
|
||||
if(Gwp.flag & VP_MIRROR_X) { /* x mirror painting */
|
||||
int j= mesh_get_x_mirror_vert(ob, faceverts[i]);
|
||||
if(j>=0) {
|
||||
/* copy, not paint again */
|
||||
if(vgroup_mirror != -1) {
|
||||
dw= verify_defweight(me->dvert+j, vgroup_mirror);
|
||||
uw= verify_defweight(Gwp.wpaint_prev+j, vgroup_mirror);
|
||||
} else {
|
||||
dw= verify_defweight(me->dvert+j, vgroup);
|
||||
uw= verify_defweight(Gwp.wpaint_prev+j, vgroup);
|
||||
}
|
||||
uw->weight= dw->weight; /* set the undo weight */
|
||||
dw->weight= paintweight;
|
||||
}
|
||||
}
|
||||
}
|
||||
(me->dvert+faceverts[i])->flag= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
index=0;
|
||||
while (index<me->totvert) {
|
||||
(me->dvert+index)->flag= 0;
|
||||
index++;
|
||||
}
|
||||
|
||||
MEM_freeN(indexar);
|
||||
copy_wpaint_prev(&Gwp, NULL, 0);
|
||||
|
||||
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
||||
BIF_undo_push("Set vertex weight");
|
||||
}
|
||||
|
||||
|
||||
void vpaint_dogamma(Scene *scene)
|
||||
{
|
||||
Mesh *me;
|
||||
Object *ob;
|
||||
float igam, fac;
|
||||
int a, temp;
|
||||
char *cp, gamtab[256];
|
||||
|
||||
if((G.f & G_VERTEXPAINT)==0) return;
|
||||
|
||||
ob= OBACT;
|
||||
me= get_mesh(ob);
|
||||
if(me==0 || me->mcol==0 || me->totface==0) return;
|
||||
|
||||
igam= 1.0/Gvp.gamma;
|
||||
for(a=0; a<256; a++) {
|
||||
|
||||
fac= ((float)a)/255.0;
|
||||
fac= Gvp.mul*pow( fac, igam);
|
||||
|
||||
temp= 255.9*fac;
|
||||
|
||||
if(temp<=0) gamtab[a]= 0;
|
||||
else if(temp>=255) gamtab[a]= 255;
|
||||
else gamtab[a]= temp;
|
||||
}
|
||||
|
||||
a= 4*me->totface;
|
||||
cp= (char *)me->mcol;
|
||||
while(a--) {
|
||||
|
||||
cp[1]= gamtab[ cp[1] ];
|
||||
cp[2]= gamtab[ cp[2] ];
|
||||
cp[3]= gamtab[ cp[3] ];
|
||||
|
||||
cp+= 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* used for both 3d view and image window */
|
||||
void sample_vpaint(Scene *scene, ARegion *ar) /* frontbuf */
|
||||
{
|
||||
unsigned int col;
|
||||
int x, y;
|
||||
short mval[2];
|
||||
char *cp;
|
||||
|
||||
// getmouseco_areawin(mval);
|
||||
x= mval[0]; y= mval[1];
|
||||
|
||||
if(x<0 || y<0) return;
|
||||
if(x>=ar->winx || y>=ar->winy) return;
|
||||
|
||||
x+= ar->winrct.xmin;
|
||||
y+= ar->winrct.ymin;
|
||||
|
||||
glReadBuffer(GL_FRONT);
|
||||
glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
|
||||
glReadBuffer(GL_BACK);
|
||||
|
||||
cp = (char *)&col;
|
||||
|
||||
if(G.f & (G_VERTEXPAINT|G_WEIGHTPAINT)) {
|
||||
Gvp.r= cp[0]/255.0f;
|
||||
Gvp.g= cp[1]/255.0f;
|
||||
Gvp.b= cp[2]/255.0f;
|
||||
}
|
||||
else {
|
||||
Brush *brush= scene->toolsettings->imapaint.brush;
|
||||
|
||||
if(brush) {
|
||||
brush->rgb[0]= cp[0]/255.0f;
|
||||
brush->rgb[1]= cp[1]/255.0f;
|
||||
brush->rgb[2]= cp[2]/255.0f;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static unsigned int mcol_blend(unsigned int col1, unsigned int col2, int fac)
|
||||
{
|
||||
char *cp1, *cp2, *cp;
|
||||
int mfac;
|
||||
unsigned int col=0;
|
||||
|
||||
if(fac==0) return col1;
|
||||
if(fac>=255) return col2;
|
||||
|
||||
mfac= 255-fac;
|
||||
|
||||
cp1= (char *)&col1;
|
||||
cp2= (char *)&col2;
|
||||
cp= (char *)&col;
|
||||
|
||||
cp[0]= 255;
|
||||
cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
|
||||
cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
|
||||
cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
static unsigned int mcol_add(unsigned int col1, unsigned int col2, int fac)
|
||||
{
|
||||
char *cp1, *cp2, *cp;
|
||||
int temp;
|
||||
unsigned int col=0;
|
||||
|
||||
if(fac==0) return col1;
|
||||
|
||||
cp1= (char *)&col1;
|
||||
cp2= (char *)&col2;
|
||||
cp= (char *)&col;
|
||||
|
||||
cp[0]= 255;
|
||||
temp= cp1[1] + ((fac*cp2[1])/255);
|
||||
if(temp>254) cp[1]= 255; else cp[1]= temp;
|
||||
temp= cp1[2] + ((fac*cp2[2])/255);
|
||||
if(temp>254) cp[2]= 255; else cp[2]= temp;
|
||||
temp= cp1[3] + ((fac*cp2[3])/255);
|
||||
if(temp>254) cp[3]= 255; else cp[3]= temp;
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
static unsigned int mcol_sub(unsigned int col1, unsigned int col2, int fac)
|
||||
{
|
||||
char *cp1, *cp2, *cp;
|
||||
int temp;
|
||||
unsigned int col=0;
|
||||
|
||||
if(fac==0) return col1;
|
||||
|
||||
cp1= (char *)&col1;
|
||||
cp2= (char *)&col2;
|
||||
cp= (char *)&col;
|
||||
|
||||
cp[0]= 255;
|
||||
temp= cp1[1] - ((fac*cp2[1])/255);
|
||||
if(temp<0) cp[1]= 0; else cp[1]= temp;
|
||||
temp= cp1[2] - ((fac*cp2[2])/255);
|
||||
if(temp<0) cp[2]= 0; else cp[2]= temp;
|
||||
temp= cp1[3] - ((fac*cp2[3])/255);
|
||||
if(temp<0) cp[3]= 0; else cp[3]= temp;
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
static unsigned int mcol_mul(unsigned int col1, unsigned int col2, int fac)
|
||||
{
|
||||
char *cp1, *cp2, *cp;
|
||||
int mfac;
|
||||
unsigned int col=0;
|
||||
|
||||
if(fac==0) return col1;
|
||||
|
||||
mfac= 255-fac;
|
||||
|
||||
cp1= (char *)&col1;
|
||||
cp2= (char *)&col2;
|
||||
cp= (char *)&col;
|
||||
|
||||
/* first mul, then blend the fac */
|
||||
cp[0]= 255;
|
||||
cp[1]= (mfac*cp1[1] + fac*((cp2[1]*cp1[1])/255) )/255;
|
||||
cp[2]= (mfac*cp1[2] + fac*((cp2[2]*cp1[2])/255) )/255;
|
||||
cp[3]= (mfac*cp1[3] + fac*((cp2[3]*cp1[3])/255) )/255;
|
||||
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
static unsigned int mcol_lighten(unsigned int col1, unsigned int col2, int fac)
|
||||
{
|
||||
char *cp1, *cp2, *cp;
|
||||
int mfac;
|
||||
unsigned int col=0;
|
||||
|
||||
if(fac==0) return col1;
|
||||
if(fac>=255) return col2;
|
||||
|
||||
mfac= 255-fac;
|
||||
|
||||
cp1= (char *)&col1;
|
||||
cp2= (char *)&col2;
|
||||
cp= (char *)&col;
|
||||
|
||||
/* See if are lighter, if so mix, else dont do anything.
|
||||
if the paint col is darker then the original, then ignore */
|
||||
if (cp1[1]+cp1[2]+cp1[3] > cp2[1]+cp2[2]+cp2[3])
|
||||
return col1;
|
||||
|
||||
cp[0]= 255;
|
||||
cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
|
||||
cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
|
||||
cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
static unsigned int mcol_darken(unsigned int col1, unsigned int col2, int fac)
|
||||
{
|
||||
char *cp1, *cp2, *cp;
|
||||
int mfac;
|
||||
unsigned int col=0;
|
||||
|
||||
if(fac==0) return col1;
|
||||
if(fac>=255) return col2;
|
||||
|
||||
mfac= 255-fac;
|
||||
|
||||
cp1= (char *)&col1;
|
||||
cp2= (char *)&col2;
|
||||
cp= (char *)&col;
|
||||
|
||||
/* See if were darker, if so mix, else dont do anything.
|
||||
if the paint col is brighter then the original, then ignore */
|
||||
if (cp1[1]+cp1[2]+cp1[3] < cp2[1]+cp2[2]+cp2[3])
|
||||
return col1;
|
||||
|
||||
cp[0]= 255;
|
||||
cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
|
||||
cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
|
||||
cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
|
||||
return col;
|
||||
}
|
||||
|
||||
static void vpaint_blend( unsigned int *col, unsigned int *colorig, unsigned int paintcol, int alpha)
|
||||
{
|
||||
|
||||
if(Gvp.mode==VP_MIX || Gvp.mode==VP_BLUR) *col= mcol_blend( *col, paintcol, alpha);
|
||||
else if(Gvp.mode==VP_ADD) *col= mcol_add( *col, paintcol, alpha);
|
||||
else if(Gvp.mode==VP_SUB) *col= mcol_sub( *col, paintcol, alpha);
|
||||
else if(Gvp.mode==VP_MUL) *col= mcol_mul( *col, paintcol, alpha);
|
||||
else if(Gvp.mode==VP_LIGHTEN) *col= mcol_lighten( *col, paintcol, alpha);
|
||||
else if(Gvp.mode==VP_DARKEN) *col= mcol_darken( *col, paintcol, alpha);
|
||||
|
||||
/* if no spray, clip color adding with colorig & orig alpha */
|
||||
if((Gvp.flag & VP_SPRAY)==0) {
|
||||
unsigned int testcol=0, a;
|
||||
char *cp, *ct, *co;
|
||||
|
||||
alpha= (int)(255.0*Gvp.a);
|
||||
|
||||
if(Gvp.mode==VP_MIX || Gvp.mode==VP_BLUR) testcol= mcol_blend( *colorig, paintcol, alpha);
|
||||
else if(Gvp.mode==VP_ADD) testcol= mcol_add( *colorig, paintcol, alpha);
|
||||
else if(Gvp.mode==VP_SUB) testcol= mcol_sub( *colorig, paintcol, alpha);
|
||||
else if(Gvp.mode==VP_MUL) testcol= mcol_mul( *colorig, paintcol, alpha);
|
||||
else if(Gvp.mode==VP_LIGHTEN) testcol= mcol_lighten( *colorig, paintcol, alpha);
|
||||
else if(Gvp.mode==VP_DARKEN) testcol= mcol_darken( *colorig, paintcol, alpha);
|
||||
|
||||
cp= (char *)col;
|
||||
ct= (char *)&testcol;
|
||||
co= (char *)colorig;
|
||||
|
||||
for(a=0; a<4; a++) {
|
||||
if( ct[a]<co[a] ) {
|
||||
if( cp[a]<ct[a] ) cp[a]= ct[a];
|
||||
else if( cp[a]>co[a] ) cp[a]= co[a];
|
||||
}
|
||||
else {
|
||||
if( cp[a]<co[a] ) cp[a]= co[a];
|
||||
else if( cp[a]>ct[a] ) cp[a]= ct[a];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int sample_backbuf_area(ARegion *ar, int *indexar, int totface, int x, int y, float size)
|
||||
{
|
||||
unsigned int *rt;
|
||||
struct ImBuf *ibuf;
|
||||
int x1, y1, x2, y2, a, tot=0, index;
|
||||
|
||||
if(totface+4>=MAXINDEX) return 0;
|
||||
|
||||
if(size>64.0) size= 64.0;
|
||||
|
||||
x1= x-size;
|
||||
x2= x+size;
|
||||
CLAMP(x1, 0, ar->winx-1);
|
||||
CLAMP(x2, 0, ar->winx-1);
|
||||
y1= y-size;
|
||||
y2= y+size;
|
||||
CLAMP(y1, 0, ar->winy-1);
|
||||
CLAMP(y2, 0, ar->winy-1);
|
||||
|
||||
if(x1>=x2 || y1>=y2) return 0;
|
||||
|
||||
ibuf = IMB_allocImBuf(2*size + 4, 2*size + 4, 32, IB_rect, 0);
|
||||
glReadPixels(x1+ar->winrct.xmin, y1+ar->winrct.ymin, x2-x1+1, y2-y1+1, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
|
||||
glReadBuffer(GL_BACK);
|
||||
|
||||
if(ENDIAN_ORDER==B_ENDIAN) {
|
||||
IMB_convert_rgba_to_abgr(ibuf);
|
||||
}
|
||||
|
||||
rt= ibuf->rect;
|
||||
size= (y2-y1)*(x2-x1);
|
||||
if(size<=0) return 0;
|
||||
|
||||
memset(indexar, 0, sizeof(int)*totface+4); /* plus 2! first element is total, +2 was giving valgrind errors, +4 seems ok */
|
||||
|
||||
while(size--) {
|
||||
|
||||
if(*rt) {
|
||||
index= WM_framebuffer_to_index(*rt);
|
||||
if(index>0 && index<=totface)
|
||||
indexar[index] = 1;
|
||||
}
|
||||
|
||||
rt++;
|
||||
}
|
||||
|
||||
for(a=1; a<=totface; a++) {
|
||||
if(indexar[a]) indexar[tot++]= a;
|
||||
}
|
||||
|
||||
IMB_freeImBuf(ibuf);
|
||||
|
||||
return tot;
|
||||
}
|
||||
|
||||
static int calc_vp_alpha_dl(VPaint *vp, ARegion *ar, View3D *v3d, float vpimat[][3], float *vert_nor, short *mval)
|
||||
{
|
||||
float fac, dx, dy;
|
||||
int alpha;
|
||||
short vertco[2];
|
||||
|
||||
if(vp->flag & VP_SOFT) {
|
||||
project_short_noclip(ar, v3d, vert_nor, vertco);
|
||||
dx= mval[0]-vertco[0];
|
||||
dy= mval[1]-vertco[1];
|
||||
|
||||
fac= sqrt(dx*dx + dy*dy);
|
||||
if(fac > vp->size) return 0;
|
||||
if(vp->flag & VP_HARD)
|
||||
alpha= 255;
|
||||
else
|
||||
alpha= 255.0*vp->a*(1.0-fac/vp->size);
|
||||
}
|
||||
else {
|
||||
alpha= 255.0*vp->a;
|
||||
}
|
||||
|
||||
if(vp->flag & VP_NORMALS) {
|
||||
float *no= vert_nor+3;
|
||||
|
||||
/* transpose ! */
|
||||
fac= vpimat[2][0]*no[0]+vpimat[2][1]*no[1]+vpimat[2][2]*no[2];
|
||||
if(fac>0.0) {
|
||||
dx= vpimat[0][0]*no[0]+vpimat[0][1]*no[1]+vpimat[0][2]*no[2];
|
||||
dy= vpimat[1][0]*no[0]+vpimat[1][1]*no[1]+vpimat[1][2]*no[2];
|
||||
|
||||
alpha*= fac/sqrt(dx*dx + dy*dy + fac*fac);
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
return alpha;
|
||||
}
|
||||
|
||||
static void wpaint_blend(MDeformWeight *dw, MDeformWeight *uw, float alpha, float paintval)
|
||||
{
|
||||
|
||||
if(dw==NULL || uw==NULL) return;
|
||||
|
||||
if(Gwp.mode==VP_MIX || Gwp.mode==VP_BLUR)
|
||||
dw->weight = paintval*alpha + dw->weight*(1.0-alpha);
|
||||
else if(Gwp.mode==VP_ADD)
|
||||
dw->weight += paintval*alpha;
|
||||
else if(Gwp.mode==VP_SUB)
|
||||
dw->weight -= paintval*alpha;
|
||||
else if(Gwp.mode==VP_MUL)
|
||||
/* first mul, then blend the fac */
|
||||
dw->weight = ((1.0-alpha) + alpha*paintval)*dw->weight;
|
||||
else if(Gwp.mode==VP_LIGHTEN) {
|
||||
if (dw->weight < paintval)
|
||||
dw->weight = paintval*alpha + dw->weight*(1.0-alpha);
|
||||
} else if(Gwp.mode==VP_DARKEN) {
|
||||
if (dw->weight > paintval)
|
||||
dw->weight = paintval*alpha + dw->weight*(1.0-alpha);
|
||||
}
|
||||
CLAMP(dw->weight, 0.0f, 1.0f);
|
||||
|
||||
/* if no spray, clip result with orig weight & orig alpha */
|
||||
if((Gwp.flag & VP_SPRAY)==0) {
|
||||
float testw=0.0f;
|
||||
|
||||
alpha= Gwp.a;
|
||||
if(Gwp.mode==VP_MIX || Gwp.mode==VP_BLUR)
|
||||
testw = paintval*alpha + uw->weight*(1.0-alpha);
|
||||
else if(Gwp.mode==VP_ADD)
|
||||
testw = uw->weight + paintval*alpha;
|
||||
else if(Gwp.mode==VP_SUB)
|
||||
testw = uw->weight - paintval*alpha;
|
||||
else if(Gwp.mode==VP_MUL)
|
||||
/* first mul, then blend the fac */
|
||||
testw = ((1.0-alpha) + alpha*paintval)*uw->weight;
|
||||
else if(Gwp.mode==VP_LIGHTEN) {
|
||||
if (uw->weight < paintval)
|
||||
testw = paintval*alpha + uw->weight*(1.0-alpha);
|
||||
else
|
||||
testw = uw->weight;
|
||||
} else if(Gwp.mode==VP_DARKEN) {
|
||||
if (uw->weight > paintval)
|
||||
testw = paintval*alpha + uw->weight*(1.0-alpha);
|
||||
else
|
||||
testw = uw->weight;
|
||||
}
|
||||
CLAMP(testw, 0.0f, 1.0f);
|
||||
|
||||
if( testw<uw->weight ) {
|
||||
if(dw->weight < testw) dw->weight= testw;
|
||||
else if(dw->weight > uw->weight) dw->weight= uw->weight;
|
||||
}
|
||||
else {
|
||||
if(dw->weight > testw) dw->weight= testw;
|
||||
else if(dw->weight < uw->weight) dw->weight= uw->weight;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------- */
|
||||
|
||||
/* used for 3d view, on active object, assumes me->dvert exists */
|
||||
/* if mode==1: */
|
||||
/* samples cursor location, and gives menu with vertex groups to activate */
|
||||
/* else */
|
||||
/* sets editbutvweight to the closest weight value to vertex */
|
||||
/* note: we cant sample frontbuf, weight colors are interpolated too unpredictable */
|
||||
static void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode)
|
||||
{
|
||||
ViewContext vc;
|
||||
Object *ob= OBACT;
|
||||
Mesh *me= get_mesh(ob);
|
||||
int index;
|
||||
short mval[2], sco[2];
|
||||
|
||||
if (!me) return;
|
||||
|
||||
// getmouseco_areawin(mval);
|
||||
index= view3d_sample_backbuf(&vc, mval[0], mval[1]);
|
||||
|
||||
if(index && index<=me->totface) {
|
||||
MFace *mface;
|
||||
|
||||
mface= ((MFace *)me->mface) + index-1;
|
||||
|
||||
if(mode==1) { /* sampe which groups are in here */
|
||||
MDeformVert *dv;
|
||||
int a, totgroup;
|
||||
|
||||
totgroup= BLI_countlist(&ob->defbase);
|
||||
if(totgroup) {
|
||||
int totmenu=0;
|
||||
int *groups=MEM_callocN(totgroup*sizeof(int), "groups");
|
||||
|
||||
dv= me->dvert+mface->v1;
|
||||
for(a=0; a<dv->totweight; a++) {
|
||||
if (dv->dw[a].def_nr<totgroup)
|
||||
groups[dv->dw[a].def_nr]= 1;
|
||||
}
|
||||
dv= me->dvert+mface->v2;
|
||||
for(a=0; a<dv->totweight; a++) {
|
||||
if (dv->dw[a].def_nr<totgroup)
|
||||
groups[dv->dw[a].def_nr]= 1;
|
||||
}
|
||||
dv= me->dvert+mface->v3;
|
||||
for(a=0; a<dv->totweight; a++) {
|
||||
if (dv->dw[a].def_nr<totgroup)
|
||||
groups[dv->dw[a].def_nr]= 1;
|
||||
}
|
||||
if(mface->v4) {
|
||||
dv= me->dvert+mface->v4;
|
||||
for(a=0; a<dv->totweight; a++) {
|
||||
if (dv->dw[a].def_nr<totgroup)
|
||||
groups[dv->dw[a].def_nr]= 1;
|
||||
}
|
||||
}
|
||||
for(a=0; a<totgroup; a++)
|
||||
if(groups[a]) totmenu++;
|
||||
|
||||
if(totmenu==0) {
|
||||
//notice("No Vertex Group Selected");
|
||||
}
|
||||
else {
|
||||
bDeformGroup *dg;
|
||||
short val;
|
||||
char item[40], *str= MEM_mallocN(40*totmenu+40, "menu");
|
||||
|
||||
strcpy(str, "Vertex Groups %t");
|
||||
for(a=0, dg=ob->defbase.first; dg && a<totgroup; a++, dg= dg->next) {
|
||||
if(groups[a]) {
|
||||
sprintf(item, "|%s %%x%d", dg->name, a);
|
||||
strcat(str, item);
|
||||
}
|
||||
}
|
||||
|
||||
val= 0; // XXX pupmenu(str);
|
||||
if(val>=0) {
|
||||
ob->actdef= val+1;
|
||||
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
||||
}
|
||||
MEM_freeN(str);
|
||||
}
|
||||
MEM_freeN(groups);
|
||||
}
|
||||
// else notice("No Vertex Groups in Object");
|
||||
}
|
||||
else {
|
||||
DerivedMesh *dm;
|
||||
MDeformWeight *dw;
|
||||
extern float editbutvweight;
|
||||
float w1, w2, w3, w4, co[3], fac;
|
||||
|
||||
dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
|
||||
if(dm->getVertCo==NULL) {
|
||||
//notice("Not supported yet");
|
||||
}
|
||||
else {
|
||||
/* calc 3 or 4 corner weights */
|
||||
dm->getVertCo(dm, mface->v1, co);
|
||||
project_short_noclip(ar, v3d, co, sco);
|
||||
w1= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
|
||||
|
||||
dm->getVertCo(dm, mface->v2, co);
|
||||
project_short_noclip(ar, v3d, co, sco);
|
||||
w2= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
|
||||
|
||||
dm->getVertCo(dm, mface->v3, co);
|
||||
project_short_noclip(ar, v3d, co, sco);
|
||||
w3= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
|
||||
|
||||
if(mface->v4) {
|
||||
dm->getVertCo(dm, mface->v4, co);
|
||||
project_short_noclip(ar, v3d, co, sco);
|
||||
w4= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
|
||||
}
|
||||
else w4= 1.0e10;
|
||||
|
||||
fac= MIN4(w1, w2, w3, w4);
|
||||
if(w1==fac) {
|
||||
dw= get_defweight(me->dvert+mface->v1, ob->actdef-1);
|
||||
if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f;
|
||||
}
|
||||
else if(w2==fac) {
|
||||
dw= get_defweight(me->dvert+mface->v2, ob->actdef-1);
|
||||
if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f;
|
||||
}
|
||||
else if(w3==fac) {
|
||||
dw= get_defweight(me->dvert+mface->v3, ob->actdef-1);
|
||||
if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f;
|
||||
}
|
||||
else if(w4==fac) {
|
||||
if(mface->v4) {
|
||||
dw= get_defweight(me->dvert+mface->v4, ob->actdef-1);
|
||||
if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
dm->release(dm);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void do_weight_paint_vertex(Object *ob, int index, int alpha, float paintweight, int vgroup_mirror)
|
||||
{
|
||||
Mesh *me= ob->data;
|
||||
MDeformWeight *dw, *uw;
|
||||
int vgroup= ob->actdef-1;
|
||||
|
||||
if(Gwp.flag & VP_ONLYVGROUP) {
|
||||
dw= get_defweight(me->dvert+index, vgroup);
|
||||
uw= get_defweight(Gwp.wpaint_prev+index, vgroup);
|
||||
}
|
||||
else {
|
||||
dw= verify_defweight(me->dvert+index, vgroup);
|
||||
uw= verify_defweight(Gwp.wpaint_prev+index, vgroup);
|
||||
}
|
||||
if(dw==NULL || uw==NULL)
|
||||
return;
|
||||
|
||||
wpaint_blend(dw, uw, (float)alpha/255.0, paintweight);
|
||||
|
||||
if(Gwp.flag & VP_MIRROR_X) { /* x mirror painting */
|
||||
int j= mesh_get_x_mirror_vert(ob, index);
|
||||
if(j>=0) {
|
||||
/* copy, not paint again */
|
||||
if(vgroup_mirror != -1)
|
||||
uw= verify_defweight(me->dvert+j, vgroup_mirror);
|
||||
else
|
||||
uw= verify_defweight(me->dvert+j, vgroup);
|
||||
|
||||
uw->weight= dw->weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void weight_paint(Scene *scene, ARegion *ar, View3D *v3d)
|
||||
{
|
||||
ViewContext vc;
|
||||
float editbutvweight; // XXX
|
||||
Object *ob;
|
||||
Mesh *me;
|
||||
MFace *mface;
|
||||
float mat[4][4], imat[4][4], paintweight, *vertexcosnos;
|
||||
float vpimat[3][3];
|
||||
int *indexar, index, totindex, alpha, totw;
|
||||
int vgroup_mirror= -1;
|
||||
short mval[2], mvalo[2], firsttime=1;
|
||||
|
||||
if((G.f & G_WEIGHTPAINT)==0) return;
|
||||
if(scene->obedit) return;
|
||||
// XXX if(multires_level1_test()) return;
|
||||
|
||||
ob= OBACT;
|
||||
if(!ob || ob->id.lib) return;
|
||||
|
||||
me= get_mesh(ob);
|
||||
if(me==NULL || me->totface==0) return;
|
||||
|
||||
/* if nothing was added yet, we make dverts and a vertex deform group */
|
||||
// if (!me->dvert)
|
||||
// create_dverts(&me->id);
|
||||
|
||||
// if(qual & LR_CTRLKEY) {
|
||||
sample_wpaint(scene, ar, v3d, 0);
|
||||
// return;
|
||||
// }
|
||||
// if(qual & LR_SHIFTKEY) {
|
||||
// sample_wpaint(scene, ar, v3d, 1);
|
||||
// return;
|
||||
// }
|
||||
|
||||
/* ALLOCATIONS! no return after this line */
|
||||
/* painting on subsurfs should give correct points too, this returns me->totvert amount */
|
||||
vertexcosnos= mesh_get_mapped_verts_nors(scene, ob);
|
||||
indexar= get_indexarray();
|
||||
copy_wpaint_prev(&Gwp, me->dvert, me->totvert);
|
||||
|
||||
/* this happens on a Bone select, when no vgroup existed yet */
|
||||
if(ob->actdef<=0) {
|
||||
Object *modob;
|
||||
if((modob = modifiers_isDeformedByArmature(ob))) {
|
||||
bPoseChannel *pchan;
|
||||
for(pchan= modob->pose->chanbase.first; pchan; pchan= pchan->next)
|
||||
if(pchan->bone->flag & SELECT)
|
||||
break;
|
||||
if(pchan) {
|
||||
bDeformGroup *dg= get_named_vertexgroup(ob, pchan->name);
|
||||
if(dg==NULL)
|
||||
dg= add_defgroup_name(ob, pchan->name); /* sets actdef */
|
||||
else
|
||||
ob->actdef= get_defgroup_num(ob, dg);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ob->defbase.first==NULL) {
|
||||
add_defgroup(ob);
|
||||
}
|
||||
|
||||
if(ob->lay & v3d->lay); else error("Active object is not in this layer");
|
||||
|
||||
// XXX persp(PERSP_VIEW);
|
||||
/* imat for normals */
|
||||
Mat4MulMat4(mat, ob->obmat, v3d->viewmat);
|
||||
Mat4Invert(imat, mat);
|
||||
Mat3CpyMat4(vpimat, imat);
|
||||
|
||||
/* load projection matrix */
|
||||
wmMultMatrix(ob->obmat);
|
||||
wmGetSingleMatrix(mat);
|
||||
wmLoadMatrix(v3d->viewmat);
|
||||
|
||||
// getmouseco_areawin(mvalo);
|
||||
|
||||
// getmouseco_areawin(mval);
|
||||
mvalo[0]= mval[0];
|
||||
mvalo[1]= mval[1];
|
||||
|
||||
/* if mirror painting, find the other group */
|
||||
if(Gwp.flag & VP_MIRROR_X) {
|
||||
bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1);
|
||||
if(defgroup) {
|
||||
bDeformGroup *curdef;
|
||||
int actdef= 0;
|
||||
char name[32];
|
||||
|
||||
BLI_strncpy(name, defgroup->name, 32);
|
||||
bone_flip_name(name, 0); /* 0 = don't strip off number extensions */
|
||||
|
||||
for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++)
|
||||
if (!strcmp(curdef->name, name))
|
||||
break;
|
||||
if(curdef==NULL) {
|
||||
int olddef= ob->actdef; /* tsk, add_defgroup sets the active defgroup */
|
||||
curdef= add_defgroup_name (ob, name);
|
||||
ob->actdef= olddef;
|
||||
}
|
||||
|
||||
if(curdef && curdef!=defgroup)
|
||||
vgroup_mirror= actdef;
|
||||
}
|
||||
}
|
||||
|
||||
while (get_mbut() & 0) {
|
||||
// getmouseco_areawin(mval);
|
||||
|
||||
if(firsttime || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
|
||||
firsttime= 0;
|
||||
|
||||
/* which faces are involved */
|
||||
if(Gwp.flag & VP_AREA) {
|
||||
totindex= sample_backbuf_area(ar, indexar, me->totface, mval[0], mval[1], Gwp.size);
|
||||
}
|
||||
else {
|
||||
indexar[0]= view3d_sample_backbuf(&vc, mval[0], mval[1]);
|
||||
if(indexar[0]) totindex= 1;
|
||||
else totindex= 0;
|
||||
}
|
||||
|
||||
MTC_Mat4SwapMat4(v3d->persmat, mat);
|
||||
|
||||
if(Gwp.flag & VP_COLINDEX) {
|
||||
for(index=0; index<totindex; index++) {
|
||||
if(indexar[index] && indexar[index]<=me->totface) {
|
||||
|
||||
mface= ((MFace *)me->mface) + (indexar[index]-1);
|
||||
|
||||
if(mface->mat_nr!=ob->actcol-1) {
|
||||
indexar[index]= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if((G.f & G_FACESELECT) && me->mface) {
|
||||
for(index=0; index<totindex; index++) {
|
||||
if(indexar[index] && indexar[index]<=me->totface) {
|
||||
|
||||
mface= ((MFace *)me->mface) + (indexar[index]-1);
|
||||
|
||||
if((mface->flag & ME_FACE_SEL)==0) {
|
||||
indexar[index]= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* make sure each vertex gets treated only once */
|
||||
/* and calculate filter weight */
|
||||
totw= 0;
|
||||
if(Gwp.mode==VP_BLUR)
|
||||
paintweight= 0.0f;
|
||||
else
|
||||
paintweight= editbutvweight;
|
||||
|
||||
for(index=0; index<totindex; index++) {
|
||||
if(indexar[index] && indexar[index]<=me->totface) {
|
||||
mface= me->mface + (indexar[index]-1);
|
||||
|
||||
(me->dvert+mface->v1)->flag= 1;
|
||||
(me->dvert+mface->v2)->flag= 1;
|
||||
(me->dvert+mface->v3)->flag= 1;
|
||||
if(mface->v4) (me->dvert+mface->v4)->flag= 1;
|
||||
|
||||
if(Gwp.mode==VP_BLUR) {
|
||||
MDeformWeight *dw, *(*dw_func)(MDeformVert *, int) = verify_defweight;
|
||||
|
||||
if(Gwp.flag & VP_ONLYVGROUP)
|
||||
dw_func= get_defweight;
|
||||
|
||||
dw= dw_func(me->dvert+mface->v1, ob->actdef-1);
|
||||
if(dw) {paintweight+= dw->weight; totw++;}
|
||||
dw= dw_func(me->dvert+mface->v2, ob->actdef-1);
|
||||
if(dw) {paintweight+= dw->weight; totw++;}
|
||||
dw= dw_func(me->dvert+mface->v3, ob->actdef-1);
|
||||
if(dw) {paintweight+= dw->weight; totw++;}
|
||||
if(mface->v4) {
|
||||
dw= dw_func(me->dvert+mface->v4, ob->actdef-1);
|
||||
if(dw) {paintweight+= dw->weight; totw++;}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(Gwp.mode==VP_BLUR)
|
||||
paintweight/= (float)totw;
|
||||
|
||||
for(index=0; index<totindex; index++) {
|
||||
|
||||
if(indexar[index] && indexar[index]<=me->totface) {
|
||||
mface= me->mface + (indexar[index]-1);
|
||||
|
||||
if((me->dvert+mface->v1)->flag) {
|
||||
alpha= calc_vp_alpha_dl(&Gwp, ar, v3d, vpimat, vertexcosnos+6*mface->v1, mval);
|
||||
if(alpha) {
|
||||
do_weight_paint_vertex(ob, mface->v1, alpha, paintweight, vgroup_mirror);
|
||||
}
|
||||
(me->dvert+mface->v1)->flag= 0;
|
||||
}
|
||||
|
||||
if((me->dvert+mface->v2)->flag) {
|
||||
alpha= calc_vp_alpha_dl(&Gwp, ar, v3d, vpimat, vertexcosnos+6*mface->v2, mval);
|
||||
if(alpha) {
|
||||
do_weight_paint_vertex(ob, mface->v2, alpha, paintweight, vgroup_mirror);
|
||||
}
|
||||
(me->dvert+mface->v2)->flag= 0;
|
||||
}
|
||||
|
||||
if((me->dvert+mface->v3)->flag) {
|
||||
alpha= calc_vp_alpha_dl(&Gwp, ar, v3d, vpimat, vertexcosnos+6*mface->v3, mval);
|
||||
if(alpha) {
|
||||
do_weight_paint_vertex(ob, mface->v3, alpha, paintweight, vgroup_mirror);
|
||||
}
|
||||
(me->dvert+mface->v3)->flag= 0;
|
||||
}
|
||||
|
||||
if((me->dvert+mface->v4)->flag) {
|
||||
if(mface->v4) {
|
||||
alpha= calc_vp_alpha_dl(&Gwp, ar, v3d, vpimat, vertexcosnos+6*mface->v4, mval);
|
||||
if(alpha) {
|
||||
do_weight_paint_vertex(ob, mface->v4, alpha, paintweight, vgroup_mirror);
|
||||
}
|
||||
(me->dvert+mface->v4)->flag= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MTC_Mat4SwapMat4(v3d->persmat, mat);
|
||||
|
||||
}
|
||||
|
||||
if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
|
||||
|
||||
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
||||
|
||||
if(Gwp.flag & (VP_AREA|VP_SOFT)) {
|
||||
/* draw circle in backbuf! */
|
||||
// XXX persp(PERSP_WIN);
|
||||
// XXX fdrawXORcirc((float)mval[0], (float)mval[1], Gwp.size);
|
||||
// XXX persp(PERSP_VIEW);
|
||||
}
|
||||
|
||||
mvalo[0]= mval[0];
|
||||
mvalo[1]= mval[1];
|
||||
}
|
||||
}
|
||||
|
||||
if(vertexcosnos)
|
||||
MEM_freeN(vertexcosnos);
|
||||
MEM_freeN(indexar);
|
||||
copy_wpaint_prev(&Gwp, NULL, 0);
|
||||
|
||||
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
||||
|
||||
/* and particles too */
|
||||
if(ob->particlesystem.first) {
|
||||
ParticleSystem *psys;
|
||||
int i;
|
||||
|
||||
psys= ob->particlesystem.first;
|
||||
while(psys) {
|
||||
for(i=0; i<PSYS_TOT_VG; i++) {
|
||||
if(psys->vgroup[i]==ob->actdef) {
|
||||
psys->recalc |= PSYS_RECALC_HAIR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
psys= psys->next;
|
||||
}
|
||||
}
|
||||
|
||||
BIF_undo_push("Weight Paint");
|
||||
}
|
||||
|
||||
void vertex_paint(Scene *scene, ARegion *ar, View3D *v3d)
|
||||
{
|
||||
ViewContext vc;
|
||||
Object *ob;
|
||||
Mesh *me;
|
||||
MFace *mface;
|
||||
float mat[4][4], imat[4][4], *vertexcosnos;
|
||||
float vpimat[3][3];
|
||||
unsigned int paintcol=0, *mcol, *mcolorig, fcol1, fcol2;
|
||||
int *indexar, index, alpha, totindex;
|
||||
short mval[2], mvalo[2], firsttime=1;
|
||||
|
||||
if((G.f & G_VERTEXPAINT)==0) return;
|
||||
if(scene->obedit) return;
|
||||
|
||||
ob= OBACT;
|
||||
if(!ob || ob->id.lib) return;
|
||||
|
||||
me= get_mesh(ob);
|
||||
if(me==NULL || me->totface==0) return;
|
||||
if(ob->lay & v3d->lay); else error("Active object is not in this layer");
|
||||
|
||||
if(me->mcol==NULL) make_vertexcol(scene, 0);
|
||||
|
||||
if(me->mcol==NULL) return;
|
||||
|
||||
/* ALLOCATIONS! No return after his line */
|
||||
|
||||
/* painting on subsurfs should give correct points too, this returns me->totvert amount */
|
||||
vertexcosnos= mesh_get_mapped_verts_nors(scene, ob);
|
||||
indexar= get_indexarray();
|
||||
copy_vpaint_prev(&Gvp, (unsigned int *)me->mcol, me->totface);
|
||||
|
||||
/* opengl/matrix stuff */
|
||||
// XXX persp(PERSP_VIEW);
|
||||
/* imat for normals */
|
||||
Mat4MulMat4(mat, ob->obmat, v3d->viewmat);
|
||||
Mat4Invert(imat, mat);
|
||||
Mat3CpyMat4(vpimat, imat);
|
||||
|
||||
/* load projection matrix */
|
||||
wmMultMatrix(ob->obmat);
|
||||
wmGetSingleMatrix(mat);
|
||||
wmLoadMatrix(v3d->viewmat);
|
||||
|
||||
paintcol= vpaint_get_current_col(&Gvp);
|
||||
|
||||
// getmouseco_areawin(mvalo);
|
||||
|
||||
// getmouseco_areawin(mval);
|
||||
mvalo[0]= mval[0];
|
||||
mvalo[1]= mval[1];
|
||||
|
||||
while (get_mbut() & 0) {
|
||||
// getmouseco_areawin(mval);
|
||||
|
||||
if(firsttime || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
|
||||
|
||||
firsttime= 0;
|
||||
|
||||
/* which faces are involved */
|
||||
if(Gvp.flag & VP_AREA) {
|
||||
totindex= sample_backbuf_area(ar, indexar, me->totface, mval[0], mval[1], Gvp.size);
|
||||
}
|
||||
else {
|
||||
indexar[0]= view3d_sample_backbuf(&vc, mval[0], mval[1]);
|
||||
if(indexar[0]) totindex= 1;
|
||||
else totindex= 0;
|
||||
}
|
||||
|
||||
MTC_Mat4SwapMat4(v3d->persmat, mat);
|
||||
|
||||
if(Gvp.flag & VP_COLINDEX) {
|
||||
for(index=0; index<totindex; index++) {
|
||||
if(indexar[index] && indexar[index]<=me->totface) {
|
||||
|
||||
mface= ((MFace *)me->mface) + (indexar[index]-1);
|
||||
|
||||
if(mface->mat_nr!=ob->actcol-1) {
|
||||
indexar[index]= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if((G.f & G_FACESELECT) && me->mface) {
|
||||
for(index=0; index<totindex; index++) {
|
||||
if(indexar[index] && indexar[index]<=me->totface) {
|
||||
mface= ((MFace *)me->mface) + (indexar[index]-1);
|
||||
|
||||
if((mface->flag & ME_FACE_SEL)==0)
|
||||
indexar[index]= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(index=0; index<totindex; index++) {
|
||||
|
||||
if(indexar[index] && indexar[index]<=me->totface) {
|
||||
|
||||
mface= ((MFace *)me->mface) + (indexar[index]-1);
|
||||
mcol= ( (unsigned int *)me->mcol) + 4*(indexar[index]-1);
|
||||
mcolorig= ( (unsigned int *)Gvp.vpaint_prev) + 4*(indexar[index]-1);
|
||||
|
||||
if(Gvp.mode==VP_BLUR) {
|
||||
fcol1= mcol_blend( mcol[0], mcol[1], 128);
|
||||
if(mface->v4) {
|
||||
fcol2= mcol_blend( mcol[2], mcol[3], 128);
|
||||
paintcol= mcol_blend( fcol1, fcol2, 128);
|
||||
}
|
||||
else {
|
||||
paintcol= mcol_blend( mcol[2], fcol1, 170);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
alpha= calc_vp_alpha_dl(&Gvp, ar, v3d, vpimat, vertexcosnos+6*mface->v1, mval);
|
||||
if(alpha) vpaint_blend( mcol, mcolorig, paintcol, alpha);
|
||||
|
||||
alpha= calc_vp_alpha_dl(&Gvp, ar, v3d, vpimat, vertexcosnos+6*mface->v2, mval);
|
||||
if(alpha) vpaint_blend( mcol+1, mcolorig+1, paintcol, alpha);
|
||||
|
||||
alpha= calc_vp_alpha_dl(&Gvp, ar, v3d, vpimat, vertexcosnos+6*mface->v3, mval);
|
||||
if(alpha) vpaint_blend( mcol+2, mcolorig+2, paintcol, alpha);
|
||||
|
||||
if(mface->v4) {
|
||||
alpha= calc_vp_alpha_dl(&Gvp, ar, v3d, vpimat, vertexcosnos+6*mface->v4, mval);
|
||||
if(alpha) vpaint_blend( mcol+3, mcolorig+3, paintcol, alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MTC_Mat4SwapMat4(v3d->persmat, mat);
|
||||
|
||||
do_shared_vertexcol(me);
|
||||
|
||||
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
||||
|
||||
if(Gvp.flag & (VP_AREA|VP_SOFT)) {
|
||||
/* draw circle in backbuf! */
|
||||
// XXX persp(PERSP_WIN);
|
||||
// fdrawXORcirc((float)mval[0], (float)mval[1], Gvp.size);
|
||||
// persp(PERSP_VIEW);
|
||||
}
|
||||
|
||||
mvalo[0]= mval[0];
|
||||
mvalo[1]= mval[1];
|
||||
}
|
||||
}
|
||||
|
||||
if(vertexcosnos)
|
||||
MEM_freeN(vertexcosnos);
|
||||
MEM_freeN(indexar);
|
||||
|
||||
/* frees prev buffer */
|
||||
copy_vpaint_prev(&Gvp, NULL, 0);
|
||||
|
||||
BIF_undo_push("Vertex Paint");
|
||||
|
||||
}
|
||||
|
||||
void set_wpaint(Scene *scene) /* toggle */
|
||||
{
|
||||
Object *ob;
|
||||
Mesh *me;
|
||||
|
||||
ob= OBACT;
|
||||
if(!ob || ob->id.lib) return;
|
||||
me= get_mesh(ob);
|
||||
|
||||
if(me && me->totface>=MAXINDEX) {
|
||||
error("Maximum number of faces: %d", MAXINDEX-1);
|
||||
G.f &= ~G_WEIGHTPAINT;
|
||||
return;
|
||||
}
|
||||
|
||||
if(G.f & G_WEIGHTPAINT) G.f &= ~G_WEIGHTPAINT;
|
||||
else G.f |= G_WEIGHTPAINT;
|
||||
|
||||
|
||||
/* Weightpaint works by overriding colors in mesh,
|
||||
* so need to make sure we recalc on enter and
|
||||
* exit (exit needs doing regardless because we
|
||||
* should redeform).
|
||||
*/
|
||||
if (me) {
|
||||
DAG_object_flush_update(scene, OBACT, OB_RECALC_DATA);
|
||||
}
|
||||
|
||||
if(G.f & G_WEIGHTPAINT) {
|
||||
Object *par;
|
||||
|
||||
mesh_octree_table(ob, NULL, NULL, 's');
|
||||
|
||||
/* verify if active weight group is also active bone */
|
||||
par= modifiers_isDeformedByArmature(ob);
|
||||
if(par && (par->flag & OB_POSEMODE)) {
|
||||
bPoseChannel *pchan;
|
||||
for(pchan= par->pose->chanbase.first; pchan; pchan= pchan->next)
|
||||
if(pchan->bone->flag & BONE_ACTIVE)
|
||||
break;
|
||||
// if(pchan)
|
||||
// XXX vertexgroup_select_by_name(ob, pchan->name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
mesh_octree_table(ob, NULL, NULL, 'e');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void set_vpaint(Scene *scene) /* toggle */
|
||||
{
|
||||
Object *ob;
|
||||
Mesh *me;
|
||||
|
||||
ob= OBACT;
|
||||
if(!ob || object_data_is_libdata(ob)) {
|
||||
G.f &= ~G_VERTEXPAINT;
|
||||
return;
|
||||
}
|
||||
|
||||
me= get_mesh(ob);
|
||||
|
||||
if(me && me->totface>=MAXINDEX) {
|
||||
error("Maximum number of faces: %d", MAXINDEX-1);
|
||||
G.f &= ~G_VERTEXPAINT;
|
||||
return;
|
||||
}
|
||||
|
||||
if(me && me->mcol==NULL) make_vertexcol(scene, 0);
|
||||
|
||||
if(G.f & G_VERTEXPAINT){
|
||||
G.f &= ~G_VERTEXPAINT;
|
||||
}
|
||||
else {
|
||||
G.f |= G_VERTEXPAINT;
|
||||
/* Turn off weight painting */
|
||||
if (G.f & G_WEIGHTPAINT)
|
||||
set_wpaint(scene);
|
||||
}
|
||||
|
||||
if (me)
|
||||
/* update modifier stack for mapping requirements */
|
||||
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user