This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/src/drawobject.c
Ton Roosendaal 422b69fe1e UI cleanup work;
Proportional edit:

- Proportional mode added to header as button/menu. Including new option
  to have only connected geometry influenced.
- Added icons for proportional & proportional modes
- Make proportional edit data part of Scene, so all gets saved.
  The Global flag G_PROPORTIONAL was removed
- Made sure #defines get used properly, also tweaked order for proportional
  so it starts with regular 'smooth' by default.
- Use ALT+O in editmode to switch to new proportional 'connected' mode

Other UI stuff:

- in EditMode, the layer buttons get hidden... the amount of icons in
  3d header grows to fast. :)
- made less ugly icons for the Manipulators. Still can be better.
- Added alpha-filter for pre-processing Icon-image, giving nicer display
  of icon-antialising on dark or bright backdrops
- disabled Manipulators when in editmode, and current layers don't show
  the edited data.
- Added the value used to define Normal size (editmode draw) in Scene too,
  so it gets saved.
2005-05-03 10:54:42 +00:00

3990 lines
93 KiB
C

/**
* $Id$
*
* ***** BEGIN GPL/BL DUAL 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. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* 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/BL DUAL LICENSE BLOCK *****
*/
#include <string.h>
#include <math.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "MEM_guardedalloc.h"
#include "BMF_Api.h"
#include "IMB_imbuf.h"
#include "MTC_matrixops.h"
#include "DNA_camera_types.h"
#include "DNA_curve_types.h"
#include "DNA_constraint_types.h" // for drawing constraint
#include "DNA_effect_types.h"
#include "DNA_ipo_types.h"
#include "DNA_lamp_types.h"
#include "DNA_lattice_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
#include "DNA_space_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BLI_editVert.h"
#include "BKE_utildefines.h"
#include "BKE_curve.h"
#include "BKE_constraint.h" // for the get_constraint_target function
#include "BKE_deform.h" // lattice_modifier()
#include "BKE_DerivedMesh.h"
#include "BKE_displist.h"
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_ipo.h"
#include "BKE_lattice.h"
#include "BKE_mesh.h"
#include "BKE_material.h"
#include "BKE_mball.h"
#include "BKE_object.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "BIF_mywindow.h"
#include "BIF_screen.h"
#include "BIF_space.h"
#include "BIF_editarmature.h"
#include "BIF_editika.h"
#include "BIF_editmesh.h"
#include "BIF_glutil.h"
#include "BIF_resources.h"
#include "BDR_drawmesh.h"
#include "BDR_drawobject.h"
#include "BDR_editobject.h"
#include "BSE_view.h"
#include "BSE_drawview.h"
#include "BSE_trans_types.h"
#include "blendef.h"
#include "mydevice.h"
#include "nla.h"
#include "BKE_deform.h"
/* pretty stupid */
/* extern Lattice *editLatt; already in BKE_lattice.h */
/* editcurve.c */
extern ListBase editNurb;
/* editmball.c */
extern ListBase editelems;
static void draw_bounding_volume(Object *ob);
/***/
// Materials start counting at # one....
#define MAXMATBUF (MAXMAT + 1)
static float matbuf[MAXMATBUF][2][4];
static int last_gl_matnr=-1;
static void init_gl_materials(Object *ob)
{
extern Material defmaterial; // render module abuse...
Material *ma;
int a;
if(ob->totcol==0) {
matbuf[0][0][0]= defmaterial.r;
matbuf[0][0][1]= defmaterial.g;
matbuf[0][0][2]= defmaterial.b;
matbuf[0][0][3]= 1.0;
matbuf[0][1][0]= defmaterial.specr;
matbuf[0][1][1]= defmaterial.specg;
matbuf[0][1][2]= defmaterial.specb;
matbuf[0][1][3]= 1.0;
/* do material 1 too, for displists! */
VECCOPY(matbuf[1][0], matbuf[0][0]);
VECCOPY(matbuf[1][1], matbuf[0][1]);
}
for(a=1; a<=ob->totcol; a++) {
ma= give_current_material(ob, a);
if(ma==NULL) ma= &defmaterial;
if(a<MAXMATBUF) {
matbuf[a][0][0]= (ma->ref+ma->emit)*ma->r;
matbuf[a][0][1]= (ma->ref+ma->emit)*ma->g;
matbuf[a][0][2]= (ma->ref+ma->emit)*ma->b;
matbuf[a][0][3]= 1.0;
matbuf[a][1][0]= ma->spec*ma->specr;
matbuf[a][1][1]= ma->spec*ma->specg;
matbuf[a][1][2]= ma->spec*ma->specb;
matbuf[a][1][3]= 1.0;
}
}
last_gl_matnr = -1;
}
static void set_gl_material(int nr)
{
if(nr<MAXMATBUF && nr!=last_gl_matnr) {
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matbuf[nr][0]);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matbuf[nr][1]);
last_gl_matnr = nr;
}
}
/***/
unsigned int rect_desel[16]= {0x707070,0x0,0x0,0x707070,0x407070,0x70cccc,0x407070,0x0,0xaaffff,0xffffff,0x70cccc,0x0,0x70cccc,0xaaffff,0x407070,0x707070};
unsigned int rect_sel[16]= {0x707070,0x0,0x0,0x707070,0x702070,0xcc50cc,0x702070,0x0,0xff80ff,0xffffff,0xcc50cc,0x0,0xcc50cc,0xff80ff,0x702070,0x707070};
unsigned int rectu_desel[16]= {0xff4e4e4e,0xff5c2309,0xff000000,0xff4e4f4d,0xff000000,0xffff9d72,0xffff601c,0xff000000,0xff5d2409,0xffffffff,0xffff9d72,0xff5b2209,0xff4e4e4e,0xff5c2309,0xff010100,0xff4f4f4f};
unsigned int rectu_sel[16]= {0xff4e4e4e,0xff403c00,0xff000000,0xff4e4e4d,0xff000000,0xfffff64c,0xffaaa100,0xff000000,0xff403c00,0xffffffff,0xfffff64c,0xff403c00,0xff4f4f4f,0xff403c00,0xff010100,0xff4e4e4e};
unsigned int rectl_desel[81]= {0x777777,0x777777,0xa9fefe,0xaaffff,0xaaffff,0xaaffff,0xaaffff,0x777777,0x777777,0x777777,0xa9fefe,0xaafefe,0x777777,0x777777,0x777777,0xa9fefe,0xa9fefe,0x777777,0xaaffff,0xa9fefe,0x4e4e4e,0x0,0x124040,0x0,0x4e4e4e,0xaafefe,0xaaffff,0xaaffff,0x777777,0x0,0x227777,0x55cccc,0x227777,0x0,0x777777,0xaaffff,0xaaffff,0x777777,0x124040,0x88ffff,0xffffff,0x55cccc,0x124040,0x777777,0xaaffff,0xaaffff,0x777777,0x0,0x55cccc,0x88ffff,0x227777,0x0,0x777777,0xaaffff,0xaafefe,0xaafefe,0x4f4f4f,0x0,0x124040,0x0,0x4e4e4e,0xa9fefe,0xaaffff,0x777777,0xa9fefe,0xa9fefe,0x777777,0x777777,0x777777,0xa9fefe,0xa9fefe,0x777777,0x777777,0x777777,0xa9fefe,0xa9fefe,0xaaffff,0xaaffff,0xaaffff,0x777777,0x777777};
unsigned int rectl_sel[81]= {0x777777,0x777777,0xffaaff,0xffaaff,0xffaaff,0xffaaff,0xffaaff,0x777777,0x777777,0x777777,0xffaaff,0xffaaff,0x777777,0x777777,0x777777,0xffaaff,0xffaaff,0x777777,0xffaaff,0xffaaff,0x4e4e4e,0x10101,0x402440,0x0,0x4e4e4e,0xffaaff,0xffaaff,0xffaaff,0x777777,0x0,0x774477,0xcc77cc,0x774477,0x0,0x777777,0xffaaff,0xffaaff,0x777777,0x402440,0xffaaff,0xffffff,0xcc77cc,0x412541,0x777777,0xffaaff,0xffaaff,0x777777,0x10101,0xcc77cc,0xffaaff,0x774477,0x0,0x777777,0xffaaff,0xffaaff,0xffaaff,0x4e4e4e,0x10101,0x402440,0x0,0x4e4e4e,0xffaaff,0xffaaff,0x777777,0xffaaff,0xffaaff,0x777777,0x777777,0x777777,0xffaaff,0xffaaff,0x777777,0x777777,0x777777,0xffaaff,0xffaaff,0xffaaff,0xffaaff,0xffaaff,0x777777,0x777777};
unsigned int rectlus_desel[81]= {0x777777,0x777777,0xa9fefe,0xaaffff,0xaaffff,0xaaffff,0xaaffff,0x777777,0x777777,0x777777,0xa9fefe,0xaafefe,0x777777,0x777777,0x777777,0xa9fefe,0xa9fefe,0x777777,0xaaffff,0xa9fefe,0x4e4e4e,0x0,0x5c2309,0x0,0x4e4f4d,0xaafefe,0xaaffff,0xaaffff,0x777777,0x0,0xff601c,0xff9d72,0xff601c,0x0,0x777777,0xaaffff,0xaaffff,0x777777,0x5d2409,0xffceb8,0xff9d72,0xff9d72,0x5b2209,0x777777,0xaaffff,0xaaffff,0x777777,0x10100,0xffceb8,0xffceb8,0xff601c,0x0,0x777777,0xaaffff,0xaafefe,0xaafefe,0x4e4e4e,0x0,0x5c2309,0x10100,0x4f4f4f,0xa9fefe,0xaaffff,0x777777,0xa9fefe,0xa9fefe,0x777777,0x777777,0x777777,0xa9fefe,0xa9fefe,0x777777,0x777777,0x777777,0xa9fefe,0xa9fefe,0xaaffff,0xaaffff,0xaaffff,0x777777,0x777777};
unsigned int rectlus_sel[81]= {0x777777,0x777777,0xffaaff,0xffaaff,0xffaaff,0xffaaff,0xffaaff,0x777777,0x777777,0x777777,0xffaaff,0xffaaff,0x777777,0x777777,0x777777,0xffaaff,0xffaaff,0x777777,0xffaaff,0xffaaff,0x4e4e4e,0x10100,0x403c00,0x0,0x4e4e4d,0xffaaff,0xffaaff,0xffaaff,0x777777,0x0,0xaaa100,0xfff64c,0xaaa100,0x0,0x777777,0xffaaff,0xffaaff,0x777777,0x403c00,0xfffde2,0xffffff,0xfff64c,0x403c00,0x777777,0xffaaff,0xffaaff,0x777777,0x10100,0xfff64c,0xfffde2,0xaaa100,0x0,0x777777,0xffaaff,0xffaaff,0xffaaff,0x4f4f4f,0x0,0x403c00,0x10100,0x4e4e4e,0xffaaff,0xffaaff,0x777777,0xffaaff,0xffaaff,0x777777,0x777777,0x777777,0xffaaff,0xffaaff,0x777777,0x777777,0x777777,0xffaaff,0xffaaff,0xffaaff,0xffaaff,0xffaaff,0x777777,0x777777};
unsigned int rectllib_desel[81]= {0xff777777,0xff777777,0xb9b237,0xb9b237,0xb9b237,0xb9b237,0xb9b237,0xff777777,0xff777777,0xff777777,0xb9b237,0xb9b237,0xff777777,0xff777777,0xff777777,0xb9b237,0xb9b237,0xff777777,0xb9b237,0xb9b237,0x4e4e4e,0x0,0x5c2309,0x0,0x4e4f4d,0xb9b237,0xb9b237,0xb9b237,0xff777777,0x0,0xff601c,0xff9d72,0xff601c,0x0,0xff777777,0xb9b237,0xb9b237,0xff777777,0x5d2409,0xffceb8,0xff9d72,0xff9d72,0x5b2209,0xff777777,0xb9b237,0xb9b237,0xff777777,0x10100,0xffceb8,0xffceb8,0xff601c,0x0,0xff777777,0xb9b237,0xb9b237,0xb9b237,0x4e4e4e,0x0,0x5c2309,0x10100,0x4f4f4f,0xb9b237,0xb9b237,0xff777777,0xb9b237,0xb9b237,0xff777777,0xff777777,0xff777777,0xb9b237,0xb9b237,0xff777777,0xff777777,0xff777777,0xb9b237,0xb9b237,0xb9b237,0xb9b237,0xb9b237,0xff777777,0xff777777};
unsigned int rectllib_sel[81]= {0xff777777,0xff777777,0xfff64c,0xfff64c,0xfff64c,0xfff64c,0xfff64c,0xff777777,0xff777777,0xff777777,0xfff64c,0xfff64c,0xff777777,0xff777777,0xff777777,0xfff64c,0xfff64c,0xff777777,0xfff64c,0xfff64c,0x4e4e4e,0x10100,0x403c00,0x0,0x4e4e4d,0xfff64c,0xfff64c,0xfff64c,0xff777777,0x0,0xaaa100,0xfff64c,0xaaa100,0x0,0xff777777,0xfff64c,0xfff64c,0xff777777,0x403c00,0xfffde2,0xffffff,0xfff64c,0x403c00,0xff777777,0xfff64c,0xfff64c,0xff777777,0x10100,0xfff64c,0xfffde2,0xaaa100,0x0,0xff777777,0xfff64c,0xfff64c,0xfff64c,0x4f4f4f,0x0,0x403c00,0x10100,0x4e4e4e,0xfff64c,0xfff64c,0xff777777,0xfff64c,0xfff64c,0xff777777,0xff777777,0xff777777,0xfff64c,0xfff64c,0xff777777,0xff777777,0xff777777,0xfff64c,0xfff64c,0xfff64c,0xfff64c,0xfff64c,0xff777777,0xff777777};
unsigned int rectl_set[81]= {0xff777777,0xff777777,0xaaaaaa,0xaaaaaa,0xaaaaaa,0xaaaaaa,0xaaaaaa,0xff777777,0xff777777,0xff777777,0xaaaaaa,0xaaaaaa,0xff777777,0xff777777,0xff777777,0xaaaaaa,0xaaaaaa,0xff777777,0xaaaaaa,0xaaaaaa,0x4e4e4e,0x10100,0x202020,0x0,0x4e4e4d,0xaaaaaa,0xaaaaaa,0xaaaaaa,0xff777777,0x0,0xaaa100,0xaaaaaa,0xaaa100,0x0,0xff777777,0xaaaaaa,0xaaaaaa,0xff777777,0x202020,0xfffde2,0xffffff,0xaaaaaa,0x202020,0xff777777,0xaaaaaa,0xaaaaaa,0xff777777,0x10100,0xaaaaaa,0xfffde2,0xaaa100,0x0,0xff777777,0xaaaaaa,0xaaaaaa,0xaaaaaa,0x4f4f4f,0x0,0x202020,0x10100,0x4e4e4e,0xaaaaaa,0xaaaaaa,0xff777777,0xaaaaaa,0xaaaaaa,0xff777777,0xff777777,0xff777777,0xaaaaaa,0xaaaaaa,0xff777777,0xff777777,0xff777777,0xaaaaaa,0xaaaaaa,0xaaaaaa,0xaaaaaa,0xaaaaaa,0xff777777,0xff777777};
static unsigned int colortab[24]=
{0x0, 0xFF88FF, 0xFFBBFF,
0x403000, 0xFFFF88, 0xFFFFBB,
0x104040, 0x66CCCC, 0x77CCCC,
0x101040, 0x5588FF, 0x88BBFF,
0xFFFFFF
};
static float cube[8][3] = {
{-1.0, -1.0, -1.0},
{-1.0, -1.0, 1.0},
{-1.0, 1.0, 1.0},
{-1.0, 1.0, -1.0},
{ 1.0, -1.0, -1.0},
{ 1.0, -1.0, 1.0},
{ 1.0, 1.0, 1.0},
{ 1.0, 1.0, -1.0},
};
void init_draw_rects(void)
{
if(G.order==B_ENDIAN) {
IMB_convert_rgba_to_abgr(16, rect_desel);
IMB_convert_rgba_to_abgr(16, rect_sel);
IMB_convert_rgba_to_abgr(16, rectu_desel);
IMB_convert_rgba_to_abgr(16, rectu_sel);
IMB_convert_rgba_to_abgr(81, rectl_desel);
IMB_convert_rgba_to_abgr(81, rectl_sel);
IMB_convert_rgba_to_abgr(81, rectlus_desel);
IMB_convert_rgba_to_abgr(81, rectlus_sel);
IMB_convert_rgba_to_abgr(81, rectllib_desel);
IMB_convert_rgba_to_abgr(81, rectllib_sel);
IMB_convert_rgba_to_abgr(81, rectl_set);
}
}
static void draw_icon_centered(float *pos, unsigned int *rect, int rectsize)
{
float hsize= (float) rectsize/2.0;
GLubyte dummy= 0;
glRasterPos3fv(pos);
/* use bitmap to shift rasterpos in pixels */
glBitmap(0, 0, 0.0, 0.0, -hsize, -hsize, &dummy);
#if defined (__sun__) || defined ( __sun ) || defined (__sparc) || defined (__sparc__)
glFlush();
#endif
glDrawPixels(rectsize, rectsize, GL_RGBA, GL_UNSIGNED_BYTE, rect);
}
/* bad frontbuffer call... because it is used in transform after force_draw() */
void helpline(float *vec)
{
float vecrot[3], cent[2];
short mval[2];
VECCOPY(vecrot, vec);
if(G.obedit) Mat4MulVecfl(G.obedit->obmat, vecrot);
else if(G.obpose) Mat4MulVecfl(G.obpose->obmat, vecrot);
getmouseco_areawin(mval);
project_float(vecrot, cent); // no overflow in extreme cases
if(cent[0]!=3200.0f) {
persp(PERSP_WIN);
glDrawBuffer(GL_FRONT);
BIF_ThemeColor(TH_WIRE);
setlinestyle(3);
glBegin(GL_LINE_STRIP);
glVertex2sv(mval);
glVertex2fv(cent);
glEnd();
setlinestyle(0);
persp(PERSP_VIEW);
glFlush(); // flush display for frontbuffer
glDrawBuffer(GL_BACK);
}
}
void drawaxes(float size)
{
int axis;
for (axis=0; axis<3; axis++) {
float v1[3]= {0.0, 0.0, 0.0};
float v2[3]= {0.0, 0.0, 0.0};
int arrow_axis= (axis==0)?1:0;
glBegin(GL_LINES);
v2[axis]= size;
glVertex3fv(v1);
glVertex3fv(v2);
v1[axis]= size*0.8;
v1[arrow_axis]= -size*0.125;
glVertex3fv(v1);
glVertex3fv(v2);
v1[arrow_axis]= size*0.125;
glVertex3fv(v1);
glVertex3fv(v2);
glEnd();
v2[axis]+= size*0.125;
glRasterPos3fv(v2);
// patch for 3d cards crashing on glSelect for text drawing (IBM)
if((G.f & G_PICKSEL) == 0) {
if (axis==0)
BMF_DrawString(G.font, "x");
else if (axis==1)
BMF_DrawString(G.font, "y");
else
BMF_DrawString(G.font, "z");
}
}
}
void drawsolidcube(float size)
{
float n[3];
glPushMatrix();
glScalef(size, size, size);
n[0]=0; n[1]=0; n[2]=0;
glBegin(GL_QUADS);
n[0]= -1.0;
glNormal3fv(n);
glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
n[0]=0;
glEnd();
glBegin(GL_QUADS);
n[1]= -1.0;
glNormal3fv(n);
glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]);
n[1]=0;
glEnd();
glBegin(GL_QUADS);
n[0]= 1.0;
glNormal3fv(n);
glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]);
n[0]=0;
glEnd();
glBegin(GL_QUADS);
n[1]= 1.0;
glNormal3fv(n);
glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]);
n[1]=0;
glEnd();
glBegin(GL_QUADS);
n[2]= 1.0;
glNormal3fv(n);
glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]);
n[2]=0;
glEnd();
glBegin(GL_QUADS);
n[2]= -1.0;
glNormal3fv(n);
glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
glEnd();
glPopMatrix();
}
static void drawcube(void)
{
glBegin(GL_LINE_STRIP);
glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
glVertex3fv(cube[7]); glVertex3fv(cube[4]);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3fv(cube[1]); glVertex3fv(cube[5]);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3fv(cube[2]); glVertex3fv(cube[6]);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3fv(cube[3]); glVertex3fv(cube[7]);
glEnd();
}
#if 0
static void drawcube_size(float *size)
{
glPushMatrix();
glScalef(size[0], size[1], size[2]);
glBegin(GL_LINE_STRIP);
glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
glVertex3fv(cube[7]); glVertex3fv(cube[4]);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3fv(cube[1]); glVertex3fv(cube[5]);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3fv(cube[2]); glVertex3fv(cube[6]);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3fv(cube[3]); glVertex3fv(cube[7]);
glEnd();
glPopMatrix();
}
#endif
static void tekenshadbuflimits(Lamp *la, float mat[][4])
{
float sta[3], end[3], lavec[3];
lavec[0]= -mat[2][0];
lavec[1]= -mat[2][1];
lavec[2]= -mat[2][2];
Normalise(lavec);
sta[0]= mat[3][0]+ la->clipsta*lavec[0];
sta[1]= mat[3][1]+ la->clipsta*lavec[1];
sta[2]= mat[3][2]+ la->clipsta*lavec[2];
end[0]= mat[3][0]+ la->clipend*lavec[0];
end[1]= mat[3][1]+ la->clipend*lavec[1];
end[2]= mat[3][2]+ la->clipend*lavec[2];
glBegin(GL_LINE_STRIP);
glVertex3fv(sta);
glVertex3fv(end);
glEnd();
glPointSize(3.0);
bglBegin(GL_POINTS);
bglVertex3fv(sta);
bglVertex3fv(end);
bglEnd();
glPointSize(1.0);
}
static void spotvolume(float *lvec, float *vvec, float inp)
{
/* camera is at 0,0,0 */
float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,hoek;
Normalise(lvec);
Normalise(vvec); /* is this the correct vector ? */
Crossf(temp,vvec,lvec); /* equation for a plane through vvec en lvec */
Crossf(plane,lvec,temp); /* a plane perpendicular to this, parrallel with lvec */
Normalise(plane);
/* now we've got two equations: one of a cone and one of a plane, but we have
three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
/* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
/* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
/* translating this comment to english didnt really help me understanding the math! :-) (ton) */
q[1] = plane[1] ;
q[2] = -plane[0] ;
q[3] = 0 ;
Normalise(&q[1]);
hoek = saacos(plane[2])/2.0;
co = cos(hoek);
si = sqrt(1-co*co);
q[0] = co;
q[1] *= si;
q[2] *= si;
q[3] = 0;
QuatToMat3(q,mat1);
/* rotate lamp vector now over acos(inp) degrees */
vvec[0] = lvec[0] ;
vvec[1] = lvec[1] ;
vvec[2] = lvec[2] ;
Mat3One(mat2);
co = inp;
si = sqrt(1-inp*inp);
mat2[0][0] = co;
mat2[1][0] = -si;
mat2[0][1] = si;
mat2[1][1] = co;
Mat3MulMat3(mat3,mat2,mat1);
mat2[1][0] = si;
mat2[0][1] = -si;
Mat3MulMat3(mat4,mat2,mat1);
Mat3Transp(mat1);
Mat3MulMat3(mat2,mat1,mat3);
Mat3MulVecfl(mat2,lvec);
Mat3MulMat3(mat2,mat1,mat4);
Mat3MulVecfl(mat2,vvec);
return;
}
static void drawlamp(Object *ob)
{
Lamp *la;
float vec[3], lvec[3], vvec[3],x,y,z;
la= ob->data;
vec[0]=vec[1]=vec[2]= 0.0;
setlinestyle(4);
/* yafray: for photonlight also draw lightcone as for spot */
if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
lvec[0]=lvec[1]= 0.0;
lvec[2] = 1.0;
x = G.vd->persmat[0][2];
y = G.vd->persmat[1][2];
z = G.vd->persmat[2][2];
vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
y = cos( M_PI*la->spotsize/360.0 );
spotvolume(lvec, vvec, y);
x = -la->dist;
lvec[0] *= x ;
lvec[1] *= x ;
lvec[2] *= x;
vvec[0] *= x ;
vvec[1] *= x ;
vvec[2] *= x;
glBegin(GL_LINE_STRIP);
glVertex3fv(vvec);
glVertex3fv(vec);
glVertex3fv(lvec);
glEnd();
z = x*sqrt(1.0 - y*y);
x *= y;
glTranslatef(0.0 , 0.0 , x);
if(la->mode & LA_SQUARE) {
vvec[0]= fabs(z);
vvec[1]= fabs(z);
vvec[2]= 0.0;
glBegin(GL_LINE_LOOP);
glVertex3fv(vvec);
vvec[1]= -fabs(z);
glVertex3fv(vvec);
vvec[0]= -fabs(z);
glVertex3fv(vvec);
vvec[1]= fabs(z);
glVertex3fv(vvec);
glEnd();
}
else circ(0.0, 0.0, fabs(z));
}
else if ELEM(la->type, LA_HEMI, LA_SUN) {
glBegin(GL_LINE_STRIP);
glVertex3fv(vec);
vec[2]= -la->dist;
glVertex3fv(vec);
glEnd();
}
else {
if(la->type==LA_AREA) {
setlinestyle(0);
if(la->area_shape==LA_AREA_SQUARE)
fdrawbox(-la->area_size*0.5, -la->area_size*0.5, la->area_size*0.5, la->area_size*0.5);
else if(la->area_shape==LA_AREA_RECT)
fdrawbox(-la->area_size*0.5, -la->area_sizey*0.5, la->area_size*0.5, la->area_sizey*0.5);
setlinestyle(3);
glBegin(GL_LINE_STRIP);
glVertex3f(0.0,0.0,0.0);
glVertex3f(0.0,0.0,-la->dist);
glEnd();
setlinestyle(0);
}
else if(la->mode & LA_SPHERE) {
float tmat[4][4], imat[4][4];
vec[0]= vec[1]= vec[2]= 0.0;
mygetmatrix(tmat);
Mat4Invert(imat, tmat);
drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
}
}
glPushMatrix();
glLoadMatrixf(G.vd->viewmat);
VECCOPY(vec, ob->obmat[3]);
setlinestyle(3);
glBegin(GL_LINE_STRIP);
glVertex3fv(vec);
vec[2]= 0;
glVertex3fv(vec);
glEnd();
setlinestyle(0);
if(la->type==LA_SPOT && (la->mode & LA_SHAD) ) {
tekenshadbuflimits(la, ob->obmat);
}
glPopMatrix();
}
static void draw_limit_line(float sta, float end, unsigned int col)
{
glBegin(GL_LINES);
glVertex3f(0.0, 0.0, -sta);
glVertex3f(0.0, 0.0, -end);
glEnd();
glPointSize(3.0);
glBegin(GL_POINTS);
cpack(col);
glVertex3f(0.0, 0.0, -sta);
glVertex3f(0.0, 0.0, -end);
glEnd();
glPointSize(1.0);
}
/* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
static void draw_focus_cross(float dist, float size)
{
glBegin(GL_LINES);
glVertex3f(-size, 0.f, -dist);
glVertex3f(size, 0.f, -dist);
glVertex3f(0.f, -size, -dist);
glVertex3f(0.f, size, -dist);
glEnd();
}
void drawcamera(Object *ob)
{
/* a standing up pyramid with (0,0,0) as top */
Camera *cam;
World *wrld;
float vec[8][4], tmat[4][4], fac, facx, facy, depth;
cam= ob->data;
glDisable(GL_LIGHTING);
glDisable(GL_CULL_FACE);
if(G.vd->persp>=2 && cam->type==CAM_ORTHO && ob==G.vd->camera) {
facx= 0.5*cam->ortho_scale*1.28;
facy= 0.5*cam->ortho_scale*1.024;
depth= -cam->clipsta-0.1;
}
else {
fac= cam->drawsize;
if(G.vd->persp>=2 && ob==G.vd->camera) fac= cam->clipsta+0.1; /* that way it's always visible */
depth= - fac*cam->lens/16.0;
facx= fac*1.28;
facy= fac*1.024;
}
vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.001; /* GLBUG: for picking at iris Entry (well thats old!) */
vec[1][0]= facx; vec[1][1]= facy; vec[1][2]= depth;
vec[2][0]= facx; vec[2][1]= -facy; vec[2][2]= depth;
vec[3][0]= -facx; vec[3][1]= -facy; vec[3][2]= depth;
vec[4][0]= -facx; vec[4][1]= facy; vec[4][2]= depth;
glBegin(GL_LINE_LOOP);
glVertex3fv(vec[1]);
glVertex3fv(vec[2]);
glVertex3fv(vec[3]);
glVertex3fv(vec[4]);
glEnd();
if(G.vd->persp>=2 && ob==G.vd->camera) return;
glBegin(GL_LINE_STRIP);
glVertex3fv(vec[2]);
glVertex3fv(vec[0]);
glVertex3fv(vec[1]);
glVertex3fv(vec[4]);
glVertex3fv(vec[0]);
glVertex3fv(vec[3]);
glEnd();
/* arrow on top */
vec[0][2]= depth;
glBegin(GL_QUADS);
vec[0][0]= -0.2*cam->drawsize;
vec[0][1]= cam->drawsize;
glVertex3fv(vec[0]);
vec[0][0]= 0.2*cam->drawsize;
glVertex3fv(vec[0]);
vec[0][1]= 1.6*cam->drawsize;
glVertex3fv(vec[0]);
vec[0][0]= -0.2*cam->drawsize;
glVertex3fv(vec[0]);
glEnd();
glBegin(GL_TRIANGLES);
vec[0][0]= -0.4*cam->drawsize;
vec[0][1]= 1.6*cam->drawsize;
glVertex3fv(vec[0]);
vec[0][0]= 0.0;
vec[0][1]= 2.0*cam->drawsize;
glVertex3fv(vec[0]);
vec[0][0]= 0.4*cam->drawsize;
vec[0][1]= 1.6*cam->drawsize;
glVertex3fv(vec[0]);
glEnd();
if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
myloadmatrix(G.vd->viewmat);
Mat4CpyMat4(vec, ob->obmat);
Mat4Ortho(vec);
mymultmatrix(vec);
MTC_Mat4SwapMat4(G.vd->persmat, tmat);
mygetsingmatrix(G.vd->persmat);
if(cam->flag & CAM_SHOWLIMITS) {
draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
/* yafray: dof focus point */
if (G.scene->r.renderer==R_YAFRAY) draw_focus_cross(cam->YF_dofdist, cam->drawsize);
}
wrld= G.scene->world;
if(cam->flag & CAM_SHOWMIST)
if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
MTC_Mat4SwapMat4(G.vd->persmat, tmat);
}
}
static void tekenvertslatt(short sel)
{
Lattice *lt;
BPoint *bp;
float size;
int a, uxt, u, vxt, v, wxt, w;
size= BIF_GetThemeValuef(TH_VERTEX_SIZE);
glPointSize(size);
if(sel) BIF_ThemeColor(TH_VERTEX_SELECT);
else BIF_ThemeColor(TH_VERTEX);
bglBegin(GL_POINTS);
bp= editLatt->def;
lt= editLatt;
if(lt->flag & LT_OUTSIDE) {
for(w=0; w<lt->pntsw; w++) {
if(w==0 || w==lt->pntsw-1) wxt= 1; else wxt= 0;
for(v=0; v<lt->pntsv; v++) {
if(v==0 || v==lt->pntsv-1) vxt= 1; else vxt= 0;
for(u=0; u<lt->pntsu; u++, bp++) {
if(u==0 || u==lt->pntsu-1) uxt= 1; else uxt= 0;
if(uxt || vxt || wxt) {
if(bp->hide==0) {
if((bp->f1 & 1)==sel) bglVertex3fv(bp->vec);
}
}
}
}
}
}
else {
a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
while(a--) {
if(bp->hide==0) {
if((bp->f1 & 1)==sel) bglVertex3fv(bp->vec);
}
bp++;
}
}
glPointSize(1.0);
bglEnd();
}
static void calc_lattverts(void)
{
BPoint *bp;
float mat[4][4];
int a;
MTC_Mat4SwapMat4(G.vd->persmat, mat);
mygetsingmatrix(G.vd->persmat);
bp= editLatt->def;
a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
while(a--) {
project_short(bp->vec, bp->s);
bp++;
}
MTC_Mat4SwapMat4(G.vd->persmat, mat);
}
void calc_lattverts_ext(void)
{
areawinset(curarea->win);
persp(PERSP_VIEW);
mymultmatrix(G.obedit->obmat);
calc_lattverts();
myloadmatrix(G.vd->viewmat);
}
static void drawlattice(Object *ob)
{
Lattice *lt;
BPoint *bp, *bpu;
int u, v, w, dv, dw, uxt, vxt, wxt;
lt= ob->data;
if(ob==G.obedit) {
bp= editLatt->def;
cpack(0x004000);
}
else {
lattice_modifier(ob, 's');
bp= lt->def;
}
dv= lt->pntsu;
dw= dv*lt->pntsv;
if(lt->flag & LT_OUTSIDE) {
for(w=0; w<lt->pntsw; w++) {
if(w==0 || w==lt->pntsw-1) wxt= 1; else wxt= 0;
for(v=0; v<lt->pntsv; v++) {
if(v==0 || v==lt->pntsv-1) vxt= 1; else vxt= 0;
for(u=0, bpu=0; u<lt->pntsu; u++, bp++) {
if(u==0 || u==lt->pntsu-1) uxt= 1; else uxt= 0;
if(uxt || vxt || wxt) {
if(w && (uxt || vxt)) {
glBegin(GL_LINE_STRIP);
glVertex3fv( (bp-dw)->vec ); glVertex3fv(bp->vec);
glEnd();
}
if(v && (uxt || wxt)) {
glBegin(GL_LINES);
glVertex3fv( (bp-dv)->vec ); glVertex3fv(bp->vec);
glEnd();
}
if(u && (vxt || wxt)) {
glBegin(GL_LINES);
glVertex3fv(bpu->vec); glVertex3fv(bp->vec);
glEnd();
}
}
bpu= bp;
}
}
}
}
else {
for(w=0; w<lt->pntsw; w++) {
for(v=0; v<lt->pntsv; v++) {
for(u=0, bpu=0; u<lt->pntsu; u++, bp++) {
if(w) {
glBegin(GL_LINES);
glVertex3fv( (bp-dw)->vec ); glVertex3fv(bp->vec);
glEnd();
}
if(v) {
glBegin(GL_LINES);
glVertex3fv( (bp-dv)->vec ); glVertex3fv(bp->vec);
glEnd();
}
if(u) {
glBegin(GL_LINES);
glVertex3fv(bpu->vec); glVertex3fv(bp->vec);
glEnd();
}
bpu= bp;
}
}
}
}
if(ob==G.obedit) {
calc_lattverts();
if(G.zbuf) glDisable(GL_DEPTH_TEST);
tekenvertslatt(0);
tekenvertslatt(1);
if(G.zbuf) glEnable(GL_DEPTH_TEST);
}
else lattice_modifier(ob, 'e');
}
/* ***************** ******************** */
void calc_mesh_facedots_ext(void)
{
EditMesh *em = G.editMesh;
EditFace *efa;
float mat[4][4];
if(em->faces.first==NULL) return;
efa= em->faces.first;
areawinset(curarea->win);
persp(PERSP_VIEW);
mymultmatrix(G.obedit->obmat);
MTC_Mat4SwapMat4(G.vd->persmat, mat);
mygetsingmatrix(G.vd->persmat);
efa= em->faces.first;
while(efa) {
if( efa->h==0) {
project_short(efa->cent, &(efa->xs));
}
efa= efa->next;
}
MTC_Mat4SwapMat4(G.vd->persmat, mat);
myloadmatrix(G.vd->viewmat);
}
/* window coord, assuming all matrices are set OK */
static void calc_meshverts(DerivedMesh *dm)
{
float co[3], mat[4][4];
EditVert *eve;
MTC_Mat4SwapMat4(G.vd->persmat, mat);
mygetsingmatrix(G.vd->persmat);
for(eve= G.editMesh->verts.first; eve; eve= eve->next) {
if(eve->h==0) {
dm->getMappedVertCoEM(dm, eve, co);
project_short(co, &(eve->xs));
}
}
MTC_Mat4SwapMat4(G.vd->persmat, mat);
}
/* window coord for current window, sets matrices temporal */
void calc_meshverts_ext(void)
{
int dmNeedsFree;
DerivedMesh *dm = mesh_get_cage_derived(G.obedit, &dmNeedsFree);
areawinset(curarea->win);
persp(PERSP_VIEW);
mymultmatrix(G.obedit->obmat);
calc_meshverts(dm);
myloadmatrix(G.vd->viewmat);
if (dmNeedsFree) {
dm->release(dm);
}
}
/* window coord for current window, sets matrices temporal, sets (eve->f & 2) when not visible */
void calc_meshverts_ext_f2(void)
{
int dmNeedsFree;
DerivedMesh *dm = mesh_get_cage_derived(G.obedit, &dmNeedsFree);
float co[3], mat[4][4];
EditVert *eve;
/* matrices */
areawinset(curarea->win);
persp(PERSP_VIEW);
mymultmatrix(G.obedit->obmat);
MTC_Mat4SwapMat4(G.vd->persmat, mat);
mygetsingmatrix(G.vd->persmat);
for(eve= G.editMesh->verts.first; eve; eve= eve->next) {
eve->f &= ~2;
if(eve->h==0) {
dm->getMappedVertCoEM(dm, eve, co);
project_short_noclip(co, &(eve->xs));
if( eve->xs >= 0 && eve->ys >= 0 && eve->xs<curarea->winx && eve->ys<curarea->winy);
else eve->f |= 2;
}
}
/* restore */
MTC_Mat4SwapMat4(G.vd->persmat, mat);
myloadmatrix(G.vd->viewmat);
if (dmNeedsFree) {
dm->release(dm);
}
}
static void calc_Nurbverts(Nurb *nurb)
{
Nurb *nu;
BezTriple *bezt;
BPoint *bp;
float mat[4][4];
int a;
MTC_Mat4SwapMat4(G.vd->persmat, mat);
mygetsingmatrix(G.vd->persmat);
nu= nurb;
while(nu) {
if((nu->type & 7)==1) {
bezt= nu->bezt;
a= nu->pntsu;
while(a--) {
project_short(bezt->vec[0], bezt->s[0]);
project_short(bezt->vec[1], bezt->s[1]);
project_short(bezt->vec[2], bezt->s[2]);
bezt++;
}
}
else {
bp= nu->bp;
a= nu->pntsu*nu->pntsv;
while(a--) {
project_short(bp->vec, bp->s);
bp++;
}
}
nu= nu->next;
}
MTC_Mat4SwapMat4(G.vd->persmat, mat);
}
void calc_nurbverts_ext(void)
{
areawinset(curarea->win);
persp(PERSP_VIEW);
mymultmatrix(G.obedit->obmat);
calc_Nurbverts(editNurb.first);
myloadmatrix(G.vd->viewmat);
}
////
static void calc_weightpaint_vert_color(Object *ob, int vert, unsigned char *col)
{
Mesh *me = ob->data;
float fr, fg, fb, input = 0.0;
int i;
if (me->dvert) {
for (i=0; i<me->dvert[vert].totweight; i++)
if (me->dvert[vert].dw[i].def_nr==ob->actdef-1)
input+=me->dvert[vert].dw[i].weight;
}
CLAMP(input, 0.0, 1.0);
fr = fg = fb = 85;
if (input<=0.25f){
fr=0.0f;
fg=255.0f * (input*4.0f);
fb=255.0f;
}
else if (input<=0.50f){
fr=0.0f;
fg=255.0f;
fb=255.0f * (1.0f-((input-0.25f)*4.0f));
}
else if (input<=0.75){
fr=255.0f * ((input-0.50f)*4.0f);
fg=255.0f;
fb=0.0f;
}
else if (input<=1.0){
fr=255.0f;
fg=255.0f * (1.0f-((input-0.75f)*4.0f));
fb=0.0f;
}
col[3] = (unsigned char)(fr * ((input/2.0f)+0.5f));
col[2] = (unsigned char)(fg * ((input/2.0f)+0.5f));
col[1] = (unsigned char)(fb * ((input/2.0f)+0.5f));
col[0] = 255;
}
static unsigned char *calc_weightpaint_colors(Object *ob)
{
Mesh *me = ob->data;
MFace *mf = me->mface;
unsigned char *wtcol;
int i;
wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap");
memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4);
for (i=0; i<me->totface; i++, mf++){
calc_weightpaint_vert_color(ob, mf->v1, &wtcol[(i*4 + 0)*4]);
calc_weightpaint_vert_color(ob, mf->v2, &wtcol[(i*4 + 1)*4]);
if (mf->v3)
calc_weightpaint_vert_color(ob, mf->v3, &wtcol[(i*4 + 2)*4]);
if (mf->v4)
calc_weightpaint_vert_color(ob, mf->v4, &wtcol[(i*4 + 3)*4]);
}
return wtcol;
}
/* ************** DRAW MESH ****************** */
/* First section is all the "simple" draw routines,
* ones that just pass some sort of primitive to GL,
* with perhaps various options to control lighting,
* color, etc.
*
* These routines should not have user interface related
* logic!!!
*/
static void draw_em_face_normals(EditMesh *em, float normalLength)
{
EditFace *efa;
glBegin(GL_LINES);
for(efa= em->faces.first; efa; efa= efa->next) {
if(efa->h==0 && efa->fgonf!=EM_FGON) {
glVertex3fv(efa->cent);
glVertex3f( efa->cent[0] + normalLength*efa->n[0],
efa->cent[1] + normalLength*efa->n[1],
efa->cent[2] + normalLength*efa->n[2]);
}
}
glEnd();
}
static void draw_em_face_centers(EditMesh *em, int sel) {
EditFace *efa;
bglBegin(GL_POINTS);
for(efa= em->faces.first; efa; efa= efa->next) {
if(efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
bglVertex3fv(efa->cent);
}
}
bglEnd();
}
/* Draw verts with color set based on selection */
static int draw_dm_verts__setDrawOptions(void *userData, EditVert *eve)
{
int sel = *((int*) userData);
return (eve->h==0 && (eve->f&SELECT)==sel);
}
static void draw_dm_verts(DerivedMesh *dm, int sel)
{
dm->drawMappedVertsEM(dm, draw_dm_verts__setDrawOptions, &sel);
}
/* Draw edges with color set based on selection */
static int draw_dm_edges_sel__setDrawOptions(void *userData, EditEdge *eed)
{
unsigned char **cols = userData;
if (eed->h==0) {
glColor4ubv(cols[(eed->f&SELECT)?1:0]);
return 1;
} else {
return 0;
}
}
static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
{
unsigned char *cols[2];
cols[0] = baseCol;
cols[1] = selCol;
dm->drawMappedEdgesEM(dm, draw_dm_edges_sel__setDrawOptions, cols);
}
/* Draw edges */
static int draw_dm_edges__setDrawOptions(void *userData, EditEdge *eed)
{
return eed->h==0;
}
static void draw_dm_edges(DerivedMesh *dm)
{
dm->drawMappedEdgesEM(dm, draw_dm_edges__setDrawOptions, NULL);
}
/* Draw edges with color interpolated based on selection */
static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, EditEdge *eed)
{
return (eed->h==0);
}
static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, EditEdge *eed, float t)
{
unsigned char **cols = userData;
unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
glColor4ub( col0[0] + (col1[0]-col0[0])*t,
col0[1] + (col1[1]-col0[1])*t,
col0[2] + (col1[2]-col0[2])*t,
col0[3] + (col1[3]-col0[3])*t);
}
static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
{
unsigned char *cols[2];
cols[0] = baseCol;
cols[1] = selCol;
dm->drawMappedEdgesInterpEM(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
}
/* Draw only seam edges */
static int draw_dm_edges_seams__setDrawOptions(void *userData, EditEdge *eed)
{
return (eed->h==0 && eed->seam);
}
static void draw_dm_edges_seams(DerivedMesh *dm)
{
dm->drawMappedEdgesEM(dm, draw_dm_edges_seams__setDrawOptions, NULL);
}
/* Draw faces with color set based on selection */
static int draw_dm_faces_sel__setDrawOptions(void *userData, EditFace *efa)
{
unsigned char **cols = userData;
if (efa->h==0) {
glColor4ubv(cols[(efa->f&SELECT)?1:0]);
return 1;
} else {
return 0;
}
}
static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
{
unsigned char *cols[2];
cols[0] = baseCol;
cols[1] = selCol;
dm->drawMappedFacesEM(dm, draw_dm_faces_sel__setDrawOptions, cols);
}
/* Second section of routines: Combine first sets to form fancy
* drawing routines (for example rendering twice to get overlays).
*
* Also includes routines that are basic drawing but are too
* specialized to be split out (like drawing creases or measurements).
*/
/* EditMesh drawing routines*/
static void draw_em_fancy_verts(EditMesh *em, DerivedMesh *cageDM)
{
int sel;
if(G.zbuf) glDepthMask(0); // disable write in zbuffer, zbuf select
for (sel=0; sel<2; sel++) {
char col[4], fcol[4];
int pass;
BIF_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
BIF_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
for (pass=0; pass<2; pass++) {
float size = BIF_GetThemeValuef(TH_VERTEX_SIZE);
float fsize = BIF_GetThemeValuef(TH_FACEDOT_SIZE);
if (pass==0) {
if(G.zbuf && !(G.vd->flag&V3D_ZBUF_SELECT)) {
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
} else {
continue;
}
size = (size>2.1?size/2.0:size);
fsize = (fsize>2.1?fsize/2.0:fsize);
col[3] = fcol[3] = 100;
} else {
col[3] = fcol[3] = 255;
}
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
glPointSize(size);
glColor4ubv(col);
draw_dm_verts(cageDM, sel);
}
if(G.scene->selectmode & SCE_SELECT_FACE) {
glPointSize(fsize);
glColor4ubv(fcol);
draw_em_face_centers(em, sel);
}
if (pass==0) {
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
}
}
}
if(G.zbuf) glDepthMask(1);
glPointSize(1.0);
}
static void draw_em_fancy_edges(DerivedMesh *cageDM)
{
int pass;
char wire[4], sel[4];
/* since this function does transparant... */
BIF_GetThemeColor3ubv(TH_EDGE_SELECT, sel);
BIF_GetThemeColor3ubv(TH_WIRE, wire);
for (pass=0; pass<2; pass++) {
/* show wires in transparant when no zbuf clipping for select */
if (pass==0) {
if (G.zbuf && (G.vd->flag & V3D_ZBUF_SELECT)==0) {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
wire[3] = sel[3] = 85;
} else {
continue;
}
} else {
wire[3] = sel[3] = 255;
}
if(G.scene->selectmode == SCE_SELECT_FACE) {
draw_dm_edges_sel(cageDM, wire, sel);
}
else if( (G.f & G_DRAWEDGES) || (G.scene->selectmode & SCE_SELECT_EDGE) ) {
if(cageDM->drawMappedEdgesInterpEM && (G.scene->selectmode & SCE_SELECT_VERTEX)) {
glShadeModel(GL_SMOOTH);
draw_dm_edges_sel_interp(cageDM, wire, sel);
glShadeModel(GL_FLAT);
} else {
draw_dm_edges_sel(cageDM, wire, sel);
}
}
else {
glColor4ubv(wire);
draw_dm_edges(cageDM);
}
if (pass==0) {
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
}
}
}
static void draw_em_creases(EditMesh *em)
{
EditEdge *eed;
float fac, *v1, *v2, vec[3];
glLineWidth(3.0);
glBegin(GL_LINES);
for(eed= em->edges.first; eed; eed= eed->next) {
if(eed->h==0 && eed->crease!=0.0) {
BIF_ThemeColor((eed->f&SELECT)?TH_EDGE_SELECT:TH_WIRE);
v1= eed->v1->co; v2= eed->v2->co;
VECSUB(vec, v2, v1);
fac= 0.5 + eed->crease/2.0;
glVertex3f(v1[0] + fac*vec[0], v1[1] + fac*vec[1], v1[2] + fac*vec[2] );
glVertex3f(v2[0] - fac*vec[0], v2[1] - fac*vec[1], v2[2] - fac*vec[2] );
}
}
glEnd();
glLineWidth(1.0);
}
static void draw_em_measure_stats(Object *ob, EditMesh *em)
{
EditEdge *eed;
EditFace *efa;
float v1[3], v2[3], v3[3], v4[3];
float fvec[3];
char val[32]; /* Stores the measurement display text here */
float area, col[3]; /* area of the face, colour of the text to draw */
if(G.zbuf && (G.vd->flag & V3D_ZBUF_SELECT)==0)
glDisable(GL_DEPTH_TEST);
if(G.zbuf) bglPolygonOffset(5.0);
if(G.f & G_DRAW_EDGELEN) {
BIF_GetThemeColor3fv(TH_TEXT, col);
/* make color a bit more red */
if(col[0]> 0.5) {col[1]*=0.7; col[2]*= 0.7;}
else col[0]= col[0]*0.7 + 0.3;
glColor3fv(col);
for(eed= em->edges.first; eed; eed= eed->next) {
if((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) )) {
VECCOPY(v1, eed->v1->co);
VECCOPY(v2, eed->v2->co);
glRasterPos3f( 0.5*(v1[0]+v2[0]), 0.5*(v1[1]+v2[1]), 0.5*(v1[2]+v2[2]));
if(G.vd->flag & V3D_GLOBAL_STATS) {
Mat4MulVecfl(ob->obmat, v1);
Mat4MulVecfl(ob->obmat, v2);
}
sprintf(val,"%.3f", VecLenf(v1, v2));
BMF_DrawString( G.fonts, val);
}
}
}
if(G.f & G_DRAW_FACEAREA) {
extern int faceselectedOR(EditFace *efa, int flag); // editmesh.h shouldn't be in this file... ok for now?
BIF_GetThemeColor3fv(TH_TEXT, col);
/* make color a bit more green */
if(col[1]> 0.5) {col[0]*=0.7; col[2]*= 0.7;}
else col[1]= col[1]*0.7 + 0.3;
glColor3fv(col);
for(efa= em->faces.first; efa; efa= efa->next) {
if((efa->f & SELECT) || (G.moving && faceselectedOR(efa, SELECT)) ) {
VECCOPY(v1, efa->v1->co);
VECCOPY(v2, efa->v2->co);
VECCOPY(v3, efa->v2->co);
if (efa->v4) {
VECCOPY(v4, efa->v4->co);
}
if(G.vd->flag & V3D_GLOBAL_STATS) {
Mat4MulVecfl(ob->obmat, v1);
Mat4MulVecfl(ob->obmat, v2);
Mat4MulVecfl(ob->obmat, v3);
if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
}
if (efa->v4)
area= AreaQ3Dfl(v1, v2, v3, v4);
else
area = AreaT3Dfl(v1, v2, v3);
sprintf(val,"%.3f", area);
glRasterPos3fv(efa->cent);
BMF_DrawString( G.fonts, val);
}
}
}
if(G.f & G_DRAW_EDGEANG) {
EditEdge *e1, *e2, *e3, *e4;
BIF_GetThemeColor3fv(TH_TEXT, col);
/* make color a bit more blue */
if(col[2]> 0.5) {col[0]*=0.7; col[1]*= 0.7;}
else col[2]= col[2]*0.7 + 0.3;
glColor3fv(col);
for(efa= em->faces.first; efa; efa= efa->next) {
VECCOPY(v1, efa->v1->co);
VECCOPY(v2, efa->v2->co);
VECCOPY(v3, efa->v3->co);
if(efa->v4) {
VECCOPY(v4, efa->v4->co);
}
else {
VECCOPY(v4, v3);
}
if(G.vd->flag & V3D_GLOBAL_STATS) {
Mat4MulVecfl(ob->obmat, v1);
Mat4MulVecfl(ob->obmat, v2);
Mat4MulVecfl(ob->obmat, v3);
if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
}
e1= efa->e1;
e2= efa->e2;
e3= efa->e3;
if(efa->e4) e4= efa->e4; else e4= e3;
/* Calculate the angles */
if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
/* Vec 1 */
sprintf(val,"%.3f", VecAngle3(v4, v1, v2));
fvec[0]= 0.2*efa->cent[0] + 0.8*efa->v1->co[0];
fvec[1]= 0.2*efa->cent[1] + 0.8*efa->v1->co[1];
fvec[2]= 0.2*efa->cent[2] + 0.8*efa->v1->co[2];
glRasterPos3fv(fvec);
BMF_DrawString( G.fonts, val);
}
if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
/* Vec 2 */
sprintf(val,"%.3f", VecAngle3(v1, v2, v3));
fvec[0]= 0.2*efa->cent[0] + 0.8*efa->v2->co[0];
fvec[1]= 0.2*efa->cent[1] + 0.8*efa->v2->co[1];
fvec[2]= 0.2*efa->cent[2] + 0.8*efa->v3->co[2];
glRasterPos3fv(fvec);
BMF_DrawString( G.fonts, val);
}
if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
/* Vec 3 */
if(efa->v4)
sprintf(val,"%.3f", VecAngle3(v2, v3, v4));
else
sprintf(val,"%.3f", VecAngle3(v2, v3, v1));
fvec[0]= 0.2*efa->cent[0] + 0.8*efa->v3->co[0];
fvec[1]= 0.2*efa->cent[1] + 0.8*efa->v3->co[1];
fvec[2]= 0.2*efa->cent[2] + 0.8*efa->v3->co[2];
glRasterPos3fv(fvec);
BMF_DrawString( G.fonts, val);
}
/* Vec 4 */
if(efa->v4) {
if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
sprintf(val,"%.3f", VecAngle3(v3, v4, v1));
fvec[0]= 0.2*efa->cent[0] + 0.8*efa->v4->co[0];
fvec[1]= 0.2*efa->cent[1] + 0.8*efa->v4->co[1];
fvec[2]= 0.2*efa->cent[2] + 0.8*efa->v4->co[2];
glRasterPos3fv(fvec);
BMF_DrawString( G.fonts, val);
}
}
}
}
if(G.zbuf) {
glEnable(GL_DEPTH_TEST);
bglPolygonOffset(0.0);
}
}
static void draw_em_fancy(Object *ob, EditMesh *em, DerivedMesh *baseDM, DerivedMesh *realDM, int dt)
{
Mesh *me = ob->data;
DerivedMesh *cageDM;
if(realDM && (me->flag&ME_OPT_EDGES)) {
cageDM = realDM;
} else {
cageDM = baseDM;
}
if(dt>OB_WIRE) {
init_gl_materials(ob);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
glEnable(GL_LIGHTING);
glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
if (realDM) {
realDM->drawFacesSolid(realDM, set_gl_material);
} else {
baseDM->drawFacesSolid(baseDM, set_gl_material);
}
glFrontFace(GL_CCW);
glDisable(GL_LIGHTING);
// Setup for drawing wire over, disable zbuffer
// write to show selected edge wires better
BIF_ThemeColor(TH_WIRE);
bglPolygonOffset(1.0);
glDepthMask(0);
} else {
if (realDM && !(me->flag&ME_OPT_EDGES)) {
BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
realDM->drawEdges(realDM);
}
}
if( (G.f & (G_FACESELECT+G_DRAWFACES))) { /* transp faces */
char col1[4], col2[4];
BIF_GetThemeColor4ubv(TH_FACE, col1);
BIF_GetThemeColor4ubv(TH_FACE_SELECT, col2);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glDepthMask(0); // disable write in zbuffer, needed for nice transp
draw_dm_faces_sel(cageDM, col1, col2);
glDisable(GL_BLEND);
glDepthMask(1); // restore write in zbuffer
}
/* here starts all fancy draw-extra over */
if(G.f & G_DRAWSEAMS) {
BIF_ThemeColor(TH_EDGE_SEAM);
glLineWidth(2);
draw_dm_edges_seams(cageDM);
glColor3ub(0,0,0);
glLineWidth(1);
}
draw_em_fancy_edges(cageDM);
if(G.f & G_DRAWCREASES) {
draw_em_creases(em);
}
if(ob==G.obedit) {
calc_meshverts(cageDM);
draw_em_fancy_verts(em, cageDM);
if(G.f & G_DRAWNORMALS) {
BIF_ThemeColor(TH_NORMAL);
draw_em_face_normals(em, G.scene->editbutsize);
}
if(G.f & (G_DRAW_EDGELEN|G_DRAW_FACEAREA|G_DRAW_EDGEANG))
draw_em_measure_stats(ob, em);
}
if(dt>OB_WIRE) {
glDepthMask(1);
bglPolygonOffset(0.0);
}
}
/* Mesh drawing routines */
static void draw_mesh_object_outline(DerivedMesh *dm)
{
glLineWidth(2.0);
glDepthMask(0);
dm->drawEdges(dm);
glLineWidth(1.0);
glDepthMask(1);
}
static void draw_mesh_fancy(Object *ob, DerivedMesh *baseDM, DerivedMesh *realDM, int dt)
{
Mesh *me = ob->data;
Material *ma= give_current_material(ob, 1);
int hasHaloMat = (ma && (ma->mode&MA_HALO));
int draw_wire = ob->dtx&OB_DRAWWIRE;
DispList *dl;
float *obExtVerts;
DerivedMesh *dm = realDM?realDM:baseDM;
dl = find_displist(&ob->disp, DL_VERTS);
obExtVerts = dl?dl->verts:NULL;
// Unwanted combination.
if (G.f&G_FACESELECT) draw_wire = 0;
// This is only for objects from the decimator and
// is a temporal solution, a reconstruction of the
// displist system should take care of it (zr/ton)
if(me->decimated) {
DispListMesh *dlm = me->decimated;
MVert *mvert= dlm->mvert;
MFace *mface= dlm->mface;
int i;
for (i=0; i<dlm->totface; i++, mface++) {
glBegin(GL_LINE_LOOP);
glVertex3fv(mvert[mface->v1].co);
glVertex3fv(mvert[mface->v2].co);
if (mface->v3) {
glVertex3fv(mvert[mface->v3].co);
if (mface->v4)
glVertex3fv(mvert[mface->v4].co);
}
glEnd();
}
}
else if(dt==OB_BOUNDBOX) {
draw_bounding_volume(ob);
}
else if(hasHaloMat || (me->totface==0 && (!me->medge || me->totedge==0))) {
glPointSize(1.5);
dm->drawVerts(dm);
glPointSize(1.0);
}
else if(dt==OB_WIRE || me->totface==0) {
draw_wire = 1;
}
else if( (ob==OBACT && (G.f & G_FACESELECT)) || (G.vd->drawtype==OB_TEXTURE && dt>OB_SOLID)) {
if ((G.vd->flag&V3D_SELECT_OUTLINE) && (ob->flag&SELECT) && !(G.f&G_FACESELECT) && !draw_wire) {
draw_mesh_object_outline(dm);
}
draw_tface_mesh(ob, ob->data, dt);
}
else if(dt==OB_SOLID ) {
if ((G.vd->flag&V3D_SELECT_OUTLINE) && (ob->flag&SELECT) && !draw_wire) {
draw_mesh_object_outline(dm);
}
init_gl_materials(ob);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
glEnable(GL_LIGHTING);
glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
dm->drawFacesSolid(dm, set_gl_material);
glFrontFace(GL_CCW);
glDisable(GL_LIGHTING);
BIF_ThemeColor(TH_WIRE);
dm->drawLooseEdges(dm);
}
else if(dt==OB_SHADED) {
if( (G.f & G_WEIGHTPAINT)) {
unsigned char *wtcol = calc_weightpaint_colors(ob);
baseDM->drawFacesColored(baseDM, me->flag&ME_TWOSIDED, wtcol, 0);
MEM_freeN (wtcol);
}
else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->mcol) {
baseDM->drawFacesColored(baseDM, me->flag&ME_TWOSIDED, (unsigned char*) me->mcol, 0);
}
else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->tface) {
tface_to_mcol(me);
baseDM->drawFacesColored(baseDM, me->flag&ME_TWOSIDED, (unsigned char*) me->mcol, 0);
MEM_freeN(me->mcol);
me->mcol= 0;
}
else {
unsigned int *obCol1, *obCol2;
dl = ob->disp.first;
if (!dl || !dl->col1) {
shadeDispList(ob);
dl = find_displist(&ob->disp, DL_VERTCOL);
}
obCol1 = dl->col1;
obCol2 = dl->col2;
if ((G.vd->flag&V3D_SELECT_OUTLINE) && (ob->flag&SELECT) && !draw_wire) {
draw_mesh_object_outline(dm);
}
dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
}
}
if (draw_wire) {
/* If drawing wire and drawtype is not OB_WIRE then we are
* overlaying the wires.
*/
if (dt!=OB_WIRE) {
if(ob->flag & SELECT) {
BIF_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
} else {
BIF_ThemeColor(TH_WIRE);
}
bglPolygonOffset(1.0);
glDepthMask(0); // disable write in zbuffer, selected edge wires show better
}
if (me->flag&ME_OPT_EDGES) {
dm->drawMappedEdges(dm);
}
else {
dm->drawEdges(dm);
}
if (dt!=OB_WIRE) {
glDepthMask(1);
bglPolygonOffset(0.0);
}
}
}
static void draw_mesh_object(Object *ob, int dt)
{
Mesh *me= ob->data;
DerivedMesh *baseDM = mesh_get_base_derived(ob);
DerivedMesh *realDM = mesh_get_derived(ob);
if(G.obedit && ob->data==G.obedit->data) {
draw_em_fancy(ob, G.editMesh, baseDM, realDM, dt);
}
else {
if(me->bb==NULL) tex_space_mesh(me);
if(me->totface<=4 || boundbox_clip(ob->obmat, me->bb)) {
draw_mesh_fancy(ob, baseDM, realDM, dt);
}
}
baseDM->release(baseDM);
}
/* ************** DRAW DISPLIST ****************** */
static int draw_index_wire= 1;
static int index3_nors_incr= 1;
static void drawDispListwire(ListBase *dlbase)
{
DispList *dl;
int parts, nr, ofs, *index;
float *data;
if(dlbase==0) return;
dl= dlbase->first;
while(dl) {
data= dl->verts;
switch(dl->type) {
case DL_SEGM:
parts= dl->parts;
while(parts--) {
nr= dl->nr;
glBegin(GL_LINE_STRIP);
while(nr--) {
glVertex3fv(data);
data+=3;
}
glEnd();
}
break;
case DL_POLY:
parts= dl->parts;
while(parts--) {
nr= dl->nr;
glBegin(GL_LINE_LOOP);
while(nr--) {
glVertex3fv(data);
data+=3;
}
glEnd();
}
break;
case DL_SURF:
parts= dl->parts;
while(parts--) {
nr= dl->nr;
if(dl->flag & DL_CYCL_U) glBegin(GL_LINE_LOOP);
else glBegin(GL_LINE_STRIP);
while(nr--) {
glVertex3fv(data);
data+=3;
}
glEnd();
}
ofs= 3*dl->nr;
nr= dl->nr;
while(nr--) {
data= ( dl->verts )+3*nr;
parts= dl->parts;
if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
else glBegin(GL_LINE_STRIP);
while(parts--) {
glVertex3fv(data);
data+=ofs;
}
glEnd();
}
break;
case DL_INDEX3:
if(draw_index_wire) {
parts= dl->parts;
data= dl->verts;
index= dl->index;
while(parts--) {
glBegin(GL_LINE_LOOP);
glVertex3fv(data+3*index[0]);
glVertex3fv(data+3*index[1]);
glVertex3fv(data+3*index[2]);
glEnd();
index+= 3;
}
}
break;
case DL_INDEX4:
if(draw_index_wire) {
parts= dl->parts;
data= dl->verts;
index= dl->index;
while(parts--) {
glBegin(GL_LINE_LOOP);
glVertex3fv(data+3*index[0]);
glVertex3fv(data+3*index[1]);
glVertex3fv(data+3*index[2]);
if(index[3]) glVertex3fv(data+3*index[3]);
glEnd();
index+= 4;
}
}
break;
}
dl= dl->next;
}
}
static void drawDispListsolid(ListBase *lb, Object *ob)
{
DispList *dl;
int parts, ofs, p1, p2, p3, p4, a, b, *index;
float *data, *v1, *v2, *v3, *v4;
float *ndata, *n1, *n2, *n3, *n4;
if(lb==0) return;
glEnable(GL_LIGHTING);
if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
else glFrontFace(GL_CCW);
if(ob->type==OB_MBALL) { // mball always smooth shaded
glShadeModel(GL_SMOOTH);
}
dl= lb->first;
while(dl) {
data= dl->verts;
ndata= dl->nors;
switch(dl->type) {
case DL_SURF:
set_gl_material(dl->col+1);
if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
else glShadeModel(GL_FLAT);
for(a=0; a<dl->parts; a++) {
DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts);
v1= data+ 3*p1;
v2= data+ 3*p2;
v3= data+ 3*p3;
v4= data+ 3*p4;
n1= ndata+ 3*p1;
n2= ndata+ 3*p2;
n3= ndata+ 3*p3;
n4= ndata+ 3*p4;
glBegin(GL_QUAD_STRIP);
glNormal3fv(n2); glVertex3fv(v2);
glNormal3fv(n4); glVertex3fv(v4);
for(; b<dl->nr; b++) {
glNormal3fv(n1); glVertex3fv(v1);
glNormal3fv(n3); glVertex3fv(v3);
v2= v1; v1+= 3;
v4= v3; v3+= 3;
n2= n1; n1+= 3;
n4= n3; n3+= 3;
}
glEnd();
}
break;
case DL_INDEX3:
parts= dl->parts;
data= dl->verts;
ndata= dl->nors;
index= dl->index;
set_gl_material(dl->col+1);
/* voor polys only one normal needed */
if(index3_nors_incr==0) {
while(parts--) {
glBegin(GL_TRIANGLES);
glNormal3fv(ndata);
glVertex3fv(data+3*index[0]);
glVertex3fv(data+3*index[1]);
glVertex3fv(data+3*index[2]);
glEnd();
index+= 3;
}
}
else {
while(parts--) {
glBegin(GL_TRIANGLES);
ofs= 3*index[0];
glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
ofs= 3*index[1];
glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
ofs= 3*index[2];
glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
glEnd();
index+= 3;
}
}
break;
case DL_INDEX4:
parts= dl->parts;
data= dl->verts;
ndata= dl->nors;
index= dl->index;
set_gl_material(dl->col+1);
while(parts--) {
glBegin(index[3]?GL_QUADS:GL_TRIANGLES);
ofs= 3*index[0];
glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
ofs= 3*index[1];
glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
ofs= 3*index[2];
glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
if(index[3]) {
ofs= 3*index[3];
glNormal3fv(ndata+ofs); glVertex3fv(data+ofs);
}
glEnd();
index+= 4;
}
break;
}
dl= dl->next;
}
glShadeModel(GL_FLAT);
glDisable(GL_LIGHTING);
glFrontFace(GL_CCW);
}
static void drawDispListshaded(ListBase *lb, Object *ob)
{
DispList *dl, *dlob;
int parts, p1, p2, p3, p4, a, b, *index;
float *data, *v1, *v2, *v3, *v4;/* , *extverts=0 */
unsigned int *cdata, *c1, *c2, *c3, *c4;
char *cp;
if(lb==0) return;
glShadeModel(GL_SMOOTH);
dl= lb->first;
dlob= ob->disp.first;
while(dl && dlob) {
cdata= dlob->col1;
data= dl->verts;
if(cdata==0) break;
switch(dl->type) {
case DL_SURF:
for(a=0; a<dl->parts; a++) {
DL_SURFINDEX(dl->flag & DL_CYCL_U, dl->flag & DL_CYCL_V, dl->nr, dl->parts);
v1= data+ 3*p1;
v2= data+ 3*p2;
v3= data+ 3*p3;
v4= data+ 3*p4;
c1= cdata+ p1;
c2= cdata+ p2;
c3= cdata+ p3;
c4= cdata+ p4;
for(; b<dl->nr; b++) {
glBegin(GL_QUADS);
cp= (char *)c1;
glColor3ub(cp[3], cp[2], cp[1]);
glVertex3fv(v1);
cp= (char *)c2;
glColor3ub(cp[3], cp[2], cp[1]);
glVertex3fv(v2);
cp= (char *)c4;
glColor3ub(cp[3], cp[2], cp[1]);
glVertex3fv(v4);
cp= (char *)c3;
glColor3ub(cp[3], cp[2], cp[1]);
glVertex3fv(v3);
glEnd();
v2= v1; v1+= 3;
v4= v3; v3+= 3;
c2= c1; c1++;
c4= c3; c3++;
}
}
break;
case DL_INDEX3:
parts= dl->parts;
index= dl->index;
while(parts--) {
glBegin(GL_TRIANGLES);
cp= (char *)(cdata+index[0]);
glColor3ub(cp[3], cp[2], cp[1]);
glVertex3fv(data+3*index[0]);
cp= (char *)(cdata+index[1]);
glColor3ub(cp[3], cp[2], cp[1]);
glVertex3fv(data+3*index[1]);
cp= (char *)(cdata+index[2]);
glColor3ub(cp[3], cp[2], cp[1]);
glVertex3fv(data+3*index[2]);
glEnd();
index+= 3;
}
break;
case DL_INDEX4:
parts= dl->parts;
index= dl->index;
while(parts--) {
glBegin(index[3]?GL_QUADS:GL_TRIANGLES);
cp= (char *)(cdata+index[0]);
glColor3ub(cp[3], cp[2], cp[1]);
glVertex3fv(data+3*index[0]);
cp= (char *)(cdata+index[1]);
glColor3ub(cp[3], cp[2], cp[1]);
glVertex3fv(data+3*index[1]);
cp= (char *)(cdata+index[2]);
glColor3ub(cp[3], cp[2], cp[1]);
glVertex3fv(data+3*index[2]);
if(index[3]) {
cp= (char *)(cdata+index[3]);
glColor3ub(cp[3], cp[2], cp[1]);
glVertex3fv(data+3*index[3]);
}
glEnd();
index+= 4;
}
break;
}
dl= dl->next;
dlob= dlob->next;
}
glShadeModel(GL_FLAT);
}
static void drawDispList(Object *ob, int dt)
{
ListBase *lb=0;
DispList *dl;
Curve *cu;
int solid;
solid= (dt > OB_WIRE);
switch(ob->type) {
case OB_FONT:
case OB_CURVE:
cu= ob->data;
lb= &cu->disp;
if(lb->first==0) makeDispList(ob);
if(solid) {
dl= lb->first;
if(dl==0) return;
/* rule: dl->type INDEX3 is always first in list */
if(dl->type!=DL_INDEX3) {
if(ob==G.obedit) curve_to_filledpoly(ob->data, &editNurb, lb);
else curve_to_filledpoly(ob->data, &cu->nurb, lb);
dl= lb->first;
}
if(dl->nors==0) addnormalsDispList(ob, lb);
index3_nors_incr= 0;
if( displist_has_faces(lb)==0) {
draw_index_wire= 0;
drawDispListwire(lb);
draw_index_wire= 1;
}
else {
if(dt==OB_SHADED) {
if(ob->disp.first==0) shadeDispList(ob);
drawDispListshaded(lb, ob);
}
else {
init_gl_materials(ob);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
drawDispListsolid(lb, ob);
}
if(ob==G.obedit) {
cpack(0);
draw_index_wire= 0;
drawDispListwire(lb);
draw_index_wire= 1;
}
}
index3_nors_incr= 1;
}
else {
draw_index_wire= 0;
drawDispListwire(lb);
draw_index_wire= 1;
}
break;
case OB_SURF:
lb= &((Curve *)ob->data)->disp;
if(lb->first==0) makeDispList(ob);
if(solid) {
dl= lb->first;
if(dl==0) return;
if(dl->nors==0) addnormalsDispList(ob, lb);
if(dt==OB_SHADED) {
if(ob->disp.first==0) shadeDispList(ob);
drawDispListshaded(lb, ob);
}
else {
init_gl_materials(ob);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
drawDispListsolid(lb, ob);
}
}
else {
drawDispListwire(lb);
}
break;
case OB_MBALL:
if( is_basis_mball(ob)) {
lb= &ob->disp;
if(lb->first==0) makeDispList(ob);
if(solid) {
if(dt==OB_SHADED) {
dl= lb->first;
if(dl && dl->col1==0) shadeDispList(ob);
drawDispListshaded(lb, ob);
}
else {
init_gl_materials(ob);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
drawDispListsolid(lb, ob);
}
}
else{
/* MetaBalls use DL_INDEX4 type of DispList */
drawDispListwire(lb);
}
}
break;
}
}
/* ******************************** */
static void draw_particle_system(Object *ob, PartEff *paf)
{
Particle *pa;
float ptime, ctime, vec[3], vec1[3];
int a;
pa= paf->keys;
if(pa==0) {
build_particle_system(ob);
pa= paf->keys;
if(pa==0) return;
}
myloadmatrix(G.vd->viewmat);
if(ob->ipoflag & OB_OFFS_PARTICLE) ptime= ob->sf;
else ptime= 0.0;
ctime= bsystem_time(ob, 0, (float)(G.scene->r.cfra), ptime);
glPointSize(1.0);
if(paf->stype!=PAF_VECT) glBegin(GL_POINTS);
for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
if(ctime > pa->time) {
if(ctime < pa->time+pa->lifetime) {
if(paf->stype==PAF_VECT) {
where_is_particle(paf, pa, ctime, vec);
where_is_particle(paf, pa, ctime+1.0, vec1);
glBegin(GL_LINE_STRIP);
glVertex3fv(vec);
glVertex3fv(vec1);
glEnd();
}
else {
where_is_particle(paf, pa, ctime, vec);
glVertex3fv(vec);
}
}
}
}
if(paf->stype!=PAF_VECT) glEnd();
mymultmatrix(ob->obmat); // bring back local matrix for dtx
}
static void draw_static_particle_system(Object *ob, PartEff *paf)
{
Particle *pa;
float ctime, mtime, vec[3], vec1[3];
int a;
pa= paf->keys;
if(pa==0) {
build_particle_system(ob);
pa= paf->keys;
if(pa==0) return;
}
glPointSize(1.0);
if(paf->stype!=PAF_VECT) glBegin(GL_POINTS);
for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
where_is_particle(paf, pa, pa->time, vec1);
mtime= pa->time+pa->lifetime+paf->staticstep-1;
for(ctime= pa->time; ctime<mtime; ctime+=paf->staticstep) {
/* make sure hair grows until the end.. */
if(ctime>pa->time+pa->lifetime) ctime= pa->time+pa->lifetime;
if(paf->stype==PAF_VECT) {
where_is_particle(paf, pa, ctime+1, vec);
glBegin(GL_LINE_STRIP);
glVertex3fv(vec);
glVertex3fv(vec1);
glEnd();
VECCOPY(vec1, vec);
}
else {
where_is_particle(paf, pa, ctime, vec);
glVertex3fv(vec);
}
}
}
if(paf->stype!=PAF_VECT) glEnd();
}
unsigned int nurbcol[8]= {
0, 0x9090, 0x409030, 0x603080, 0, 0x40fff0, 0x40c033, 0xA090F0 };
static void tekenhandlesN(Nurb *nu, short sel)
{
BezTriple *bezt;
float *fp;
unsigned int *col;
int a;
if(nu->hide) return;
if( (nu->type & 7)==1) {
if(sel) col= nurbcol+4;
else col= nurbcol;
bezt= nu->bezt;
a= nu->pntsu;
while(a--) {
if(bezt->hide==0) {
if( (bezt->f2 & 1)==sel) {
fp= bezt->vec[0];
cpack(col[bezt->h1]);
glBegin(GL_LINE_STRIP);
glVertex3fv(fp);
glVertex3fv(fp+3);
glEnd();
cpack(col[bezt->h2]);
glBegin(GL_LINE_STRIP);
glVertex3fv(fp+3);
glVertex3fv(fp+6);
glEnd();
}
else if( (bezt->f1 & 1)==sel) {
fp= bezt->vec[0];
cpack(col[bezt->h1]);
glBegin(GL_LINE_STRIP);
glVertex3fv(fp);
glVertex3fv(fp+3);
glEnd();
}
else if( (bezt->f3 & 1)==sel) {
fp= bezt->vec[1];
cpack(col[bezt->h2]);
glBegin(GL_LINE_STRIP);
glVertex3fv(fp);
glVertex3fv(fp+3);
glEnd();
}
}
bezt++;
}
}
}
static void tekenvertsN(Nurb *nu, short sel)
{
BezTriple *bezt;
BPoint *bp;
float size;
int a;
if(nu->hide) return;
if(sel) BIF_ThemeColor(TH_VERTEX_SELECT);
else BIF_ThemeColor(TH_VERTEX);
size= BIF_GetThemeValuef(TH_VERTEX_SIZE);
glPointSize(size);
bglBegin(GL_POINTS);
if((nu->type & 7)==1) {
bezt= nu->bezt;
a= nu->pntsu;
while(a--) {
if(bezt->hide==0) {
if((bezt->f1 & 1)==sel) bglVertex3fv(bezt->vec[0]);
if((bezt->f2 & 1)==sel) bglVertex3fv(bezt->vec[1]);
if((bezt->f3 & 1)==sel) bglVertex3fv(bezt->vec[2]);
}
bezt++;
}
}
else {
bp= nu->bp;
a= nu->pntsu*nu->pntsv;
while(a--) {
if(bp->hide==0) {
if((bp->f1 & 1)==sel) bglVertex3fv(bp->vec);
}
bp++;
}
}
bglEnd();
glPointSize(1.0);
}
static void draw_editnurb(Object *ob, Nurb *nurb, int sel)
{
Nurb *nu;
BPoint *bp, *bp1;
int a, b, ofs;
nu= nurb;
while(nu) {
if(nu->hide==0) {
switch(nu->type & 7) {
case CU_POLY:
cpack(nurbcol[3]);
bp= nu->bp;
for(b=0; b<nu->pntsv; b++) {
if(nu->flagu & 1) glBegin(GL_LINE_LOOP);
else glBegin(GL_LINE_STRIP);
for(a=0; a<nu->pntsu; a++, bp++) {
glVertex3fv(bp->vec);
}
if(nu->flagu & 1) glEnd();
else glEnd();
}
break;
case CU_NURBS:
bp= nu->bp;
for(b=0; b<nu->pntsv; b++) {
bp1= bp;
bp++;
for(a=nu->pntsu-1; a>0; a--, bp++) {
if(bp->hide==0 && bp1->hide==0) {
if(sel) {
if( (bp->f1 & 1) && ( bp1->f1 & 1) ) {
cpack(nurbcol[5]);
glBegin(GL_LINE_STRIP);
glVertex3fv(bp->vec);
glVertex3fv(bp1->vec);
glEnd();
}
}
else {
if( (bp->f1 & 1) && ( bp1->f1 & 1) );
else {
cpack(nurbcol[1]);
glBegin(GL_LINE_STRIP);
glVertex3fv(bp->vec);
glVertex3fv(bp1->vec);
glEnd();
}
}
}
bp1= bp;
}
}
if(nu->pntsv > 1) { /* surface */
ofs= nu->pntsu;
for(b=0; b<nu->pntsu; b++) {
bp1= nu->bp+b;
bp= bp1+ofs;
for(a=nu->pntsv-1; a>0; a--, bp+=ofs) {
if(bp->hide==0 && bp1->hide==0) {
if(sel) {
if( (bp->f1 & 1) && ( bp1->f1 & 1) ) {
cpack(nurbcol[7]);
glBegin(GL_LINE_STRIP);
glVertex3fv(bp->vec);
glVertex3fv(bp1->vec);
glEnd();
}
}
else {
if( (bp->f1 & 1) && ( bp1->f1 & 1) );
else {
cpack(nurbcol[3]);
glBegin(GL_LINE_STRIP);
glVertex3fv(bp->vec);
glVertex3fv(bp1->vec);
glEnd();
}
}
}
bp1= bp;
}
}
}
break;
}
}
nu= nu->next;
}
}
static void drawnurb(Object *ob, Nurb *nurb, int dt)
{
Curve *cu;
Nurb *nu;
BevPoint *bevp;
BevList *bl;
float vec[3];
int a, nr, skip;
/* first non-selected handles */
nu= nurb;
while(nu) {
if((nu->type & 7)==CU_BEZIER) {
tekenhandlesN(nu, 0);
}
nu= nu->next;
}
/* then DispList */
BIF_ThemeColor(TH_WIRE);
cu= ob->data;
drawDispList(ob, dt);
draw_editnurb(ob, nurb, 0);
draw_editnurb(ob, nurb, 1);
if(cu->flag & CU_3D) {
if(cu->bev.first==0) makeBevelList(ob);
BIF_ThemeColor(TH_WIRE);
bl= cu->bev.first;
nu= nurb;
while(nu && bl) {
bevp= (BevPoint *)(bl+1);
nr= bl->nr;
skip= nu->resolu/16;
while(nr-- > 0) {
glBegin(GL_LINE_STRIP);
vec[0]= bevp->x-G.scene->editbutsize*bevp->mat[0][0];
vec[1]= bevp->y-G.scene->editbutsize*bevp->mat[0][1];
vec[2]= bevp->z-G.scene->editbutsize*bevp->mat[0][2];
glVertex3fv(vec);
vec[0]= bevp->x+G.scene->editbutsize*bevp->mat[0][0];
vec[1]= bevp->y+G.scene->editbutsize*bevp->mat[0][1];
vec[2]= bevp->z+G.scene->editbutsize*bevp->mat[0][2];
glVertex3fv(vec);
glEnd();
bevp++;
a= skip;
while(a--) {
bevp++;
nr--;
}
}
bl= bl->next;
nu= nu->next;
}
}
calc_Nurbverts(nurb);
if(G.zbuf) glDisable(GL_DEPTH_TEST);
nu= nurb;
while(nu) {
if((nu->type & 7)==1) tekenhandlesN(nu, 1);
tekenvertsN(nu, 0);
nu= nu->next;
}
nu= nurb;
while(nu) {
tekenvertsN(nu, 1);
nu= nu->next;
}
if(G.zbuf) glEnable(GL_DEPTH_TEST);
}
static void tekentextcurs(void)
{
cpack(0);
glBegin(GL_QUADS);
glVertex2fv(G.textcurs[0]);
glVertex2fv(G.textcurs[1]);
glVertex2fv(G.textcurs[2]);
glVertex2fv(G.textcurs[3]);
glEnd();
}
static void drawspiral(float *cent, float rad, float tmat[][4], int start)
{
float vec[3], vx[3], vy[3];
int a, tot=32;
char inverse=0;
/* 32 values of sin function (still same result!) */
static float si[32] = {0.00000000,
0.20129852,
0.39435585,
0.57126821,
0.72479278,
0.84864425,
0.93775213,
0.98846832,
0.99871650,
0.96807711,
0.89780453,
0.79077573,
0.65137248,
0.48530196,
0.29936312,
0.10116832,
-0.10116832,
-0.29936312,
-0.48530196,
-0.65137248,
-0.79077573,
-0.89780453,
-0.96807711,
-0.99871650,
-0.98846832,
-0.93775213,
-0.84864425,
-0.72479278,
-0.57126821,
-0.39435585,
-0.20129852,
0.00000000};
/* 32 values of cos function (still same result!) */
static float co[32] ={1.00000000,
0.97952994,
0.91895781,
0.82076344,
0.68896691,
0.52896401,
0.34730525,
0.15142777,
-0.05064916,
-0.25065253,
-0.44039415,
-0.61210598,
-0.75875812,
-0.87434661,
-0.95413925,
-0.99486932,
-0.99486932,
-0.95413925,
-0.87434661,
-0.75875812,
-0.61210598,
-0.44039415,
-0.25065253,
-0.05064916,
0.15142777,
0.34730525,
0.52896401,
0.68896691,
0.82076344,
0.91895781,
0.97952994,
1.00000000};
if (start < 0) {
inverse = 1;
start *= -1;
}
VECCOPY(vx, tmat[0]);
VECCOPY(vy, tmat[1]);
VecMulf(vx, rad);
VecMulf(vy, rad);
VECCOPY(vec, cent);
if (inverse==0) {
for(a=0; a<tot; a++) {
if (a+start>31)
start=-a + 1;
glBegin(GL_LINES);
glVertex3fv(vec);
vec[0]= cent[0] + *(si+a+start) * (vx[0] * (float)a/(float)tot) + *(co+a+start) * (vy[0] * (float)a/(float)tot);
vec[1]= cent[1] + *(si+a+start) * (vx[1] * (float)a/(float)tot) + *(co+a+start) * (vy[1] * (float)a/(float)tot);
vec[2]= cent[2] + *(si+a+start) * (vx[2] * (float)a/(float)tot) + *(co+a+start) * (vy[2] * (float)a/(float)tot);
glVertex3fv(vec);
glEnd();
}
}
else {
a=0;
vec[0]= cent[0] + *(si+a+start) * (vx[0] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[0] * (float)(-a+31)/(float)tot);
vec[1]= cent[1] + *(si+a+start) * (vx[1] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[1] * (float)(-a+31)/(float)tot);
vec[2]= cent[2] + *(si+a+start) * (vx[2] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[2] * (float)(-a+31)/(float)tot);
for(a=0; a<tot; a++) {
if (a+start>31)
start=-a + 1;
glBegin(GL_LINES);
glVertex3fv(vec);
vec[0]= cent[0] + *(si+a+start) * (vx[0] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[0] * (float)(-a+31)/(float)tot);
vec[1]= cent[1] + *(si+a+start) * (vx[1] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[1] * (float)(-a+31)/(float)tot);
vec[2]= cent[2] + *(si+a+start) * (vx[2] * (float)(-a+31)/(float)tot) + *(co+a+start) * (vy[2] * (float)(-a+31)/(float)tot);
glVertex3fv(vec);
glEnd();
}
}
}
void drawcircball(int mode, float *cent, float rad, float tmat[][4])
{
float vec[3], vx[3], vy[3];
int a, tot=32;
/* 32 values of sin function (still same result!) */
static float si[32] = {0.00000000,
0.20129852,
0.39435585,
0.57126821,
0.72479278,
0.84864425,
0.93775213,
0.98846832,
0.99871650,
0.96807711,
0.89780453,
0.79077573,
0.65137248,
0.48530196,
0.29936312,
0.10116832,
-0.10116832,
-0.29936312,
-0.48530196,
-0.65137248,
-0.79077573,
-0.89780453,
-0.96807711,
-0.99871650,
-0.98846832,
-0.93775213,
-0.84864425,
-0.72479278,
-0.57126821,
-0.39435585,
-0.20129852,
0.00000000};
/* 32 values of cos function (still same result!) */
static float co[32] ={1.00000000,
0.97952994,
0.91895781,
0.82076344,
0.68896691,
0.52896401,
0.34730525,
0.15142777,
-0.05064916,
-0.25065253,
-0.44039415,
-0.61210598,
-0.75875812,
-0.87434661,
-0.95413925,
-0.99486932,
-0.99486932,
-0.95413925,
-0.87434661,
-0.75875812,
-0.61210598,
-0.44039415,
-0.25065253,
-0.05064916,
0.15142777,
0.34730525,
0.52896401,
0.68896691,
0.82076344,
0.91895781,
0.97952994,
1.00000000};
VECCOPY(vx, tmat[0]);
VECCOPY(vy, tmat[1]);
VecMulf(vx, rad);
VecMulf(vy, rad);
glBegin(mode);
for(a=0; a<tot; a++) {
vec[0]= cent[0] + *(si+a) * vx[0] + *(co+a) * vy[0];
vec[1]= cent[1] + *(si+a) * vx[1] + *(co+a) * vy[1];
vec[2]= cent[2] + *(si+a) * vx[2] + *(co+a) * vy[2];
glVertex3fv(vec);
}
glEnd();
}
static void drawmball(Object *ob, int dt)
{
MetaBall *mb;
MetaElem *ml;
float imat[4][4], tmat[4][4];
int code= 1;
mb= ob->data;
if(ob==G.obedit) {
BIF_ThemeColor(TH_WIRE);
if((G.f & G_PICKSEL)==0 ) drawDispList(ob, dt);
ml= editelems.first;
}
else {
drawDispList(ob, dt);
ml= mb->elems.first;
}
/* in case solid draw, reset wire colors */
if(ob!=G.obedit && (ob->flag & SELECT)) {
if(ob==OBACT) BIF_ThemeColor(TH_ACTIVE);
else BIF_ThemeColor(TH_SELECT);
}
else BIF_ThemeColor(TH_WIRE);
mygetmatrix(tmat);
Mat4Invert(imat, tmat);
Normalise(imat[0]);
Normalise(imat[1]);
while(ml) {
/* draw radius */
if(ob==G.obedit) {
if((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) cpack(0xA0A0F0);
else cpack(0x3030A0);
if(G.f & G_PICKSEL) {
ml->selcol1= code;
glLoadName(code++);
}
}
drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad, imat);
/* draw stiffness */
if(ob==G.obedit) {
if((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) cpack(0xA0F0A0);
else cpack(0x30A030);
if(G.f & G_PICKSEL) {
ml->selcol2= code;
glLoadName(code++);
}
}
drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad*atan(ml->s)/M_PI_2, imat);
ml= ml->next;
}
}
static void draw_forcefield(Object *ob)
{
PartDeflect *pd= ob->pd;
float imat[4][4], tmat[4][4];
float vec[3]= {0.0, 0.0, 0.0};
/* calculus here, is reused in PFIELD_FORCE */
mygetmatrix(tmat);
Mat4Invert(imat, tmat);
// Normalise(imat[0]); // we don't do this because field doesnt scale either... apart from wind!
// Normalise(imat[1]);
if(pd->flag & PFIELD_USEMAX) {
setlinestyle(3);
BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5);
drawcircball(GL_LINE_LOOP, vec, pd->maxdist, imat);
setlinestyle(0);
}
if (pd->forcefield == PFIELD_WIND) {
float force_val;
Mat4One(tmat);
BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5);
if (has_ipo_code(ob->ipo, OB_PD_FSTR))
force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, G.scene->r.cfra);
else
force_val = pd->f_strength;
force_val*= 0.1;
drawcircball(GL_LINE_LOOP, vec, 1.0, tmat);
vec[2]= 0.5*force_val;
drawcircball(GL_LINE_LOOP, vec, 1.0, tmat);
vec[2]= 1.0*force_val;
drawcircball(GL_LINE_LOOP, vec, 1.0, tmat);
vec[2]= 1.5*force_val;
drawcircball(GL_LINE_LOOP, vec, 1.0, tmat);
}
else if (pd->forcefield == PFIELD_FORCE) {
float ffall_val;
if (has_ipo_code(ob->ipo, OB_PD_FFALL))
ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, G.scene->r.cfra);
else
ffall_val = pd->f_power;
BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5);
drawcircball(GL_LINE_LOOP, vec, 1.0, imat);
BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.9 - 0.4 / pow(1.5, (double)ffall_val));
drawcircball(GL_LINE_LOOP, vec, 1.5, imat);
BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.9 - 0.4 / pow(2.0, (double)ffall_val));
drawcircball(GL_LINE_LOOP, vec, 2.0, imat);
}
else if (pd->forcefield == PFIELD_VORTEX) {
float ffall_val, force_val;
Mat4One(imat);
if (has_ipo_code(ob->ipo, OB_PD_FFALL))
ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, G.scene->r.cfra);
else
ffall_val = pd->f_power;
if (has_ipo_code(ob->ipo, OB_PD_FSTR))
force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, G.scene->r.cfra);
else
force_val = pd->f_strength;
BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
if (force_val < 0) {
drawspiral(vec, 1.0, imat, 1);
drawspiral(vec, 1.0, imat, 16);
}
else {
drawspiral(vec, 1.0, imat, -1);
drawspiral(vec, 1.0, imat, -16);
}
}
}
static void draw_bb_box(BoundBox *bb)
{
float *vec;
vec= bb->vec[0];
glBegin(GL_LINE_STRIP);
glVertex3fv(vec); glVertex3fv(vec+3);glVertex3fv(vec+6); glVertex3fv(vec+9);
glVertex3fv(vec); glVertex3fv(vec+12);glVertex3fv(vec+15); glVertex3fv(vec+18);
glVertex3fv(vec+21); glVertex3fv(vec+12);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3fv(vec+3); glVertex3fv(vec+15);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3fv(vec+6); glVertex3fv(vec+18);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3fv(vec+9); glVertex3fv(vec+21);
glEnd();
}
void get_local_bounds(Object *ob, float *centre, float *size)
{
BoundBox *bb= NULL;
/* uses boundbox, function used by Ketsji */
if(ob->type==OB_MESH) {
bb= ( (Mesh *)ob->data )->bb;
if(bb==0) {
tex_space_mesh(ob->data);
bb= ( (Mesh *)ob->data )->bb;
}
}
else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
bb= ( (Curve *)ob->data )->bb;
}
else if(ob->type==OB_MBALL) {
bb= ob->bb;
}
if(bb==NULL) {
centre[0]= centre[1]= centre[2]= 0.0;
VECCOPY(size, ob->size);
}
else {
size[0]= 0.5*fabs(bb->vec[0][0] - bb->vec[4][0]);
size[1]= 0.5*fabs(bb->vec[0][1] - bb->vec[2][1]);
size[2]= 0.5*fabs(bb->vec[0][2] - bb->vec[1][2]);
centre[0]= (bb->vec[0][0] + bb->vec[4][0])/2.0;
centre[1]= (bb->vec[0][1] + bb->vec[2][1])/2.0;
centre[2]= (bb->vec[0][2] + bb->vec[1][2])/2.0;
}
}
static void draw_bb_quadric(BoundBox *bb, short type)
{
float size[3], cent[3];
GLUquadricObj *qobj = gluNewQuadric();
gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
size[0]= 0.5*fabs(bb->vec[0][0] - bb->vec[4][0]);
size[1]= 0.5*fabs(bb->vec[0][1] - bb->vec[2][1]);
size[2]= 0.5*fabs(bb->vec[0][2] - bb->vec[1][2]);
cent[0]= (bb->vec[0][0] + bb->vec[4][0])/2.0;
cent[1]= (bb->vec[0][1] + bb->vec[2][1])/2.0;
cent[2]= (bb->vec[0][2] + bb->vec[1][2])/2.0;
glPushMatrix();
if(type==OB_BOUND_SPHERE) {
glTranslatef(cent[0], cent[1], cent[2]);
glScalef(size[0], size[1], size[2]);
gluSphere(qobj, 1.0, 8, 5);
}
else if(type==OB_BOUND_CYLINDER) {
float radius = size[0] > size[1] ? size[0] : size[1];
glTranslatef(cent[0], cent[1], cent[2]-size[2]);
glScalef(radius, radius, 2.0*size[2]);
gluCylinder(qobj, 1.0, 1.0, 1.0, 8, 1);
}
else if(type==OB_BOUND_CONE) {
float radius = size[0] > size[1] ? size[0] : size[1];
glTranslatef(cent[0], cent[2]-size[2], cent[1]);
glScalef(radius, 2.0*size[2], radius);
glRotatef(-90., 1.0, 0.0, 0.0);
gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
}
glPopMatrix();
gluDeleteQuadric(qobj);
}
static void draw_bounding_volume(Object *ob)
{
BoundBox *bb=0;
if(ob->type==OB_MESH) {
bb= ( (Mesh *)ob->data )->bb;
if(bb==0) {
tex_space_mesh(ob->data);
bb= ( (Mesh *)ob->data )->bb;
}
}
else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
bb= ( (Curve *)ob->data )->bb;
if(bb==0) {
makeDispList(ob);
bb= ( (Curve *)ob->data )->bb;
}
}
else if(ob->type==OB_MBALL) {
bb= ob->bb;
if(bb==0) {
makeDispList(ob);
bb= ob->bb;
}
}
else {
drawcube();
return;
}
if(bb==0) return;
if(ob->boundtype==OB_BOUND_BOX) draw_bb_box(bb);
else draw_bb_quadric(bb, ob->boundtype);
}
static void drawtexspace(Object *ob)
{
Mesh *me;
MetaBall *mb;
Curve *cu;
BoundBox bb;
float *vec, *loc, *size;
if(ob->type==OB_MESH) {
me= ob->data;
size= me->size;
loc= me->loc;
}
else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
cu= ob->data;
size= cu->size;
loc= cu->loc;
}
else if(ob->type==OB_MBALL) {
mb= ob->data;
size= mb->size;
loc= mb->loc;
}
else return;
bb.vec[0][0]=bb.vec[1][0]=bb.vec[2][0]=bb.vec[3][0]= loc[0]-size[0];
bb.vec[4][0]=bb.vec[5][0]=bb.vec[6][0]=bb.vec[7][0]= loc[0]+size[0];
bb.vec[0][1]=bb.vec[1][1]=bb.vec[4][1]=bb.vec[5][1]= loc[1]-size[1];
bb.vec[2][1]=bb.vec[3][1]=bb.vec[6][1]=bb.vec[7][1]= loc[1]+size[1];
bb.vec[0][2]=bb.vec[3][2]=bb.vec[4][2]=bb.vec[7][2]= loc[2]-size[2];
bb.vec[1][2]=bb.vec[2][2]=bb.vec[5][2]=bb.vec[6][2]= loc[2]+size[2];
setlinestyle(2);
vec= bb.vec[0];
glBegin(GL_LINE_STRIP);
glVertex3fv(vec); glVertex3fv(vec+3);glVertex3fv(vec+6); glVertex3fv(vec+9);
glVertex3fv(vec); glVertex3fv(vec+12);glVertex3fv(vec+15); glVertex3fv(vec+18);
glVertex3fv(vec+21); glVertex3fv(vec+12);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3fv(vec+3); glVertex3fv(vec+15);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3fv(vec+6); glVertex3fv(vec+18);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3fv(vec+9); glVertex3fv(vec+21);
glEnd();
setlinestyle(0);
}
/* draws wire outline */
static void drawSolidSelect(Object *ob)
{
glLineWidth(2.0);
glDepthMask(0);
if(ELEM3(ob->type, OB_FONT,OB_CURVE, OB_SURF)) {
Curve *cu = ob->data;
if (displist_has_faces(&cu->disp) && boundbox_clip(ob->obmat, cu->bb)) {
drawDispListwire(&cu->disp);
}
} else if (ob->type==OB_MBALL) {
drawDispListwire(&ob->disp);
}
glLineWidth(1.0);
glDepthMask(1);
}
static void drawWireExtra(Object *ob)
{
if(ob!=G.obedit && (ob->flag & SELECT)) {
if(ob==OBACT) BIF_ThemeColor(TH_ACTIVE);
else BIF_ThemeColor(TH_SELECT);
}
else BIF_ThemeColor(TH_WIRE);
bglPolygonOffset(1.0);
glDepthMask(0); // disable write in zbuffer, selected edge wires show better
if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
Curve *cu = ob->data;
if (boundbox_clip(ob->obmat, cu->bb)) {
if (ob->type==OB_CURVE)
draw_index_wire= 0;
drawDispListwire(&cu->disp);
if (ob->type==OB_CURVE)
draw_index_wire= 1;
}
} else if (ob->type==OB_MBALL) {
drawDispListwire(&ob->disp);
}
glDepthMask(1);
bglPolygonOffset(0.0);
}
/* should be called in view space */
static void draw_hooks(Object *ob)
{
ObHook *hook;
float vec[3];
for(hook= ob->hooks.first; hook; hook= hook->next) {
VecMat4MulVecfl(vec, ob->obmat, hook->cent);
if(hook->parent) {
setlinestyle(3);
glBegin(GL_LINES);
glVertex3fv(hook->parent->obmat[3]);
glVertex3fv(vec);
glEnd();
setlinestyle(0);
}
glPointSize(3.0);
bglBegin(GL_POINTS);
bglVertex3fv(vec);
bglEnd();
glPointSize(1.0);
}
}
void draw_object(Base *base)
{
Object *ob;
Curve *cu;
ListBase elems;
CfraElem *ce;
float cfraont, axsize=1.0;
unsigned int *rect, col=0;
static int warning_recursive= 0;
int sel, drawtype, colindex= 0, ipoflag;
short dt, dtx, zbufoff= 0;
ob= base->object;
/* draw keys? */
if(base==(G.scene->basact) || (base->flag & (SELECT+BA_WASSEL))) {
if(warning_recursive==0 && ob!=G.obedit) {
if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
float temp[7][3];
warning_recursive= 1;
elems.first= elems.last= 0;
make_cfra_list(ob->ipo, &elems);
cfraont= (G.scene->r.cfra);
drawtype= G.vd->drawtype;
if(drawtype>OB_WIRE) G.vd->drawtype= OB_WIRE;
sel= base->flag;
memcpy(temp, &ob->loc, 7*3*sizeof(float));
ipoflag= ob->ipoflag;
ob->ipoflag &= ~OB_OFFS_OB;
set_no_parent_ipo(1);
disable_speed_curve(1);
if ((ob->ipoflag & OB_DRAWKEYSEL)==0) {
ce= elems.first;
while(ce) {
if(!ce->sel) {
(G.scene->r.cfra)= ce->cfra/G.scene->r.framelen;
base->flag= 0;
where_is_object_time(ob, (G.scene->r.cfra));
draw_object(base);
}
ce= ce->next;
}
}
ce= elems.first;
while(ce) {
if(ce->sel) {
(G.scene->r.cfra)= ce->cfra/G.scene->r.framelen;
base->flag= SELECT;
where_is_object_time(ob, (G.scene->r.cfra));
draw_object(base);
}
ce= ce->next;
}
set_no_parent_ipo(0);
disable_speed_curve(0);
base->flag= sel;
ob->ipoflag= ipoflag;
/* restore icu->curval */
(G.scene->r.cfra)= cfraont;
memcpy(&ob->loc, temp, 7*3*sizeof(float));
where_is_object(ob);
G.vd->drawtype= drawtype;
BLI_freelistN(&elems);
warning_recursive= 0;
}
}
}
/* patch? children objects with a timeoffs change the parents. How to solve! */
/* if( ((int)ob->ctime) != F_(G.scene->r.cfra)) where_is_object(ob); */
mymultmatrix(ob->obmat);
/* which wire color */
if((G.f & G_PICKSEL) == 0) {
project_short(ob->obmat[3], &base->sx);
if((G.moving & G_TRANSFORM_OBJ) && (base->flag & (SELECT+BA_PARSEL))) BIF_ThemeColor(TH_TRANSFORM);
else {
BIF_ThemeColor(TH_WIRE);
if((G.scene->basact)==base) {
if(base->flag & (SELECT+BA_WASSEL)) BIF_ThemeColor(TH_ACTIVE);
}
else {
if(base->flag & (SELECT+BA_WASSEL)) BIF_ThemeColor(TH_SELECT);
}
// no theme yet
if(ob->id.lib) {
if(base->flag & (SELECT+BA_WASSEL)) colindex = 4;
else colindex = 3;
}
else if(warning_recursive==1) {
if(base->flag & (SELECT+BA_WASSEL)) colindex = 7;
else colindex = 6;
}
}
if(colindex) {
col= colortab[colindex];
cpack(col);
}
}
/* maximum drawtype */
dt= MIN2(G.vd->drawtype, ob->dt);
if(G.zbuf==0 && dt>OB_WIRE) dt= OB_WIRE;
dtx= 0;
/* faceselect exception: also draw solid when dt==wire, except in editmode */
if(ob==((G.scene->basact) ? (G.scene->basact->object) : 0) && (G.f & (G_FACESELECT+G_VERTEXPAINT+G_TEXTUREPAINT+G_WEIGHTPAINT))) {
if(ob->type==OB_MESH) {
if(ob==G.obedit);
else {
dt= OB_SHADED;
glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
zbufoff= 1;
}
}
else {
if(dt<OB_SOLID) {
dt= OB_SOLID;
glClearDepth(1.); glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
zbufoff= 1;
}
}
}
if(dt>=OB_WIRE ) {
dtx= ob->dtx;
if(G.obedit==ob) {
// the only 2 extra drawtypes alowed in editmode
dtx= dtx & (OB_DRAWWIRE|OB_TEXSPACE);
}
if(G.f & G_DRAW_EXT) {
if(ob->type==OB_EMPTY || ob->type==OB_CAMERA || ob->type==OB_LAMP) dt= OB_WIRE;
}
}
/* draw outline for selected solid objects, mesh does itself */
if((G.vd->flag & V3D_SELECT_OUTLINE) && ob->type!=OB_MESH) {
if(dt>OB_WIRE && dt<OB_TEXTURE && ob!=G.obedit) {
if (!(ob->dtx&OB_DRAWWIRE) && (ob->flag&SELECT)) {
drawSolidSelect(ob);
}
}
}
switch( ob->type) {
case OB_MESH:
if (!(base->flag&OB_RADIO)) {
draw_mesh_object(ob, dt);
dtx &= ~OB_DRAWWIRE; // mesh draws wire itself
{
PartEff *paf = give_parteff(ob);
if(paf) {
if(col) cpack(0xFFFFFF); /* for visibility */
if(paf->flag & PAF_STATIC) draw_static_particle_system(ob, paf);
else if((G.f & G_PICKSEL) == 0) draw_particle_system(ob, paf); // selection errors happen to easy
if(col) cpack(col);
}
}
}
break;
case OB_FONT:
cu= ob->data;
if(ob==G.obedit) {
tekentextcurs();
cpack(0xFFFF90);
drawDispList(ob, OB_WIRE);
}
else if(dt==OB_BOUNDBOX) draw_bounding_volume(ob);
else if(boundbox_clip(ob->obmat, cu->bb)) drawDispList(ob, dt);
break;
case OB_CURVE:
case OB_SURF:
cu= ob->data;
if(ob==G.obedit) {
drawnurb(ob, editNurb.first, dt);
}
else if(dt==OB_BOUNDBOX) draw_bounding_volume(ob);
else if(boundbox_clip(ob->obmat, cu->bb)) drawDispList(ob, dt);
break;
case OB_MBALL:
if(ob==G.obedit) drawmball(ob, dt);
else if(dt==OB_BOUNDBOX) draw_bounding_volume(ob);
else drawmball(ob, dt);
break;
case OB_EMPTY:
drawaxes(1.0);
break;
case OB_LAMP:
drawlamp(ob);
break;
case OB_CAMERA:
drawcamera(ob);
break;
case OB_LATTICE:
drawlattice(ob);
break;
case OB_ARMATURE:
draw_armature (ob);
break;
default:
drawaxes(1.0);
}
if(ob->pd && ob->pd->forcefield) draw_forcefield(ob);
/* draw extra: after normal draw because of makeDispList */
if(dtx) {
if(G.f & G_SIMULATION);
else if(dtx & OB_AXIS) {
drawaxes(axsize);
}
if(dtx & OB_BOUNDBOX) draw_bounding_volume(ob);
if(dtx & OB_TEXSPACE) drawtexspace(ob);
if(dtx & OB_DRAWNAME) {
// patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing
if((G.f & G_PICKSEL) == 0) {
glRasterPos3f(0.0, 0.0, 0.0);
BMF_DrawString(G.font, " ");
BMF_DrawString(G.font, ob->id.name+2);
}
}
if(dtx & OB_DRAWIMAGE) drawDispListwire(&ob->disp);
if((dtx & OB_DRAWWIRE) && dt>=OB_SOLID) drawWireExtra(ob);
}
if(dt<OB_SHADED) {
if((ob->gameflag & OB_ACTOR) && (ob->gameflag & OB_DYNAMIC)) {
float tmat[4][4], imat[4][4], vec[3];
vec[0]= vec[1]= vec[2]= 0.0;
mygetmatrix(tmat);
Mat4Invert(imat, tmat);
setlinestyle(2);
drawcircball(GL_LINE_LOOP, vec, ob->inertia, imat);
setlinestyle(0);
}
}
myloadmatrix(G.vd->viewmat);
if(zbufoff) glDisable(GL_DEPTH_TEST);
if(warning_recursive) return;
if(base->flag & OB_FROMDUPLI) return;
if(base->flag & OB_RADIO) return;
if(G.f & G_SIMULATION) return;
if((G.f & (G_PICKSEL))==0) {
ListBase *list;
/* draw hook center and offset line */
if(ob->hooks.first && ob!=G.obedit) draw_hooks(ob);
/* help lines and so */
if(ob!=G.obedit && ob->parent && (ob->parent->lay & G.vd->lay)) {
setlinestyle(3);
glBegin(GL_LINES);
glVertex3fv(ob->obmat[3]);
glVertex3fv(ob->orig);
glEnd();
setlinestyle(0);
}
/* Drawing the constraint lines */
list = &ob->constraints;
if (list){
/*
extern void make_axis_color(char *col, char *col2, char axis); // drawview.c
*/
bConstraint *curcon;
float size[3], tmat[4][4];
char col[4], col2[4];
BIF_GetThemeColor3ubv(TH_GRID, col);
make_axis_color(col, col2, 'z');
glColor3ubv(col2);
for (curcon = list->first; curcon; curcon=curcon->next){
if ((curcon->flag & CONSTRAINT_EXPAND)&&(curcon->type!=CONSTRAINT_TYPE_NULL)&&(constraint_has_target(curcon))){
get_constraint_target_matrix(curcon, TARGET_OBJECT, NULL, tmat, size, bsystem_time(ob, 0, (float)(G.scene->r.cfra), ob->sf));
setlinestyle(3);
glBegin(GL_LINES);
glVertex3fv(tmat[3]);
glVertex3fv(ob->obmat[3]);
glEnd();
setlinestyle(0);
}
}
}
/* object centers */
if(G.zbuf) glDisable(GL_DEPTH_TEST);
if(ob->type == OB_LAMP) {
if(ob->id.lib) {
if(base->flag & SELECT) rect= rectllib_sel;
else rect= rectllib_desel;
}
else if(ob->id.us>1) {
if(base->flag & SELECT) rect= rectlus_sel;
else rect= rectlus_desel;
}
else {
if(base->flag & SELECT) rect= rectl_sel;
else rect= rectl_desel;
}
draw_icon_centered(ob->obmat[3], rect, 9);
}
else {
if(ob->id.lib || ob->id.us>1) {
if(base->flag & SELECT) rect= rectu_sel;
else rect= rectu_desel;
}
else {
if(base->flag & SELECT) rect= rect_sel;
/* The center of the active object (which need not
* be selected) gets drawn as if it were selected
*/
else if(base==(G.scene->basact)) rect= rect_sel;
else rect= rect_desel;
}
draw_icon_centered(ob->obmat[3], rect, 4);
}
if(G.zbuf) glEnable(GL_DEPTH_TEST);
}
else if((G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT))==0) {
glBegin(GL_POINTS);
glVertex3fv(ob->obmat[3]);
glEnd();
}
}
void draw_object_ext(Base *base)
{
if(G.vd==NULL || base==NULL) return;
if(G.vd->drawtype > OB_WIRE) {
G.zbuf= 1;
glEnable(GL_DEPTH_TEST);
}
G.f |= G_DRAW_EXT;
glDrawBuffer(GL_FRONT);
persp(PERSP_VIEW);
draw_object(base);
G.f &= ~G_DRAW_EXT;
glFlush(); /* reveil frontbuffer drawing */
glDrawBuffer(GL_BACK);
if(G.zbuf) {
G.zbuf= 0;
glDisable(GL_DEPTH_TEST);
}
curarea->win_swap= WIN_FRONT_OK;
}
/* ***************** BACKBUF SEL (BBS) ********* */
static int bbs_mesh_verts__setDrawOptions(void *userData, EditVert *eve)
{
if (eve->h==0) {
set_framebuffer_index_color((int) eve->prev);
return 1;
} else {
return 0;
}
}
static int bbs_mesh_verts(DerivedMesh *dm, int offset)
{
EditVert *eve, *preveve;
for (eve=G.editMesh->verts.first; eve; eve= eve->next)
eve->prev = (EditVert*) offset++;
glPointSize( BIF_GetThemeValuef(TH_VERTEX_SIZE) );
dm->drawMappedVertsEM(dm, bbs_mesh_verts__setDrawOptions, NULL);
glPointSize(1.0);
for (preveve=NULL, eve=G.editMesh->verts.first; eve; preveve=eve, eve= eve->next)
eve->prev = preveve;
return offset;
}
static int bbs_mesh_wire__setDrawOptions(void *userData, EditEdge *eed)
{
if (eed->h==0) {
set_framebuffer_index_color((int) eed->vn);
return 1;
} else {
return 0;
}
}
static int bbs_mesh_wire(DerivedMesh *dm, int offset)
{
EditEdge *eed;
for(eed= G.editMesh->edges.first; eed; eed= eed->next)
eed->vn= (EditVert*) offset++;
dm->drawMappedEdgesEM(dm, bbs_mesh_wire__setDrawOptions, NULL);
return offset;
}
static int bbs_mesh_solid__setDrawOptions(void *userData, EditFace *efa)
{
if (efa->h==0) {
if (userData) {
set_framebuffer_index_color((int) efa->prev);
}
return 1;
} else {
return 0;
}
}
/* two options, facecolors or black */
static int bbs_mesh_solid(Object *ob, DerivedMesh *dm, int facecol)
{
int glmode, a;
cpack(0);
if(ob==G.obedit) {
if (facecol) {
EditFace *efa, *prevefa;
int b;
// tuck original indices in efa->prev
for(b=1, efa= G.editMesh->faces.first; efa; efa= efa->next, b++)
efa->prev= (EditFace *)(b);
a = b;
dm->drawMappedFacesEM(dm, bbs_mesh_solid__setDrawOptions, (void*) 1);
if(G.scene->selectmode & SCE_SELECT_FACE) {
glPointSize(BIF_GetThemeValuef(TH_FACEDOT_SIZE));
bglBegin(GL_POINTS);
for(efa= G.editMesh->faces.first; efa; efa= efa->next) {
if(efa->h==0 && efa->fgonf!=EM_FGON) {
set_framebuffer_index_color((int)efa->prev);
bglVertex3fv(efa->cent);
}
}
bglEnd();
}
for (prevefa= NULL, efa= G.editMesh->faces.first; efa; prevefa= efa, efa= efa->next)
efa->prev= prevefa;
return a;
} else {
dm->drawMappedFacesEM(dm, bbs_mesh_solid__setDrawOptions, (void*) 0);
return 1;
}
}
else {
Mesh *me= ob->data;
MVert *mvert;
MFace *mface;
TFace *tface;
DispList *dl;
float *extverts=NULL;
int a, totface, hastface;
mvert= me->mvert;
mface= me->mface;
tface= me->tface;
hastface = (me->tface != NULL);
totface= me->totface;
dl= find_displist(&ob->disp, DL_VERTS);
if(dl) extverts= dl->verts;
glBegin(GL_QUADS);
glmode= GL_QUADS;
for(a=0; a<totface; a++, mface++, tface++) {
if(mface->v3) {
if(facecol) {
if(hastface && tface->flag & TF_HIDE) continue;
set_framebuffer_index_color(a+1);
}
if(mface->v4) {if(glmode==GL_TRIANGLES) {glmode= GL_QUADS; glEnd(); glBegin(GL_QUADS);}}
else {if(glmode==GL_QUADS) {glmode= GL_TRIANGLES; glEnd(); glBegin(GL_TRIANGLES);}}
if(extverts) {
glVertex3fv( extverts+3*mface->v1 );
glVertex3fv( extverts+3*mface->v2 );
glVertex3fv( extverts+3*mface->v3 );
if(mface->v4) glVertex3fv( extverts+3*mface->v4 );
}
else {
glVertex3fv( (mvert+mface->v1)->co );
glVertex3fv( (mvert+mface->v2)->co );
glVertex3fv( (mvert+mface->v3)->co );
if(mface->v4) glVertex3fv( (mvert+mface->v4)->co );
}
}
}
glEnd();
return 1;
}
}
void draw_object_backbufsel(Object *ob)
{
extern int em_solidoffs, em_wireoffs, em_vertoffs; // let linker solve it... from editmesh_mods.c
int dmNeedsFree;
DerivedMesh *dm;
mymultmatrix(ob->obmat);
glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
switch( ob->type) {
case OB_MESH:
dm = mesh_get_cage_derived(ob, &dmNeedsFree);
if(G.obedit) {
em_solidoffs= bbs_mesh_solid(ob, dm, G.scene->selectmode & SCE_SELECT_FACE);
bglPolygonOffset(1.0);
// we draw edges always, for loop (select) tools
em_wireoffs= bbs_mesh_wire(dm, em_solidoffs);
if(G.scene->selectmode & SCE_SELECT_VERTEX)
em_vertoffs= bbs_mesh_verts(dm, em_wireoffs);
else em_vertoffs= em_wireoffs;
bglPolygonOffset(0.0);
}
else bbs_mesh_solid(ob, dm, 1); // 1= facecol, faceselect
if (dmNeedsFree) {
dm->release(dm);
}
break;
case OB_CURVE:
case OB_SURF:
break;
}
myloadmatrix(G.vd->viewmat);
}