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:
Diffstat (limited to 'source/blender/src/sculptmode.c')
-rw-r--r--source/blender/src/sculptmode.c2267
1 files changed, 0 insertions, 2267 deletions
diff --git a/source/blender/src/sculptmode.c b/source/blender/src/sculptmode.c
deleted file mode 100644
index 010bf6f746c..00000000000
--- a/source/blender/src/sculptmode.c
+++ /dev/null
@@ -1,2267 +0,0 @@
-/*
- * $Id$
- *
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * The Original Code is Copyright (C) 2006 by Nicholas Bishop
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- *
- * Implements the Sculpt Mode tools
- *
- * BDR_sculptmode.h
- *
- */
-
-#include "GHOST_Types.h"
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_arithb.h"
-#include "BLI_blenlib.h"
-#include "BLI_dynstr.h"
-
-#include "DNA_armature_types.h"
-#include "DNA_brush_types.h"
-#include "DNA_image_types.h"
-#include "DNA_key_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_object_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_texture_types.h"
-#include "DNA_view3d_types.h"
-#include "DNA_userdef_types.h"
-#include "DNA_color_types.h"
-
-#include "BKE_customdata.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_depsgraph.h"
-#include "BKE_global.h"
-#include "BKE_image.h"
-#include "BKE_key.h"
-#include "BKE_library.h"
-#include "BKE_main.h"
-#include "BKE_mesh.h"
-#include "BKE_modifier.h"
-#include "BKE_texture.h"
-#include "BKE_utildefines.h"
-#include "BKE_colortools.h"
-
-#include "BIF_editkey.h"
-#include "BIF_editview.h"
-#include "BIF_glutil.h"
-#include "BIF_gl.h"
-#include "BIF_interface.h"
-#include "BIF_mywindow.h"
-#include "BIF_resources.h"
-#include "BIF_screen.h"
-#include "BIF_space.h"
-#include "BIF_toolbox.h"
-
-#include "BDR_drawobject.h"
-#include "BDR_sculptmode.h"
-
-#include "BSE_drawview.h"
-#include "BSE_edit.h"
-#include "BSE_view.h"
-
-#include "IMB_imbuf_types.h"
-
-#include "blendef.h"
-#include "multires.h"
-#include "mydevice.h"
-
-#include "RE_render_ext.h"
-#include "RE_shader_ext.h" /*for multitex_ext*/
-
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* Number of vertices to average in order to determine the flatten distance */
-#define FLATTEN_SAMPLE_SIZE 10
-
-/* ===== STRUCTS =====
- *
- */
-
-/* Used by vertex_users to store face indices in a list */
-typedef struct IndexNode {
- struct IndexNode* next,* prev;
- int Index;
-} IndexNode;
-
-
-/* ActiveData stores an Index into the mvert array of Mesh, plus Fade, which
- stores how far the vertex is from the brush center, scaled to the range [0,1]. */
-typedef struct ActiveData {
- struct ActiveData *next, *prev;
- unsigned int Index;
- float Fade;
- float dist;
-} ActiveData;
-
-typedef struct GrabData {
- char firsttime;
- ListBase active_verts[8];
- unsigned char index;
- vec3f delta, delta_symm;
- float depth;
-} GrabData;
-
-typedef struct EditData {
- vec3f center;
- float size;
- char flip;
- short mouse[2];
-
- /* Adjust brush strength along each axis
- to adjust for object scaling */
- float scale[3];
-
- /* View normals */
- vec3f up, right, out;
-
- GrabData *grabdata;
- float *layer_disps;
- vec3f *layer_store;
-
- char clip[3];
- float cliptol[3];
-
- char symm;
-} EditData;
-
-typedef struct RectNode {
- struct RectNode *next, *prev;
- rcti r;
-} RectNode;
-
-/* Used to store to 2D screen coordinates of each vertex in the mesh. */
-typedef struct ProjVert {
- short co[2];
-
- /* Used to mark whether a vertex is inside a rough bounding box
- containing the brush. */
- char inside;
-} ProjVert;
-
-static ProjVert *projverts= NULL;
-static Object *active_ob= NULL;
-
-SculptData *sculpt_data(void)
-{
- return &G.scene->sculptdata;
-}
-
-void sculpt_init_session(void);
-void init_editdata(EditData *e, short *, short *);
-void sculpt_undo_push(const short);
-
-SculptSession *sculpt_session(void)
-{
- if(!sculpt_data()->session)
- sculpt_init_session();
- return sculpt_data()->session;
-}
-
-/* ===== MEMORY =====
- *
- * Allocate/initialize/free data
- */
-
-// Default curve approximates 0.5 * (cos(pi * x) + 1), with 0 <= x <= 1;
-void sculpt_reset_curve(SculptData *sd)
-{
- CurveMap *cm = NULL;
-
- if(!sd->cumap)
- sd->cumap = curvemapping_add(1, 0, 0, 1, 1);
-
- cm = sd->cumap->cm;
-
- if(cm->curve)
- MEM_freeN(cm->curve);
- cm->curve= MEM_callocN(6*sizeof(CurveMapPoint), "curve points");
- cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
- cm->totpoint= 6;
- cm->curve[0].x= 0;
- cm->curve[0].y= 1;
- cm->curve[1].x= 0.1;
- cm->curve[1].y= 0.97553;
- cm->curve[2].x= 0.3;
- cm->curve[2].y= 0.79389;
- cm->curve[3].x= 0.9;
- cm->curve[3].y= 0.02447;
- cm->curve[4].x= 0.7;
- cm->curve[4].y= 0.20611;
- cm->curve[5].x= 1;
- cm->curve[5].y= 0;
-}
-
-/* Initialize 'permanent' sculpt data that is saved with file kept after
- switching out of sculptmode. */
-void sculptmode_init(Scene *sce)
-{
- SculptData *sd;
-
- if(!sce) {
- error("Unable to initialize sculptmode: bad scene");
- return;
- }
-
- sd= &sce->sculptdata;
-
- if(sd->cumap)
- curvemapping_free(sd->cumap);
-
- memset(sd, 0, sizeof(SculptData));
-
- sd->drawbrush.size = sd->smoothbrush.size = sd->pinchbrush.size =
- sd->inflatebrush.size = sd->grabbrush.size =
- sd->layerbrush.size = sd->flattenbrush.size = 50;
- sd->drawbrush.strength = sd->smoothbrush.strength =
- sd->pinchbrush.strength = sd->inflatebrush.strength =
- sd->grabbrush.strength = sd->layerbrush.strength =
- sd->flattenbrush.strength = 25;
- sd->drawbrush.dir = sd->pinchbrush.dir = sd->inflatebrush.dir = sd->layerbrush.dir= 1;
- sd->drawbrush.airbrush = sd->smoothbrush.airbrush =
- sd->pinchbrush.airbrush = sd->inflatebrush.airbrush =
- sd->layerbrush.airbrush = sd->flattenbrush.airbrush = 0;
- sd->drawbrush.view= 0;
- sd->brush_type= DRAW_BRUSH;
- sd->texact= -1;
- sd->texfade= 1;
- sd->averaging= 1;
- sd->texsep= 0;
- sd->texrept= SCULPTREPT_DRAG;
- sd->flags= SCULPT_DRAW_BRUSH;
- sd->tablet_size=3;
- sd->tablet_strength=10;
- sd->rake=0;
- sculpt_reset_curve(sd);
-}
-
-void sculptmode_free_session(Scene *);
-void sculpt_init_session(void)
-{
- if(sculpt_data()->session)
- sculptmode_free_session(G.scene);
- sculpt_data()->session= MEM_callocN(sizeof(SculptSession), "SculptSession");
-}
-
-void sculptmode_free_vertexusers(SculptSession *ss)
-{
- if(ss && ss->vertex_users){
- MEM_freeN(ss->vertex_users);
- MEM_freeN(ss->vertex_users_mem);
- ss->vertex_users= NULL;
- ss->vertex_users_mem= NULL;
- ss->vertex_users_size= 0;
- }
-}
-
-void sculptmode_propset_end(SculptSession *ss, int);
-void sculptmode_free_session(Scene *sce)
-{
- SculptSession *ss= sce->sculptdata.session;
- if(ss) {
- sculptmode_free_vertexusers(ss);
- if(ss->texcache)
- MEM_freeN(ss->texcache);
- sculptmode_propset_end(ss, 1);
- MEM_freeN(ss);
- sce->sculptdata.session= NULL;
- }
-}
-
-void sculptmode_free_all(Scene *sce)
-{
- SculptData *sd= &sce->sculptdata;
- int a;
-
- sculptmode_free_session(sce);
-
- if(projverts) {
- MEM_freeN(projverts);
- projverts = NULL;
- }
-
- for(a=0; a<MAX_MTEX; a++) {
- MTex *mtex= sd->mtex[a];
- if(mtex) {
- if(mtex->tex) mtex->tex->id.us--;
- MEM_freeN(mtex);
- }
- }
-
- curvemapping_free(sd->cumap);
- sd->cumap = NULL;
-}
-
-/* vertex_users is an array of Lists that store all the faces that use a
- particular vertex. vertex_users is in the same order as mesh.mvert */
-void calc_vertex_users()
-{
- SculptSession *ss= sculpt_session();
- int i,j;
- IndexNode *node= NULL;
- Mesh *me= get_mesh(OBACT);
-
- sculptmode_free_vertexusers(ss);
-
- /* For efficiency, use vertex_users_mem as a memory pool (may be larger
- than necessary if mesh has triangles, but only one alloc is needed.) */
- ss->vertex_users= MEM_callocN(sizeof(ListBase) * me->totvert, "vertex_users");
- ss->vertex_users_size= me->totvert;
- ss->vertex_users_mem= MEM_callocN(sizeof(IndexNode)*me->totface*4, "vertex_users_mem");
- node= ss->vertex_users_mem;
-
- /* Find the users */
- for(i=0; i<me->totface; ++i){
- for(j=0; j<(me->mface[i].v4?4:3); ++j, ++node) {
- node->Index=i;
- BLI_addtail(&ss->vertex_users[((unsigned int*)(&me->mface[i]))[j]], node);
- }
- }
-}
-
-/* ===== INTERFACE =====
- */
-
-void sculptmode_rem_tex(void *junk0,void *junk1)
-{
- MTex *mtex= G.scene->sculptdata.mtex[G.scene->sculptdata.texact];
- if(mtex) {
- SculptSession *ss= sculpt_session();
- if(mtex->tex) mtex->tex->id.us--;
- MEM_freeN(mtex);
- G.scene->sculptdata.mtex[G.scene->sculptdata.texact]= NULL;
- /* Clear brush preview */
- if(ss->texcache) {
- MEM_freeN(ss->texcache);
- ss->texcache= NULL;
- }
- BIF_undo_push("Unlink brush texture");
- allqueue(REDRAWBUTSEDIT, 0);
- allqueue(REDRAWOOPS, 0);
- }
-}
-
-/* ===== OPENGL =====
- *
- * Simple functions to get data from the GL
- */
-
-/* Store the modelview and projection matrices and viewport. */
-void init_sculptmatrices()
-{
- SculptSession *ss= sculpt_session();
-
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glMultMatrixf(OBACT->obmat);
-
- bgl_get_mats(&ss->mats);
-
- glPopMatrix();
-
-}
-
-/* Uses window coordinates (x,y) to find the depth in the GL depth buffer. If
- available, G.vd->depths is used so that the brush doesn't sculpt on top of
- itself (G.vd->depths is only updated at the end of a brush stroke.) */
-float get_depth(short x, short y)
-{
- float depth;
-
- if(x<0 || y<0) return 1;
- if(x>=curarea->winx || y>=curarea->winy) return 1;
-
- if(G.vd->depths && x<G.vd->depths->w && y<G.vd->depths->h)
- return G.vd->depths->depths[y*G.vd->depths->w+x];
-
- x+= curarea->winrct.xmin;
- y+= curarea->winrct.ymin;
-
- glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
-
- return depth;
-}
-
-/* Uses window coordinates (x,y) and depth component z to find a point in
- modelspace */
-vec3f unproject(const short x, const short y, const float z)
-{
- SculptSession *ss= sculpt_session();
- double ux, uy, uz;
- vec3f p;
-
- gluUnProject(x,y,z, ss->mats.modelview, ss->mats.projection,
- (GLint *)ss->mats.viewport, &ux, &uy, &uz );
- p.x= ux;
- p.y= uy;
- p.z= uz;
- return p;
-}
-
-/* Convert a point in model coordinates to 2D screen coordinates. */
-void project(const float v[3], short p[2])
-{
- SculptSession *ss= sculpt_session();
- double ux, uy, uz;
-
- gluProject(v[0],v[1],v[2], ss->mats.modelview, ss->mats.projection,
- (GLint *)ss->mats.viewport, &ux, &uy, &uz);
- p[0]= ux;
- p[1]= uy;
-}
-
-/* ===== Sculpting =====
- *
- */
-
-/* Return modified brush size. Uses current tablet pressure (if available) to
- shrink the brush. Skipped for grab brush because only the first mouse down
- size is used, which is small if the user has just touched the pen to the
- tablet */
-char brush_size()
-{
- const BrushData *b= sculptmode_brush();
- float size= b->size;
- float pressure= get_pressure();
- short activedevice= get_activedevice();
-
- if(sculpt_data()->brush_type!=GRAB_BRUSH) {
- const float size_factor= G.scene->sculptdata.tablet_size / 10.0f;
- if(ELEM(activedevice, DEV_STYLUS, DEV_ERASER))
- size*= G.scene->sculptdata.tablet_size==0?1:
- (1-size_factor) + pressure*size_factor;
- }
-
- return size;
-}
-
-/* Return modified brush strength. Includes the direction of the brush, positive
- values pull vertices, negative values push. Uses tablet pressure and a
- special multiplier found experimentally to scale the strength factor. */
-float brush_strength(EditData *e)
-{
- const BrushData* b= sculptmode_brush();
- float dir= b->dir==1 ? 1 : -1;
- float pressure= 1;
- short activedevice= get_activedevice();
- float flip= e->flip ? -1:1;
-
- const float strength_factor= G.scene->sculptdata.tablet_strength / 10.0f;
- if(ELEM(activedevice, DEV_STYLUS, DEV_ERASER))
- pressure= G.scene->sculptdata.tablet_strength==0?1:
- (1-strength_factor) + get_pressure()*strength_factor;
-
- /* Flip direction for eraser */
- if(activedevice==DEV_ERASER)
- dir= -dir;
-
- switch(G.scene->sculptdata.brush_type){
- case DRAW_BRUSH:
- case LAYER_BRUSH:
- return b->strength / 5000.0f * dir * pressure * flip;
- case SMOOTH_BRUSH:
- return b->strength / 50.0f * pressure;
- case PINCH_BRUSH:
- return b->strength / 1000.0f * dir * pressure * flip;
- case GRAB_BRUSH:
- return 1;
- case INFLATE_BRUSH:
- return b->strength / 5000.0f * dir * pressure * flip;
- case FLATTEN_BRUSH:
- return b->strength / 500.0f * pressure;
- default:
- return 0;
- }
-}
-
-/* For clipping against a mirror modifier */
-void sculpt_clip(const EditData *e, float *co, const float val[3])
-{
- char i;
- for(i=0; i<3; ++i) {
- if(e->clip[i] && (fabs(co[i]) <= e->cliptol[i]))
- co[i]= 0.0f;
- else
- co[i]= val[i];
- }
-}
-
-/* Currently only for the draw brush; finds average normal for all active
- vertices */
-vec3f calc_area_normal(const vec3f *outdir, const ListBase* active_verts)
-{
- Mesh *me= get_mesh(OBACT);
- vec3f area_normal= {0,0,0};
- ActiveData *node= active_verts->first;
- const int view= sculpt_data()->brush_type==DRAW_BRUSH ? sculptmode_brush()->view : 0;
-
- while(node){
- area_normal.x+= me->mvert[node->Index].no[0];
- area_normal.y+= me->mvert[node->Index].no[1];
- area_normal.z+= me->mvert[node->Index].no[2];
- node= node->next;
- }
- Normalize(&area_normal.x);
- if(outdir) {
- area_normal.x= outdir->x * view + area_normal.x * (10-view);
- area_normal.y= outdir->y * view + area_normal.y * (10-view);
- area_normal.z= outdir->z * view + area_normal.z * (10-view);
- }
- Normalize(&area_normal.x);
- return area_normal;
-}
-void do_draw_brush(const EditData *e, const ListBase* active_verts)
-{
- Mesh *me= get_mesh(OBACT);
- const vec3f area_normal= calc_area_normal(&e->out, active_verts);
- ActiveData *node= active_verts->first;
-
- while(node){
- float *co= me->mvert[node->Index].co;
-
- const float val[3]= {co[0]+area_normal.x*node->Fade*e->scale[0],
- co[1]+area_normal.y*node->Fade*e->scale[1],
- co[2]+area_normal.z*node->Fade*e->scale[2]};
-
- sculpt_clip(e, co, val);
-
- node= node->next;
- }
-}
-
-/* For the smooth brush, uses the neighboring vertices around vert to calculate
- a smoothed location for vert. Skips corner vertices (used by only one
- polygon.) */
-vec3f neighbor_average(const int vert)
-{
- SculptSession *ss= sculpt_session();
- Mesh *me= get_mesh(OBACT);
- int i, skip= -1, total=0;
- IndexNode *node= ss->vertex_users[vert].first;
- vec3f avg= {0,0,0};
- char ncount= BLI_countlist(&ss->vertex_users[vert]);
- MFace *f;
-
- /* Don't modify corner vertices */
- if(ncount==1) {
- VecCopyf(&avg.x, me->mvert[vert].co);
- return avg;
- }
-
- while(node){
- f= &me->mface[node->Index];
-
- if(f->v4) {
- skip= (f->v1==vert?2:
- f->v2==vert?3:
- f->v3==vert?0:
- f->v4==vert?1:-1);
- }
-
- for(i=0; i<(f->v4?4:3); ++i) {
- if(i != skip && (ncount!=2 || BLI_countlist(&ss->vertex_users[(&f->v1)[i]]) <= 2)) {
- VecAddf(&avg.x,&avg.x,me->mvert[(&f->v1)[i]].co);
- ++total;
- }
- }
-
- node= node->next;
- }
-
- if(total>0) {
- avg.x/= total;
- avg.y/= total;
- avg.z/= total;
- }
- else
- VecCopyf(&avg.x, me->mvert[vert].co);
-
- return avg;
-}
-
-void do_smooth_brush(const EditData *e, const ListBase* active_verts)
-{
- ActiveData *node= active_verts->first;
- Mesh *me= get_mesh(OBACT);
-
- while(node){
- float *co= me->mvert[node->Index].co;
- const vec3f avg= neighbor_average(node->Index);
- const float val[3]= {co[0]+(avg.x-co[0])*node->Fade,
- co[1]+(avg.y-co[1])*node->Fade,
- co[2]+(avg.z-co[2])*node->Fade};
- sculpt_clip(e, co, val);
- node= node->next;
- }
-}
-
-void do_pinch_brush(const EditData *e, const ListBase* active_verts)
-{
- Mesh *me= get_mesh(OBACT);
- ActiveData *node= active_verts->first;
-
- while(node) {
- float *co= me->mvert[node->Index].co;
- const float val[3]= {co[0]+(e->center.x-co[0])*node->Fade,
- co[1]+(e->center.y-co[1])*node->Fade,
- co[2]+(e->center.z-co[2])*node->Fade};
- sculpt_clip(e, co, val);
- node= node->next;
- }
-}
-
-void do_grab_brush(EditData *e)
-{
- Mesh *me= get_mesh(OBACT);
- ActiveData *node= e->grabdata->active_verts[e->grabdata->index].first;
- float add[3];
-
- while(node) {
- float *co= me->mvert[node->Index].co;
-
- VecCopyf(add, &e->grabdata->delta_symm.x);
- VecMulf(add, node->Fade);
- VecAddf(add, add, co);
- sculpt_clip(e, co, add);
-
- node= node->next;
- }
-}
-
-void do_layer_brush(EditData *e, const ListBase *active_verts)
-{
- Mesh *me= get_mesh(OBACT);
- vec3f area_normal= calc_area_normal(NULL, active_verts);
- ActiveData *node= active_verts->first;
- const float bstr= brush_strength(e);
-
- while(node){
- float *disp= &e->layer_disps[node->Index];
-
- if((bstr > 0 && *disp < bstr) ||
- (bstr < 0 && *disp > bstr)) {
- float *co= me->mvert[node->Index].co;
-
- *disp+= node->Fade;
-
- if(bstr < 0) {
- if(*disp < bstr)
- *disp = bstr;
- } else {
- if(*disp > bstr)
- *disp = bstr;
- }
-
- {
- const float val[3]= {e->layer_store[node->Index].x+area_normal.x * *disp*e->scale[0],
- e->layer_store[node->Index].y+area_normal.y * *disp*e->scale[1],
- e->layer_store[node->Index].z+area_normal.z * *disp*e->scale[2]};
- sculpt_clip(e, co, val);
- }
- }
-
- node= node->next;
- }
-}
-
-void do_inflate_brush(const EditData *e, const ListBase *active_verts)
-{
- ActiveData *node= active_verts->first;
- float add[3];
- Mesh *me= get_mesh(OBACT);
-
- while(node) {
- float *co= me->mvert[node->Index].co;
- short *no= me->mvert[node->Index].no;
-
- add[0]= no[0]/ 32767.0f;
- add[1]= no[1]/ 32767.0f;
- add[2]= no[2]/ 32767.0f;
- VecMulf(add, node->Fade);
- add[0]*= e->scale[0];
- add[1]*= e->scale[1];
- add[2]*= e->scale[2];
- VecAddf(add, add, co);
-
- sculpt_clip(e, co, add);
-
- node= node->next;
- }
-}
-
-void calc_flatten_center(Mesh *me, ActiveData *node, const EditData *e, float co[3])
-{
- ActiveData *outer[FLATTEN_SAMPLE_SIZE];
- int i;
-
- for(i = 0; i < FLATTEN_SAMPLE_SIZE; ++i)
- outer[i] = node;
-
- for(; node; node = node->next) {
- for(i = 0; i < FLATTEN_SAMPLE_SIZE; ++i) {
- if(node->dist > outer[i]->dist) {
- outer[i] = node;
- break;
- }
- }
- }
-
- co[0] = co[1] = co[2] = 0.0f;
- for(i = 0; i < FLATTEN_SAMPLE_SIZE; ++i)
- VecAddf(co, co, me->mvert[outer[i]->Index].co);
- VecMulf(co, 1.0f / FLATTEN_SAMPLE_SIZE);
-}
-
-void do_flatten_brush(const EditData *e, const ListBase *active_verts)
-{
- Mesh *me= get_mesh(OBACT);
- ActiveData *node= active_verts->first;
- /* area_normal and cntr define the plane towards which vertices are squashed */
- vec3f area_normal= calc_area_normal(&e->out, active_verts);
- float cntr[3];
-
- calc_flatten_center(me, node, e, cntr);
-
- while(node){
- float *co= me->mvert[node->Index].co;
- float p1[3], sub1[3], sub2[3], intr[3], val[3];
-
- /* Find the intersection between squash-plane and vertex (along the area normal) */
- VecSubf(p1, co, &area_normal.x);
- VecSubf(sub1, cntr, p1);
- VecSubf(sub2, co, p1);
- VecSubf(intr, co, p1);
- VecMulf(intr, Inpf(&area_normal.x, sub1) / Inpf(&area_normal.x, sub2));
- VecAddf(intr, intr, p1);
-
- VecSubf(val, intr, co);
- VecMulf(val, node->Fade);
- VecAddf(val, val, co);
-
- sculpt_clip(e, co, val);
-
- node= node->next;
- }
-}
-
-/* Uses the brush curve control to find a strength value between 0 and 1 */
-float curve_strength(float p, const float len)
-{
- if(p > len) p= len;
- return curvemapping_evaluateF(G.scene->sculptdata.cumap, 0, p/len);
-}
-
-/* Uses symm to selectively flip any axis of a coordinate. */
-void flip_coord(float co[3], const char symm)
-{
- if(symm & SYMM_X)
- co[0]= -co[0];
- if(symm & SYMM_Y)
- co[1]= -co[1];
- if(symm & SYMM_Z)
- co[2]= -co[2];
-}
-
-/* Use the warpfac field in MTex to store a rotation value for sculpt textures. Value is in degrees */
-float tex_angle(void)
-{
- SculptData *sd= sculpt_data();
- if(sd->texact!=-1 && sd->mtex[sd->texact])
- return sd->mtex[sd->texact]->warpfac;
- return 0;
-}
-
-void set_tex_angle(const float f)
-{
- SculptData *sd = sculpt_data();
- if(sd->texact != -1 && sd->mtex[sd->texact])
- sd->mtex[sd->texact]->warpfac = f;
-}
-
-float to_rad(const float deg)
-{
- return deg * (M_PI/180.0f);
-}
-
-float to_deg(const float rad)
-{
- return rad * (180.0f/M_PI);
-}
-
-/* Get a pixel from the texcache at (px, py) */
-unsigned *get_texcache_pixel(const SculptSession *ss, int px, int py)
-{
- if(px < 0) px= 0;
- if(py < 0) py= 0;
- if(px > ss->texcache_w - 1) px= ss->texcache_w - 1;
- if(py > ss->texcache_h - 1) py= ss->texcache_h - 1;
- return ss->texcache + py * ss->texcache_w + px;
-}
-
-/* Return a multiplier for brush strength on a particular vertex. */
-float tex_strength(EditData *e, float *point, const float len,const unsigned vindex)
-{
- SculptData *sd= sculpt_data();
- SculptSession *ss= sculpt_session();
- float avg= 1;
-
- if(sd->texact==-1 || !sd->mtex[sd->texact])
- avg= 1;
- else if(sd->texrept==SCULPTREPT_3D) {
- /* Get strength by feeding the vertex location directly
- into a texture */
- float jnk;
- const float factor= 0.01;
- MTex mtex;
- memset(&mtex,0,sizeof(MTex));
- mtex.tex= sd->mtex[sd->texact]->tex;
- mtex.projx= 1;
- mtex.projy= 2;
- mtex.projz= 3;
- VecCopyf(mtex.size, sd->mtex[sd->texact]->size);
- VecMulf(mtex.size, factor);
- if(!sd->texsep)
- mtex.size[1]= mtex.size[2]= mtex.size[0];
-
- externtex(&mtex,point,&avg,&jnk,&jnk,&jnk,&jnk);
- }
- else if(ss->texcache) {
- const short bsize= sculptmode_brush()->size * 2;
- const short half= sculptmode_brush()->size;
- const float rot= to_rad(tex_angle());
- const unsigned tcw = ss->texcache_w, tch = ss->texcache_h;
- int px, py;
- unsigned i, *p;
- ProjVert pv;
-
- /* If the active area is being applied for symmetry, flip it
- across the symmetry axis in order to project it. This insures
- that the brush texture will be oriented correctly. */
- if(!e->symm)
- pv= projverts[vindex];
- else {
- float co[3];
- VecCopyf(co, point);
- flip_coord(co, e->symm);
- project(co, pv.co);
- }
-
- /* For Tile and Drag modes, get the 2D screen coordinates of the
- and scale them up or down to the texture size. */
- if(sd->texrept==SCULPTREPT_TILE) {
- const int sx= (const int)sd->mtex[sd->texact]->size[0];
- const int sy= (const int)sd->texsep ? sd->mtex[sd->texact]->size[1] : sx;
-
- float fx= pv.co[0];
- float fy= pv.co[1];
-
- float angle= atan2(fy, fx) - rot;
- float len= sqrtf(fx*fx + fy*fy);
-
- if(rot<0.001 && rot>-0.001) {
- px= pv.co[0];
- py= pv.co[1];
- } else {
- px= len * cos(angle) + 2000;
- py= len * sin(angle) + 2000;
- }
- if(sx != 1)
- px %= sx-1;
- if(sy != 1)
- py %= sy-1;
- p= get_texcache_pixel(ss, tcw*px/sx, tch*py/sy);
- } else {
- float fx= (pv.co[0] - e->mouse[0] + half) * (tcw*1.0f/bsize) - tcw/2;
- float fy= (pv.co[1] - e->mouse[1] + half) * (tch*1.0f/bsize) - tch/2;
-
- float angle= atan2(fy, fx) - rot;
- float len= sqrtf(fx*fx + fy*fy);
-
- px= tcw/2 + len * cos(angle);
- py= tch/2 + len * sin(angle);
-
- p= get_texcache_pixel(ss, px, py);
- }
-
- avg= 0;
- for(i=0; i<3; ++i)
- avg+= ((unsigned char*)(p))[i] / 255.0f;
-
- avg/= 3;
- }
-
- if(sd->texfade)
- avg*= curve_strength(len,e->size); /* Smooth curve */
-
- return avg;
-}
-
-/* Mark area around the brush as damaged. projverts are marked if they are
- inside the area and the damaged rectangle in 2D screen coordinates is
- added to damaged_rects. */
-void sculpt_add_damaged_rect(EditData *e)
-{
- short p[2];
- const float radius= brush_size();
- RectNode *rn= MEM_mallocN(sizeof(RectNode),"RectNode");
- Mesh *me= get_mesh(OBACT);
- unsigned i;
-
- /* Find center */
- project(&e->center.x, p);
- rn->r.xmin= p[0]-radius;
- rn->r.ymin= p[1]-radius;
- rn->r.xmax= p[0]+radius;
- rn->r.ymax= p[1]+radius;
-
- BLI_addtail(&sculpt_session()->damaged_rects, rn);
-
- /* Update insides */
- for(i=0; i<me->totvert; ++i) {
- if(!projverts[i].inside) {
- if(projverts[i].co[0] > rn->r.xmin && projverts[i].co[1] > rn->r.ymin &&
- projverts[i].co[0] < rn->r.xmax && projverts[i].co[1] < rn->r.ymax) {
- projverts[i].inside= 1;
- }
- }
- }
-}
-
-/* Clears the depth buffer in each modified area. */
-void sculpt_clear_damaged_areas(SculptSession *ss)
-{
- RectNode *rn= NULL;
-
- for(rn = ss->damaged_rects.first; rn; rn = rn->next) {
- rcti clp = rn->r;
- rcti *win = &curarea->winrct;
-
- clp.xmin += win->xmin;
- clp.xmax += win->xmin;
- clp.ymin += win->ymin;
- clp.ymax += win->ymin;
-
- if(clp.xmin < win->xmax && clp.xmax > win->xmin &&
- clp.ymin < win->ymax && clp.ymax > win->ymin) {
- if(clp.xmin < win->xmin) clp.xmin = win->xmin;
- if(clp.ymin < win->ymin) clp.ymin = win->ymin;
- if(clp.xmax > win->xmax) clp.xmax = win->xmax;
- if(clp.ymax > win->ymax) clp.ymax = win->ymax;
-
- glScissor(clp.xmin + 1, clp.ymin + 1,
- clp.xmax - clp.xmin - 2,
- clp.ymax - clp.ymin - 2);
- }
-
- glClear(GL_DEPTH_BUFFER_BIT);
- }
-}
-
-void do_brush_action(EditData e)
-{
- int i;
- float av_dist;
- ListBase active_verts={0,0};
- ActiveData *adata= 0;
- float *vert;
- Mesh *me= get_mesh(OBACT);
- const float bstrength= brush_strength(&e);
- KeyBlock *keyblock= ob_get_keyblock(OBACT);
- SculptSession *ss = sculpt_session();
-
- sculpt_add_damaged_rect(&e);
-
- /* Build a list of all vertices that are potentially within the brush's
- area of influence. Only do this once for the grab brush. */
- if(!e.grabdata || (e.grabdata && e.grabdata->firsttime)) {
- for(i=0; i<me->totvert; ++i) {
- /* Projverts.inside provides a rough bounding box */
- if(projverts[i].inside) {
- vert= ss->vertexcosnos ? &ss->vertexcosnos[i*6] : me->mvert[i].co;
- av_dist= VecLenf(&e.center.x,vert);
- if(av_dist < e.size) {
- adata= (ActiveData*)MEM_mallocN(sizeof(ActiveData), "ActiveData");
- adata->Index = i;
- /* Fade is used to store the final strength at which the brush
- should modify a particular vertex. */
- adata->Fade= tex_strength(&e,vert,av_dist,i) * bstrength;
- adata->dist = av_dist;
- if(e.grabdata && e.grabdata->firsttime)
- BLI_addtail(&e.grabdata->active_verts[e.grabdata->index], adata);
- else
- BLI_addtail(&active_verts, adata);
- }
- }
- }
- }
-
- /* Only act if some verts are inside the brush area */
- if(active_verts.first || (e.grabdata && e.grabdata->active_verts[e.grabdata->index].first)) {
- /* Apply one type of brush action */
- switch(G.scene->sculptdata.brush_type){
- case DRAW_BRUSH:
- do_draw_brush(&e, &active_verts);
- break;
- case SMOOTH_BRUSH:
- do_smooth_brush(&e, &active_verts);
- break;
- case PINCH_BRUSH:
- do_pinch_brush(&e, &active_verts);
- break;
- case INFLATE_BRUSH:
- do_inflate_brush(&e, &active_verts);
- break;
- case GRAB_BRUSH:
- do_grab_brush(&e);
- break;
- case LAYER_BRUSH:
- do_layer_brush(&e, &active_verts);
- break;
- case FLATTEN_BRUSH:
- do_flatten_brush(&e, &active_verts);
- break;
- }
-
- /* Copy the modified vertices from mesh to the active key */
- if(keyblock) {
- float *co= keyblock->data;
- if(co) {
- adata = e.grabdata ? e.grabdata->active_verts[e.grabdata->index].first : active_verts.first;
- for(; adata; adata= adata->next)
- if(adata->Index < keyblock->totelem)
- VecCopyf(&co[adata->Index*3], me->mvert[adata->Index].co);
- }
- }
-
- if(ss->vertexcosnos)
- BLI_freelistN(&active_verts);
- else {
- if(!e.grabdata)
- addlisttolist(&ss->damaged_verts, &active_verts);
- }
- }
-}
-
-/* Flip all the editdata across the axis/axes specified by symm. Used to
- calculate multiple modifications to the mesh when symmetry is enabled. */
-EditData flip_editdata(EditData *e, const char symm)
-{
- EditData fe= *e;
- GrabData *gd= fe.grabdata;
-
- flip_coord(&fe.center.x, symm);
- flip_coord(&fe.up.x, symm);
- flip_coord(&fe.right.x, symm);
- flip_coord(&fe.out.x, symm);
-
- fe.symm= symm;
-
- project(&e->center.x,fe.mouse);
-
- if(gd) {
- gd->index= symm;
- gd->delta_symm= gd->delta;
- flip_coord(&gd->delta_symm.x, symm);
- }
-
- return fe;
-}
-
-void do_symmetrical_brush_actions(EditData * e, short co[2], short pr_co[2])
-{
- const char symm= sculpt_data()->symm;
-
- init_editdata(e, co, pr_co);
-
- do_brush_action(flip_editdata(e, 0));
-
- if(symm & SYMM_X)
- do_brush_action(flip_editdata(e, SYMM_X));
- if(symm & SYMM_Y)
- do_brush_action(flip_editdata(e, SYMM_Y));
- if(symm & SYMM_Z)
- do_brush_action(flip_editdata(e, SYMM_Z));
- if(symm & SYMM_X && symm & SYMM_Y)
- do_brush_action(flip_editdata(e, SYMM_X | SYMM_Y));
- if(symm & SYMM_X && symm & SYMM_Z)
- do_brush_action(flip_editdata(e, SYMM_X | SYMM_Z));
- if(symm & SYMM_Y && symm & SYMM_Z)
- do_brush_action(flip_editdata(e, SYMM_Y | SYMM_Z));
- if(symm & SYMM_X && symm & SYMM_Y && symm & SYMM_Z)
- do_brush_action(flip_editdata(e, SYMM_X | SYMM_Y | SYMM_Z));
-}
-
-void add_face_normal(vec3f *norm, const MFace* face)
-{
- Mesh *me= get_mesh(OBACT);
-
- vec3f c= {me->mvert[face->v1].co[0],me->mvert[face->v1].co[1],me->mvert[face->v1].co[2]};
- vec3f b= {me->mvert[face->v2].co[0],me->mvert[face->v2].co[1],me->mvert[face->v2].co[2]};
- vec3f a= {me->mvert[face->v3].co[0],me->mvert[face->v3].co[1],me->mvert[face->v3].co[2]};
- vec3f s1, s2;
-
- VecSubf(&s1.x,&a.x,&b.x);
- VecSubf(&s2.x,&c.x,&b.x);
-
- norm->x+= s1.y * s2.z - s1.z * s2.y;
- norm->y+= s1.z * s2.x - s1.x * s2.z;
- norm->z+= s1.x * s2.y - s1.y * s2.x;
-}
-
-void update_damaged_vert(Mesh *me, ListBase *lb)
-{
- ActiveData *vert;
-
- for(vert= lb->first; vert; vert= vert->next) {
- vec3f norm= {0,0,0};
- IndexNode *face= sculpt_session()->vertex_users[vert->Index].first;
-
- while(face){
- add_face_normal(&norm,&me->mface[face->Index]);
- face= face->next;
- }
- Normalize(&norm.x);
-
- me->mvert[vert->Index].no[0]=norm.x*32767;
- me->mvert[vert->Index].no[1]=norm.y*32767;
- me->mvert[vert->Index].no[2]=norm.z*32767;
- }
-}
-
-void calc_damaged_verts(ListBase *damaged_verts, GrabData *grabdata)
-{
- Mesh *me= get_mesh(OBACT);
-
- if(grabdata) {
- int i;
- for(i=0; i<8; ++i)
- update_damaged_vert(me,&grabdata->active_verts[i]);
- } else {
- update_damaged_vert(me,damaged_verts);
- BLI_freelistN(damaged_verts);
- damaged_verts->first = damaged_verts->last = NULL;
- }
-}
-
-void projverts_clear_inside()
-{
- Mesh *me = get_mesh(OBACT);
- if(me) {
- int i;
- for(i = 0; i < me->totvert; ++i)
- projverts[i].inside = 0;
- }
-}
-
-BrushData *sculptmode_brush(void)
-{
- SculptData *sd= &G.scene->sculptdata;
-
- BrushData *bd =
- (sd->brush_type==DRAW_BRUSH ? &sd->drawbrush :
- sd->brush_type==SMOOTH_BRUSH ? &sd->smoothbrush :
- sd->brush_type==PINCH_BRUSH ? &sd->pinchbrush :
- sd->brush_type==INFLATE_BRUSH ? &sd->inflatebrush :
- sd->brush_type==GRAB_BRUSH ? &sd->grabbrush :
- sd->brush_type==LAYER_BRUSH ? &sd->layerbrush :
- sd->brush_type==FLATTEN_BRUSH ? &sd->flattenbrush : NULL);
-
- if(!bd) {
- sculptmode_init(G.scene);
- bd = &sd->drawbrush;
- }
-
- return bd;
-}
-
-void sculptmode_update_tex()
-{
- SculptData *sd= sculpt_data();
- SculptSession *ss= sculpt_session();
- MTex *mtex = sd->mtex[sd->texact];
- TexResult texres = {0};
- float x, y, step=2.0/128.0, co[3];
- int hasrgb, ix, iy;
-
- /* Skip Default brush shape and non-textures */
- if(sd->texact == -1 || !sd->mtex[sd->texact]) return;
-
- if(ss->texcache) {
- MEM_freeN(ss->texcache);
- ss->texcache= NULL;
- }
-
- ss->texcache_w = ss->texcache_h = 128;
- ss->texcache = MEM_callocN(sizeof(int) * ss->texcache_w * ss->texcache_h, "Sculpt Texture cache");
-
- if(mtex && mtex->tex) {
- BKE_image_get_ibuf(sd->mtex[sd->texact]->tex->ima, NULL);
-
- /*do normalized cannonical view coords for texture*/
- for (y=-1.0, iy=0; iy<128; iy++, y += step) {
- for (x=-1.0, ix=0; ix<128; ix++, x += step) {
- co[0]= x;
- co[1]= y;
- co[2]= 0.0f;
-
- /* This is copied from displace modifier code */
- hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 1, &texres);
-
- /* if the texture gave an RGB value, we assume it didn't give a valid
- * intensity, so calculate one (formula from do_material_tex).
- * if the texture didn't give an RGB value, copy the intensity across
- */
- if(hasrgb & TEX_RGB)
- texres.tin = (0.35 * texres.tr + 0.45 *
- texres.tg + 0.2 * texres.tb);
-
- texres.tin = texres.tin * 255.0;
- ((char*)ss->texcache)[(iy*128+ix)*4] = (char)texres.tin;
- ((char*)ss->texcache)[(iy*128+ix)*4+1] = (char)texres.tin;
- ((char*)ss->texcache)[(iy*128+ix)*4+2] = (char)texres.tin;
- ((char*)ss->texcache)[(iy*128+ix)*4+3] = (char)texres.tin;
- }
- }
- }
-}
-
-/* pr_mouse is only used for the grab brush, can be NULL otherwise */
-void init_editdata(EditData *e, short *mouse, short *pr_mouse)
-{
- SculptData *sd = sculpt_data();
- const float mouse_depth= get_depth(mouse[0],mouse[1]);
- vec3f brush_edge_loc, zero_loc, oldloc;
- ModifierData *md;
- int i;
- const char flip = (get_qual() == LR_SHIFTKEY);
-
- e->flip= flip;
-
- /* Convert the location and size of the brush to
- modelspace coords */
- e->center= unproject(mouse[0],mouse[1],mouse_depth);
- brush_edge_loc= unproject(mouse[0] +
- brush_size(),mouse[1],
- mouse_depth);
- e->size= VecLenf(&e->center.x,&brush_edge_loc.x);
-
- /* Set the pivot to allow the model to rotate around the center of the brush */
- if(get_depth(mouse[0],mouse[1]) < 1.0)
- sculpt_session()->pivot= e->center;
-
- /* Now project the Up, Right, and Out normals from view to model coords */
- zero_loc= unproject(0, 0, 0);
- e->up= unproject(0, -1, 0);
- e->right= unproject(1, 0, 0);
- e->out= unproject(0, 0, -1);
- VecSubf(&e->up.x, &e->up.x, &zero_loc.x);
- VecSubf(&e->right.x, &e->right.x, &zero_loc.x);
- VecSubf(&e->out.x, &e->out.x, &zero_loc.x);
- Normalize(&e->up.x);
- Normalize(&e->right.x);
- Normalize(&e->out.x);
-
- /* Initialize mirror modifier clipping */
- for(i=0; i<3; ++i) {
- e->clip[i]= 0;
- e->cliptol[i]= 0;
- }
- for(md= OBACT->modifiers.first; md; md= md->next) {
- if(md->type==eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) {
- const MirrorModifierData *mmd = (MirrorModifierData*) md;
-
- if(mmd->flag & MOD_MIR_CLIPPING) {
- e->clip[mmd->axis]= 1;
- if(mmd->tolerance > e->cliptol[mmd->axis])
- e->cliptol[mmd->axis]= mmd->tolerance;
- }
- }
- }
-
- if(sd->brush_type == GRAB_BRUSH) {
- vec3f gcenter;
- if(!e->grabdata) {
- e->grabdata= MEM_callocN(sizeof(GrabData),"grab data");
- e->grabdata->firsttime= 1;
- e->grabdata->depth= mouse_depth;
- }
- else
- e->grabdata->firsttime= 0;
-
- /* Find the delta */
- gcenter= unproject(mouse[0],mouse[1],e->grabdata->depth);
- oldloc= unproject(pr_mouse[0],pr_mouse[1],e->grabdata->depth);
- VecSubf(&e->grabdata->delta.x,&gcenter.x,&oldloc.x);
- }
- else if(sd->brush_type == LAYER_BRUSH) {
- Mesh *me= get_mesh(OBACT);
-
- if(!e->layer_disps)
- e->layer_disps= MEM_callocN(sizeof(float)*me->totvert,"Layer disps");
- if(!e->layer_store) {
- unsigned i;
- e->layer_store= MEM_mallocN(sizeof(vec3f)*me->totvert,"Layer store");
- for(i=0; i<me->totvert; ++i)
- VecCopyf(&e->layer_store[i].x,me->mvert[i].co);
- }
- }
-}
-void sculptmode_set_strength(const int delta)
-{
- int val = sculptmode_brush()->strength + delta;
- if(val < 1) val = 1;
- if(val > 100) val = 100;
- sculptmode_brush()->strength= val;
-}
-
-void sculptmode_propset_calctex()
-{
- SculptData *sd= sculpt_data();
- SculptSession *ss= sculpt_session();
- PropsetData *pd= sculpt_session()->propset;
- if(pd) {
- int i, j;
- const int tsz = 128;
- float *d;
- if(!pd->texdata) {
- pd->texdata= MEM_mallocN(sizeof(float)*tsz*tsz, "Brush preview");
- if(sd->texrept!=SCULPTREPT_3D)
- sculptmode_update_tex();
- for(i=0; i<tsz; ++i)
- for(j=0; j<tsz; ++j) {
- float magn= sqrt(pow(i-tsz/2,2)+pow(j-tsz/2,2));
- if(sd->texfade)
- pd->texdata[i*tsz+j]= curve_strength(magn,tsz/2);
- else
- pd->texdata[i*tsz+j]= magn < tsz/2 ? 1 : 0;
- }
- if(sd->texact != -1 && ss->texcache) {
- for(i=0; i<tsz; ++i)
- for(j=0; j<tsz; ++j) {
- const int col= ss->texcache[i*tsz+j];
- pd->texdata[i*tsz+j]*= (((char*)&col)[0]+((char*)&col)[1]+((char*)&col)[2])/3.0f/255.0f;
- }
- }
- }
-
- /* Adjust alpha with brush strength */
- d= MEM_dupallocN(pd->texdata);
- for(i=0; i<tsz; ++i)
- for(j=0; j<tsz; ++j)
- d[i*tsz+j]*= sculptmode_brush()->strength/200.0f+0.5f;
-
-
- if(!pd->tex)
- glGenTextures(1, (GLuint *)&pd->tex);
- glBindTexture(GL_TEXTURE_2D, pd->tex);
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tsz, tsz, 0, GL_ALPHA, GL_FLOAT, d);
- MEM_freeN(d);
- }
-}
-
-void sculptmode_propset_header()
-{
- SculptSession *ss= sculpt_session();
- PropsetData *pd= ss ? ss->propset : NULL;
- if(pd) {
- char str[512];
- const char *name= "";
- int val= 0;
- if(pd->mode == PropsetSize) {
- name= "Size";
- val= sculptmode_brush()->size;
- }
- else if(pd->mode == PropsetStrength) {
- name= "Strength";
- val= sculptmode_brush()->strength;
- }
- else if(pd->mode == PropsetTexRot) {
- name= "Texture Angle";
- val= tex_angle();
- }
- sprintf(str, "Brush %s: %d", name, val);
- headerprint(str);
- }
-}
-
-void sculptmode_propset_end(SculptSession *ss, int cancel)
-{
- if(ss && ss->propset) {
- PropsetData *pd= ss->propset;
-
- if(cancel) {
- sculptmode_brush()->size= pd->origsize;
- sculptmode_brush()->strength= pd->origstrength;
- set_tex_angle(pd->origtexrot);
- } else {
- if(pd->mode != PropsetSize)
- sculptmode_brush()->size= pd->origsize;
- if(pd->mode != PropsetStrength)
- sculptmode_brush()->strength= pd->origstrength;
- if(pd->mode != PropsetTexRot)
- set_tex_angle(pd->origtexrot);
- }
- glDeleteTextures(1, &pd->tex);
- MEM_freeN(pd->texdata);
- MEM_freeN(pd);
- ss->propset= NULL;
- allqueue(REDRAWVIEW3D, 0);
- allqueue(REDRAWBUTSEDIT, 0);
- allqueue(REDRAWHEADERS, 0);
- }
-}
-
-void sculptmode_propset_init(PropsetMode mode)
-{
- SculptSession *ss= sculpt_session();
- PropsetData *pd= ss->propset;
- const float ang= tex_angle();
-
- if(!pd) {
- short mouse[2];
-
- pd= MEM_callocN(sizeof(PropsetData),"PropsetSize");
- ss->propset= pd;
-
- getmouseco_areawin(mouse);
- pd->origloc[0]= mouse[0];
- pd->origloc[1]= mouse[1];
-
- if(mode == PropsetSize)
- pd->origloc[0]-= sculptmode_brush()->size;
- else if(mode == PropsetStrength)
- pd->origloc[0]-= 200 - 2*sculptmode_brush()->strength;
- else if(mode == PropsetTexRot) {
- pd->origloc[0]-= 200 * cos(to_rad(ang));
- pd->origloc[1]-= 200 * sin(to_rad(ang));
- }
-
- pd->origsize= sculptmode_brush()->size;
- pd->origstrength= sculptmode_brush()->strength;
- pd->origtexrot= ang;
-
- sculptmode_propset_calctex();
-
- pd->num.idx_max= 0;
- }
-
- pd->mode= mode;
- sculptmode_propset_header();
-
- allqueue(REDRAWVIEW3D, 0);
-}
-
-void sculpt_paint_brush(char clear)
-{
- if(sculpt_data()->flags & SCULPT_DRAW_BRUSH) {
- static short mvalo[2];
- short mval[2];
- const short rad= sculptmode_brush()->size;
-
- getmouseco_areawin(mval);
-
- persp(PERSP_WIN);
- if(clear)
- fdrawXORcirc(mval[0], mval[1], rad);
- else
- draw_sel_circle(mval, mvalo, rad, rad, 0);
-
- mvalo[0]= mval[0];
- mvalo[1]= mval[1];
- }
-}
-
-void sculptmode_propset(unsigned short event)
-{
- PropsetData *pd= sculpt_session()->propset;
- short mouse[2];
- short tmp[2];
- float dist;
- BrushData *brush= sculptmode_brush();
- char valset= 0;
-
- handleNumInput(&pd->num, event);
-
- if(hasNumInput(&pd->num)) {
- float val;
- applyNumInput(&pd->num, &val);
- if(pd->mode==PropsetSize)
- brush->size= val;
- else if(pd->mode==PropsetStrength)
- brush->strength= val;
- else if(pd->mode==PropsetTexRot)
- set_tex_angle(val);
- valset= 1;
- allqueue(REDRAWVIEW3D, 0);
- }
-
- switch(event) {
- case MOUSEX:
- case MOUSEY:
- if(!hasNumInput(&pd->num)) {
- char ctrl= G.qual & LR_CTRLKEY;
- getmouseco_areawin(mouse);
- tmp[0]= pd->origloc[0]-mouse[0];
- tmp[1]= pd->origloc[1]-mouse[1];
- dist= sqrt(tmp[0]*tmp[0]+tmp[1]*tmp[1]);
- if(pd->mode == PropsetSize) {
- brush->size= dist;
- if(ctrl) brush->size= (brush->size+5)/10*10;
- } else if(pd->mode == PropsetStrength) {
- float fin= (200.0f - dist) * 0.5f;
- brush->strength= fin>=0 ? fin : 0;
- if(ctrl) brush->strength= (brush->strength+5)/10*10;
- } else if(pd->mode == PropsetTexRot) {
- set_tex_angle((int)to_deg(atan2(tmp[1], tmp[0])) + 180);
- if(ctrl)
- set_tex_angle(((int)(tex_angle())+5)/10*10);
- }
- valset= 1;
- allqueue(REDRAWVIEW3D, 0);
- }
- break;
- case ESCKEY:
- case RIGHTMOUSE:
- brush->size= pd->origsize;
- brush->strength= pd->origstrength;
- set_tex_angle(pd->origtexrot);
- case LEFTMOUSE:
- while(get_mbut()==L_MOUSE);
- case RETKEY:
- case PADENTER:
- sculptmode_propset_end(sculpt_session(), 0);
- break;
- default:
- break;
- };
-
- if(valset) {
- if(pd->mode == PropsetSize) {
- if(brush->size<1) brush->size= 1;
- if(brush->size>200) brush->size= 200;
- }
- else if(pd->mode == PropsetStrength) {
- if(brush->strength > 100) brush->strength= 100;
- sculptmode_propset_calctex();
- }
- else if(pd->mode == PropsetTexRot) {
- if(tex_angle() < 0)
- set_tex_angle(0);
- else if(tex_angle() > 360)
- set_tex_angle(360);
- }
- }
-
- sculptmode_propset_header();
-}
-
-void sculptmode_selectbrush_menu(void)
-{
- SculptData *sd= sculpt_data();
- int val;
-
- pupmenu_set_active(sd->brush_type);
-
- val= pupmenu("Select Brush%t|Draw|Smooth|Pinch|Inflate|Grab|Layer|Flatten");
-
- if(val>0) {
- sd->brush_type= val;
-
- allqueue(REDRAWVIEW3D, 1);
- allqueue(REDRAWBUTSEDIT, 1);
- }
-}
-
-void sculptmode_update_all_projverts(float *vertcosnos)
-{
- Mesh *me= get_mesh(OBACT);
- unsigned i;
-
- if(!projverts)
- projverts = MEM_mallocN(sizeof(ProjVert)*me->totvert,"ProjVerts");
-
- for(i=0; i<me->totvert; ++i) {
- project(vertcosnos ? &vertcosnos[i * 6] : me->mvert[i].co, projverts[i].co);
- projverts[i].inside= 0;
- }
-}
-
-void sculptmode_draw_wires(int only_damaged, Mesh *me)
-{
- int i;
-
- bglPolygonOffset(1.0);
- glDepthMask(0);
- BIF_ThemeColor((OBACT==OBACT)?TH_ACTIVE:TH_SELECT);
-
- for(i=0; i<me->totedge; i++) {
- MEdge *med= &me->medge[i];
-
- if((!only_damaged || (projverts[med->v1].inside || projverts[med->v2].inside)) &&
- (med->flag & ME_EDGEDRAW)) {
- glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, &med->v1);
- }
- }
-
- glDepthMask(1);
- bglPolygonOffset(0.0);
-}
-
-void sculptmode_draw_mesh(int only_damaged)
-{
- Mesh *me= get_mesh(OBACT);
- int i, j, dt, drawCurrentMat = 1, matnr= -1;
-
- persp(PERSP_VIEW);
- mymultmatrix(OBACT->obmat);
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_LIGHTING);
- init_gl_materials(OBACT, 0);
- glEnable(GL_CULL_FACE);
-
- glShadeModel(GL_SMOOTH);
-
- glVertexPointer(3, GL_FLOAT, sizeof(MVert), &me->mvert[0].co);
- glNormalPointer(GL_SHORT, sizeof(MVert), &me->mvert[0].no);
-
- dt= MIN2(G.vd->drawtype, OBACT->dt);
- if(dt==OB_WIRE)
- glColorMask(0,0,0,0);
-
- for(i=0; i<me->totface; ++i) {
- MFace *f= &me->mface[i];
- char inside= 0;
- int new_matnr= f->mat_nr + 1;
-
- if(new_matnr != matnr)
- drawCurrentMat= set_gl_material(matnr = new_matnr);
-
- /* If only_damaged!=0, only draw faces that are partially
- inside the area(s) modified by the brush */
- if(only_damaged) {
- for(j=0; j<(f->v4?4:3); ++j) {
- if(projverts[*((&f->v1)+j)].inside) {
- inside= 1;
- break;
- }
- }
- }
- else
- inside= 1;
-
- if(inside && drawCurrentMat)
- glDrawElements(f->v4?GL_QUADS:GL_TRIANGLES, f->v4?4:3, GL_UNSIGNED_INT, &f->v1);
- }
-
- glDisable(GL_CULL_FACE);
- glDisable(GL_LIGHTING);
- glColorMask(1,1,1,1);
-
- if(dt==OB_WIRE || (OBACT->dtx & OB_DRAWWIRE))
- sculptmode_draw_wires(only_damaged, me);
-
- glDisable(GL_DEPTH_TEST);
-}
-
-void sculptmode_correct_state(void)
-{
- if(!sculpt_session())
- sculpt_init_session();
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_NORMAL_ARRAY);
-
- if(!sculpt_session()->vertex_users) calc_vertex_users();
-}
-
-/* Checks whether full update mode (slower) needs to be used to work with modifiers */
-char sculpt_modifiers_active(Object *ob)
-{
- ModifierData *md;
-
- for(md= modifiers_getVirtualModifierList(ob); md; md= md->next) {
- if(md->mode & eModifierMode_Realtime)
- return 1;
- }
-
- return 0;
-}
-
-void sculpt(void)
-{
- SculptData *sd= sculpt_data();
- SculptSession *ss= sculpt_session();
- Object *ob= OBACT;
- /* lastSigMouse is for the rake, to store the last place the mouse movement was significant */
- short mouse[2], mvalo[2], lastSigMouse[2],firsttime=1, mousebut;
- short modifier_calculations= 0;
- EditData e;
- short spacing= 32000;
- int scissor_box[4];
- float offsetRot;
- if(!(G.f & G_SCULPTMODE) || G.obedit || !ob || ob->id.lib || !get_mesh(ob) || (get_mesh(ob)->totface == 0))
- return;
- if(!(ob->lay & G.vd->lay))
- error("Active object is not in this layer");
- if(ob_get_keyblock(ob)) {
- if(!(ob->shapeflag & OB_SHAPE_LOCK)) {
- error("Cannot sculpt on unlocked shape key");
- return;
- }
- }
-
- if(!ss) {
- sculpt_init_session();
- ss= sd->session;
- }
-
- if(sd->flags & SCULPT_INPUT_SMOOTH)
- sculpt_stroke_new(256);
-
- ss->damaged_rects.first = ss->damaged_rects.last = NULL;
- ss->damaged_verts.first = ss->damaged_verts.last = NULL;
- ss->vertexcosnos = NULL;
-
- /* Check that vertex users are up-to-date */
- if(ob != active_ob || !ss->vertex_users || ss->vertex_users_size != get_mesh(ob)->totvert) {
- sculptmode_free_vertexusers(ss);
- calc_vertex_users();
- if(projverts)
- MEM_freeN(projverts);
- projverts = NULL;
- active_ob= ob;
- }
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_NORMAL_ARRAY);
-
- persp(PERSP_VIEW);
-
- getmouseco_areawin(mvalo);
-
- /* Init texture
- FIXME: Shouldn't be doing this every time! */
- if(sd->texrept!=SCULPTREPT_3D)
- sculptmode_update_tex();
-
- getmouseco_areawin(mouse);
- mvalo[0]= mouse[0];
- mvalo[1]= mouse[1];
- lastSigMouse[0]=mouse[0];
- lastSigMouse[1]=mouse[1];
- mousebut = L_MOUSE;
-
- /* If modifier_calculations is true, then extra time must be spent
- updating the mesh. This takes a *lot* longer, so it's worth
- skipping if the modifier stack is empty. */
- modifier_calculations= sculpt_modifiers_active(ob);
-
- init_sculptmatrices();
-
- if(modifier_calculations)
- ss->vertexcosnos= mesh_get_mapped_verts_nors(ob);
- sculptmode_update_all_projverts(ss->vertexcosnos);
-
- e.grabdata= NULL;
- e.layer_disps= NULL;
- e.layer_store= NULL;
-
- /* Set scaling adjustment */
- e.scale[0]= 1.0f / ob->size[0];
- e.scale[1]= 1.0f / ob->size[1];
- e.scale[2]= 1.0f / ob->size[2];
-
- /* Capture original copy */
- if(sd->flags & SCULPT_DRAW_FAST)
- glAccum(GL_LOAD, 1);
-
- /* Get original scissor box */
- glGetIntegerv(GL_SCISSOR_BOX, scissor_box);
-
- /* For raking, get the original angle*/
- offsetRot=tex_angle();
-
- while (get_mbut() & mousebut) {
- getmouseco_areawin(mouse);
- /* If rake, and the mouse has moved over 10 pixels (euclidean) (prevents jitter) then get the new angle */
- if (sd->rake && (pow(lastSigMouse[0]-mouse[0],2)+pow(lastSigMouse[1]-mouse[1],2))>100){
- /*Nasty looking, but just orig + new angle really*/
- set_tex_angle(offsetRot+180.+to_deg(atan2((float)(mouse[1]-lastSigMouse[1]),(float)(mouse[0]-lastSigMouse[0]))));
- lastSigMouse[0]=mouse[0];
- lastSigMouse[1]=mouse[1];
- }
-
- if(firsttime || mouse[0]!=mvalo[0] || mouse[1]!=mvalo[1] || sculptmode_brush()->airbrush) {
- firsttime= 0;
-
- if(sd->flags & SCULPT_INPUT_SMOOTH)
- sculpt_stroke_add_point(mouse[0], mouse[1]);
-
- spacing+= sqrt(pow(mvalo[0]-mouse[0],2)+pow(mvalo[1]-mouse[1],2));
-
- if(modifier_calculations && !ss->vertexcosnos)
- ss->vertexcosnos= mesh_get_mapped_verts_nors(ob);
-
- if(G.scene->sculptdata.brush_type != GRAB_BRUSH) {
- if(sd->flags & SCULPT_INPUT_SMOOTH) {
- sculpt_stroke_apply(&e);
- }
- else if(sd->spacing==0 || spacing>sd->spacing) {
- do_symmetrical_brush_actions(&e, mouse, NULL);
- spacing= 0;
- }
- }
- else {
- do_symmetrical_brush_actions(&e, mouse, mvalo);
- ss->pivot= unproject(mouse[0],mouse[1],e.grabdata->depth);
- }
-
- if(modifier_calculations || ob_get_keyblock(ob))
- DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
-
- if(modifier_calculations || sd->brush_type == GRAB_BRUSH || !(sd->flags & SCULPT_DRAW_FAST)) {
- calc_damaged_verts(&ss->damaged_verts,e.grabdata);
- scrarea_do_windraw(curarea);
- screen_swapbuffers();
- } else { /* Optimized drawing */
- calc_damaged_verts(&ss->damaged_verts,e.grabdata);
-
- /* Draw the stored image to the screen */
- glAccum(GL_RETURN, 1);
-
- sculpt_clear_damaged_areas(ss);
-
- /* Draw all the polygons that are inside the modified area(s) */
- glScissor(scissor_box[0], scissor_box[1], scissor_box[2], scissor_box[3]);
- sculptmode_draw_mesh(1);
- glAccum(GL_LOAD, 1);
-
- projverts_clear_inside();
-
- persp(PERSP_WIN);
- glDisable(GL_DEPTH_TEST);
-
- /* Draw cursor */
- if(sculpt_data()->flags & SCULPT_DRAW_BRUSH)
- fdrawXORcirc((float)mouse[0],(float)mouse[1],sculptmode_brush()->size);
- if(sculpt_data()->flags & SCULPT_INPUT_SMOOTH)
- sculpt_stroke_draw();
-
- myswapbuffers();
- }
-
- BLI_freelistN(&ss->damaged_rects);
- ss->damaged_rects.first = ss->damaged_rects.last = NULL;
-
- mvalo[0]= mouse[0];
- mvalo[1]= mouse[1];
-
- if(ss->vertexcosnos) {
- MEM_freeN(ss->vertexcosnos);
- ss->vertexcosnos= NULL;
- }
-
- }
- else BIF_wait_for_statechange();
- }
-
- /* Set the rotation of the brush back to what it was before any rake */
- set_tex_angle(offsetRot);
-
- if(sd->flags & SCULPT_INPUT_SMOOTH) {
- sculpt_stroke_apply_all(&e);
- calc_damaged_verts(&ss->damaged_verts,e.grabdata);
- BLI_freelistN(&ss->damaged_rects);
- }
-
- if(e.layer_disps) MEM_freeN(e.layer_disps);
- if(e.layer_store) MEM_freeN(e.layer_store);
- /* Free GrabData */
- if(e.grabdata) {
- int i;
- for(i=0; i<8; ++i)
- BLI_freelistN(&e.grabdata->active_verts[i]);
- MEM_freeN(e.grabdata);
- }
- sculpt_stroke_free();
-
- sculpt_undo_push(G.scene->sculptdata.brush_type);
-
- if(G.vd->depths) G.vd->depths->damaged= 1;
-
- allqueue(REDRAWVIEW3D, 0);
-}
-
-void sculpt_undo_push(const short brush_type)
-{
- switch(brush_type) {
- case DRAW_BRUSH:
- BIF_undo_push("Draw Brush"); break;
- case SMOOTH_BRUSH:
- BIF_undo_push("Smooth Brush"); break;
- case PINCH_BRUSH:
- BIF_undo_push("Pinch Brush"); break;
- case INFLATE_BRUSH:
- BIF_undo_push("Inflate Brush"); break;
- case GRAB_BRUSH:
- BIF_undo_push("Grab Brush"); break;
- case LAYER_BRUSH:
- BIF_undo_push("Layer Brush"); break;
- case FLATTEN_BRUSH:
- BIF_undo_push("Flatten Brush"); break;
- default:
- BIF_undo_push("Sculpting"); break;
- }
-}
-
-void set_sculptmode(void)
-{
- if(G.f & G_SCULPTMODE) {
- Mesh *me= get_mesh(OBACT);
-
- G.f &= ~G_SCULPTMODE;
-
- sculptmode_free_session(G.scene);
- if(me && me->pv)
- sculptmode_pmv_off(me);
- }
- else {
- G.f |= G_SCULPTMODE;
-
- /* Called here to sanity-check the brush */
- sculptmode_brush();
-
- sculpt_init_session();
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_NORMAL_ARRAY);
- }
-
- active_ob= NULL;
-
- allqueue(REDRAWVIEW3D, 1);
- allqueue(REDRAWBUTSEDIT, 0);
-}
-
-/* Partial Mesh Visibility */
-PartialVisibility *sculptmode_copy_pmv(PartialVisibility *pmv)
-{
- PartialVisibility *n= MEM_dupallocN(pmv);
- n->vert_map= MEM_dupallocN(pmv->vert_map);
- n->edge_map= MEM_dupallocN(pmv->edge_map);
- n->old_edges= MEM_dupallocN(pmv->old_edges);
- n->old_faces= MEM_dupallocN(pmv->old_faces);
- return n;
-}
-
-void sculptmode_pmv_free(PartialVisibility *pv)
-{
- MEM_freeN(pv->vert_map);
- MEM_freeN(pv->edge_map);
- MEM_freeN(pv->old_faces);
- MEM_freeN(pv->old_edges);
- MEM_freeN(pv);
-}
-
-void sculptmode_revert_pmv(Mesh *me)
-{
- if(me->pv) {
- unsigned i;
- MVert *nve, *old_verts;
-
- active_ob= NULL;
-
- /* Reorder vertices */
- nve= me->mvert;
- old_verts = MEM_mallocN(sizeof(MVert)*me->pv->totvert,"PMV revert verts");
- for(i=0; i<me->pv->totvert; ++i)
- old_verts[i]= nve[me->pv->vert_map[i]];
-
- /* Restore verts, edges and faces */
- CustomData_free_layer_active(&me->vdata, CD_MVERT, me->totvert);
- CustomData_free_layer_active(&me->edata, CD_MEDGE, me->totedge);
- CustomData_free_layer_active(&me->fdata, CD_MFACE, me->totface);
-
- CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, old_verts, me->pv->totvert);
- CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, me->pv->old_edges, me->pv->totedge);
- CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, me->pv->old_faces, me->pv->totface);
- mesh_update_customdata_pointers(me);
-
- me->totvert= me->pv->totvert;
- me->totedge= me->pv->totedge;
- me->totface= me->pv->totface;
-
- me->pv->old_edges= NULL;
- me->pv->old_faces= NULL;
-
- /* Free maps */
- MEM_freeN(me->pv->edge_map);
- me->pv->edge_map= NULL;
- MEM_freeN(me->pv->vert_map);
- me->pv->vert_map= NULL;
-
- DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
- }
-}
-
-void sculptmode_pmv_off(Mesh *me)
-{
- if(me->pv) {
- sculptmode_revert_pmv(me);
- MEM_freeN(me->pv);
- me->pv= NULL;
- }
-}
-
-/* mode: 0=hide outside selection, 1=hide inside selection */
-void sculptmode_do_pmv(Object *ob, rcti *hb_2d, int mode)
-{
- Mesh *me= get_mesh(ob);
- vec3f hidebox[6];
- vec3f plane_normals[4];
- float plane_ds[4];
- unsigned i, j;
- unsigned ndx_show, ndx_hide;
- MVert *nve;
- unsigned face_cnt_show= 0, face_ndx_show= 0;
- unsigned edge_cnt_show= 0, edge_ndx_show= 0;
- unsigned *old_map= NULL;
- const unsigned SHOW= 0, HIDE=1;
-
- /* Convert hide box from 2D to 3D */
- hidebox[0]= unproject(hb_2d->xmin, hb_2d->ymax, 1);
- hidebox[1]= unproject(hb_2d->xmax, hb_2d->ymax, 1);
- hidebox[2]= unproject(hb_2d->xmax, hb_2d->ymin, 1);
- hidebox[3]= unproject(hb_2d->xmin, hb_2d->ymin, 1);
- hidebox[4]= unproject(hb_2d->xmin, hb_2d->ymax, 0);
- hidebox[5]= unproject(hb_2d->xmax, hb_2d->ymin, 0);
-
- /* Calculate normals for each side of hide box */
- CalcNormFloat(&hidebox[0].x,&hidebox[1].x,&hidebox[4].x,&plane_normals[0].x);
- CalcNormFloat(&hidebox[1].x,&hidebox[2].x,&hidebox[5].x,&plane_normals[1].x);
- CalcNormFloat(&hidebox[2].x,&hidebox[3].x,&hidebox[5].x,&plane_normals[2].x);
- CalcNormFloat(&hidebox[3].x,&hidebox[0].x,&hidebox[4].x,&plane_normals[3].x);
-
- /* Calculate D for each side of hide box */
- for(i= 0; i<4; ++i)
- plane_ds[i]= hidebox[i].x*plane_normals[i].x + hidebox[i].y*plane_normals[i].y +
- hidebox[i].z*plane_normals[i].z;
-
- /* Add partial visibility to mesh */
- if(!me->pv) {
- me->pv= MEM_callocN(sizeof(PartialVisibility),"PartialVisibility");
- } else {
- old_map= MEM_callocN(sizeof(unsigned)*me->pv->totvert,"PMV oldmap");
- for(i=0; i<me->pv->totvert; ++i) {
- old_map[i]= me->pv->vert_map[i]<me->totvert?0:1;
- }
- sculptmode_revert_pmv(me);
- }
-
- /* Kill sculpt data */
- active_ob= NULL;
-
- /* Initalize map with which verts are to be hidden */
- me->pv->vert_map= MEM_mallocN(sizeof(unsigned)*me->totvert, "PMV vertmap");
- me->pv->totvert= me->totvert;
- me->totvert= 0;
- for(i=0; i<me->pv->totvert; ++i) {
- me->pv->vert_map[i]= mode ? HIDE:SHOW;
- for(j=0; j<4; ++j) {
- if(me->mvert[i].co[0] * plane_normals[j].x +
- me->mvert[i].co[1] * plane_normals[j].y +
- me->mvert[i].co[2] * plane_normals[j].z < plane_ds[j] ) {
- me->pv->vert_map[i]= mode ? SHOW:HIDE; /* Vert is outside the hide box */
- break;
- }
- }
- if(old_map && old_map[i]) me->pv->vert_map[i]= 1;
- if(!me->pv->vert_map[i]) ++me->totvert;
-
- }
- if(old_map) MEM_freeN(old_map);
-
- /* Find out how many faces to show */
- for(i=0; i<me->totface; ++i) {
- if(!me->pv->vert_map[me->mface[i].v1] &&
- !me->pv->vert_map[me->mface[i].v2] &&
- !me->pv->vert_map[me->mface[i].v3]) {
- if(me->mface[i].v4) {
- if(!me->pv->vert_map[me->mface[i].v4])
- ++face_cnt_show;
- }
- else ++face_cnt_show;
- }
- }
- /* Find out how many edges to show */
- for(i=0; i<me->totedge; ++i) {
- if(!me->pv->vert_map[me->medge[i].v1] &&
- !me->pv->vert_map[me->medge[i].v2])
- ++edge_cnt_show;
- }
-
- /* Create new vert array and reset each vert's map with map[old]=new index */
- nve= MEM_mallocN(sizeof(MVert)*me->pv->totvert, "PMV verts");
- ndx_show= 0; ndx_hide= me->totvert;
- for(i=0; i<me->pv->totvert; ++i) {
- if(me->pv->vert_map[i]) {
- me->pv->vert_map[i]= ndx_hide;
- nve[me->pv->vert_map[i]]= me->mvert[i];
- ++ndx_hide;
- } else {
- me->pv->vert_map[i]= ndx_show;
- nve[me->pv->vert_map[i]]= me->mvert[i];
- ++ndx_show;
- }
- }
- CustomData_free_layer_active(&me->vdata, CD_MVERT, me->pv->totvert);
- me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, nve, me->totvert);
-
- /* Create new face array */
- me->pv->old_faces= me->mface;
- me->pv->totface= me->totface;
- me->mface= MEM_mallocN(sizeof(MFace)*face_cnt_show, "PMV faces");
- for(i=0; i<me->totface; ++i) {
- MFace *pr_f= &me->pv->old_faces[i];
- char show= 0;
-
- if(me->pv->vert_map[pr_f->v1] < me->totvert &&
- me->pv->vert_map[pr_f->v2] < me->totvert &&
- me->pv->vert_map[pr_f->v3] < me->totvert) {
- if(pr_f->v4) {
- if(me->pv->vert_map[pr_f->v4] < me->totvert)
- show= 1;
- }
- else show= 1;
- }
-
- if(show) {
- MFace *cr_f= &me->mface[face_ndx_show];
- *cr_f= *pr_f;
- cr_f->v1= me->pv->vert_map[pr_f->v1];
- cr_f->v2= me->pv->vert_map[pr_f->v2];
- cr_f->v3= me->pv->vert_map[pr_f->v3];
- cr_f->v4= pr_f->v4 ? me->pv->vert_map[pr_f->v4] : 0;
- test_index_face(cr_f,NULL,0,pr_f->v4?4:3);
- ++face_ndx_show;
- }
- }
- me->totface= face_cnt_show;
- CustomData_set_layer(&me->fdata, CD_MFACE, me->mface);
-
- /* Create new edge array */
- me->pv->old_edges= me->medge;
- me->pv->totedge= me->totedge;
- me->medge= MEM_mallocN(sizeof(MEdge)*edge_cnt_show, "PMV edges");
- me->pv->edge_map= MEM_mallocN(sizeof(int)*me->pv->totedge,"PMV edgemap");
- for(i=0; i<me->totedge; ++i) {
- if(me->pv->vert_map[me->pv->old_edges[i].v1] < me->totvert &&
- me->pv->vert_map[me->pv->old_edges[i].v2] < me->totvert) {
- MEdge *cr_e= &me->medge[edge_ndx_show];
- me->pv->edge_map[i]= edge_ndx_show;
- *cr_e= me->pv->old_edges[i];
- cr_e->v1= me->pv->vert_map[me->pv->old_edges[i].v1];
- cr_e->v2= me->pv->vert_map[me->pv->old_edges[i].v2];
- ++edge_ndx_show;
- }
- else me->pv->edge_map[i]= -1;
- }
- me->totedge= edge_cnt_show;
- CustomData_set_layer(&me->edata, CD_MEDGE, me->medge);
-
- DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
-}
-
-rcti sculptmode_pmv_box()
-{
- short down[2], mouse[2];
- rcti ret;
-
- getmouseco_areawin(down);
-
- while((get_mbut()&L_MOUSE) || (get_mbut()&R_MOUSE)) {
- getmouseco_areawin(mouse);
-
- scrarea_do_windraw(curarea);
-
- persp(PERSP_WIN);
- glLineWidth(2);
- setlinestyle(2);
- sdrawXORline(down[0],down[1],mouse[0],down[1]);
- sdrawXORline(mouse[0],down[1],mouse[0],mouse[1]);
- sdrawXORline(mouse[0],mouse[1],down[0],mouse[1]);
- sdrawXORline(down[0],mouse[1],down[0],down[1]);
- setlinestyle(0);
- glLineWidth(1);
- persp(PERSP_VIEW);
-
- screen_swapbuffers();
- backdrawview3d(0);
- }
-
- ret.xmin= down[0]<mouse[0]?down[0]:mouse[0];
- ret.ymin= down[1]<mouse[1]?down[1]:mouse[1];
- ret.xmax= down[0]>mouse[0]?down[0]:mouse[0];
- ret.ymax= down[1]>mouse[1]?down[1]:mouse[1];
- return ret;
-}
-
-void sculptmode_pmv(int mode)
-{
- Object *ob= OBACT;
- rcti hb_2d;
-
- if(ob_get_key(ob)) {
- error("Cannot hide mesh with shape keys enabled");
- return;
- }
-
- hb_2d= sculptmode_pmv_box(); /* Get 2D hide box */
-
- sculptmode_correct_state();
-
- waitcursor(1);
-
- if(hb_2d.xmax-hb_2d.xmin > 3 && hb_2d.ymax-hb_2d.ymin > 3) {
- init_sculptmatrices();
-
- sculptmode_do_pmv(ob,&hb_2d,mode);
- }
- else sculptmode_pmv_off(get_mesh(ob));
-
- scrarea_do_windraw(curarea);
-
- BIF_undo_push("Partial mesh hide");
-
- waitcursor(0);
-}