From f6bd2ad3d0502f04524081e1d8e0a348e7ab6181 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Tue, 12 Jul 2005 16:02:50 +0000 Subject: ACK! Forgot to add the new drawarmature.c file. :) --- source/blender/src/drawarmature.c | 582 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 582 insertions(+) create mode 100644 source/blender/src/drawarmature.c (limited to 'source/blender/src/drawarmature.c') diff --git a/source/blender/src/drawarmature.c b/source/blender/src/drawarmature.c new file mode 100644 index 00000000000..43668b37089 --- /dev/null +++ b/source/blender/src/drawarmature.c @@ -0,0 +1,582 @@ +/** + * $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) 2005 by the Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "MEM_guardedalloc.h" + +#include "BMF_Api.h" + +#include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_constraint_types.h" +#include "DNA_ID.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_view3d_types.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#include "BKE_action.h" +#include "BKE_armature.h" +#include "BKE_constraint.h" +#include "BKE_depsgraph.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" + +#include "BIF_editarmature.h" +#include "BIF_gl.h" +#include "BIF_glutil.h" +#include "BIF_graphics.h" +#include "BIF_interface.h" +#include "BIF_poseobject.h" +#include "BIF_mywindow.h" +#include "BIF_resources.h" +#include "BIF_screen.h" + +#include "BDR_editobject.h" +#include "BDR_drawobject.h" + +#include "BSE_edit.h" +#include "BSE_view.h" +#include "BSE_editaction.h" + +#include "mydevice.h" +#include "blendef.h" +#include "nla.h" + + +/* *************** Armature drawing ******************* */ + +static void draw_bonevert(void) +{ + static GLuint displist=0; + + if(displist==0) { + GLUquadricObj *qobj; + + displist= glGenLists(1); + glNewList(displist, GL_COMPILE_AND_EXECUTE); + + glPushMatrix(); + + qobj = gluNewQuadric(); + gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); + gluDisk( qobj, 0.0, 0.05, 16, 1); + + glRotatef (90, 0, 1, 0); + gluDisk( qobj, 0.0, 0.05, 16, 1); + + glRotatef (90, 1, 0, 0); + gluDisk( qobj, 0.0, 0.05, 16, 1); + + gluDeleteQuadric(qobj); + + glPopMatrix(); + glEndList(); + } + else glCallList(displist); +} + +static void draw_bonevert_solid(void) +{ + static GLuint displist=0; + + if(displist==0) { + GLUquadricObj *qobj; + + displist= glGenLists(1); + glNewList(displist, GL_COMPILE_AND_EXECUTE); + + qobj = gluNewQuadric(); + gluQuadricDrawStyle(qobj, GLU_FILL); + glShadeModel(GL_SMOOTH); + gluSphere( qobj, 0.05, 8, 5); + glShadeModel(GL_FLAT); + gluDeleteQuadric(qobj); + + glEndList(); + } + else glCallList(displist); +} + +static void draw_bone_octahedral() +{ + static GLuint displist=0; + + if(displist==0) { + float vec[6][3]; + + displist= glGenLists(1); + glNewList(displist, GL_COMPILE_AND_EXECUTE); + + vec[0][0]= vec[0][1]= vec[0][2]= 0.0; + vec[5][0]= vec[5][2]= 0.0; vec[5][1]= 1.0; + + vec[1][0]= 0.1; vec[1][2]= 0.1; vec[1][1]= 0.1; + vec[2][0]= 0.1; vec[2][2]= -0.1; vec[2][1]= 0.1; + vec[3][0]= -0.1; vec[3][2]= -0.1; vec[3][1]= 0.1; + vec[4][0]= -0.1; vec[4][2]= 0.1; vec[4][1]= 0.1; + + /* Section 1, sides */ + glBegin(GL_LINE_LOOP); + glVertex3fv(vec[0]); + glVertex3fv(vec[1]); + glVertex3fv(vec[5]); + glVertex3fv(vec[3]); + glVertex3fv(vec[0]); + glVertex3fv(vec[4]); + glVertex3fv(vec[5]); + glVertex3fv(vec[2]); + glEnd(); + + /* Section 1, square */ + glBegin(GL_LINE_LOOP); + glVertex3fv(vec[1]); + glVertex3fv(vec[2]); + glVertex3fv(vec[3]); + glVertex3fv(vec[4]); + glEnd(); + + glEndList(); + } + else glCallList(displist); +} + +static void draw_bone_solid_octahedral(void) +{ + static GLuint displist=0; + + if(displist==0) { + float vec[6][3], nor[3]; + + displist= glGenLists(1); + glNewList(displist, GL_COMPILE_AND_EXECUTE); + + vec[0][0]= vec[0][1]= vec[0][2]= 0.0; + vec[5][0]= vec[5][2]= 0.0; vec[5][1]= 1.0; + + vec[1][0]= 0.1; vec[1][2]= 0.1; vec[1][1]= 0.1; + vec[2][0]= 0.1; vec[2][2]= -0.1; vec[2][1]= 0.1; + vec[3][0]= -0.1; vec[3][2]= -0.1; vec[3][1]= 0.1; + vec[4][0]= -0.1; vec[4][2]= 0.1; vec[4][1]= 0.1; + + + glBegin(GL_TRIANGLES); + /* bottom */ + CalcNormFloat(vec[2], vec[1], vec[0], nor); + glNormal3fv(nor); + glVertex3fv(vec[2]);glVertex3fv(vec[1]);glVertex3fv(vec[0]); + + CalcNormFloat(vec[3], vec[2], vec[0], nor); + glNormal3fv(nor); + glVertex3fv(vec[3]);glVertex3fv(vec[2]);glVertex3fv(vec[0]); + + CalcNormFloat(vec[4], vec[3], vec[0], nor); + glNormal3fv(nor); + glVertex3fv(vec[4]);glVertex3fv(vec[3]);glVertex3fv(vec[0]); + + CalcNormFloat(vec[1], vec[4], vec[0], nor); + glNormal3fv(nor); + glVertex3fv(vec[1]);glVertex3fv(vec[4]);glVertex3fv(vec[0]); + + /* top */ + CalcNormFloat(vec[5], vec[1], vec[2], nor); + glNormal3fv(nor); + glVertex3fv(vec[5]);glVertex3fv(vec[1]);glVertex3fv(vec[2]); + + CalcNormFloat(vec[5], vec[2], vec[3], nor); + glNormal3fv(nor); + glVertex3fv(vec[5]);glVertex3fv(vec[2]);glVertex3fv(vec[3]); + + CalcNormFloat(vec[5], vec[3], vec[4], nor); + glNormal3fv(nor); + glVertex3fv(vec[5]);glVertex3fv(vec[3]);glVertex3fv(vec[4]); + + CalcNormFloat(vec[5], vec[4], vec[1], nor); + glNormal3fv(nor); + glVertex3fv(vec[5]);glVertex3fv(vec[4]);glVertex3fv(vec[1]); + + glEnd(); + + glEndList(); + } + else glCallList(displist); +} + + +static void draw_bone (int dt, int armflag, int boneflag, int constflag, unsigned int id, char *name, float length) +{ + + /* Draw a 3d octahedral bone, we use normalized space based on length, + for glDisplayLists */ + + /* set up solid drawing */ + if(dt > OB_WIRE) { + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_LIGHTING); + BIF_ThemeColor(TH_BONE_SOLID); + } + + /* change the matrix */ + glScalef(length, length, length); + + /* colors for posemode */ + if (armflag & ARM_POSEMODE) { + if(dt==OB_WIRE) { + if (boneflag & BONE_ACTIVE) BIF_ThemeColorShade(TH_BONE_POSE, 40); + else if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_BONE_POSE); + else BIF_ThemeColor(TH_WIRE); + } + else + BIF_ThemeColor(TH_BONE_SOLID); + } + + /* Draw root point if we have no IK parent */ + if (!(boneflag & BONE_IK_TOPARENT)){ + if (id != -1) + glLoadName (id | BONESEL_ROOT); + if (armflag & ARM_EDITMODE) { + if(dt<=OB_WIRE) { + if (boneflag & BONE_ROOTSEL) BIF_ThemeColor(TH_VERTEX_SELECT); + else BIF_ThemeColor(TH_VERTEX); + } + else + BIF_ThemeColor(TH_BONE_SOLID); + } + if(dt>OB_WIRE) draw_bonevert_solid(); + else draw_bonevert(); + } + + /* Draw tip point */ + if (id != -1) + glLoadName (id | BONESEL_TIP); + if (armflag & ARM_EDITMODE) { + if(dt<=OB_WIRE) { + if (boneflag & BONE_TIPSEL) BIF_ThemeColor(TH_VERTEX_SELECT); + else BIF_ThemeColor(TH_VERTEX); + } + else + BIF_ThemeColor(TH_BONE_SOLID); + } + + glTranslatef(0.0, 1.0, 0.0); + if(dt>OB_WIRE) draw_bonevert_solid(); + else draw_bonevert(); + + /* Draw additional axes */ + if (armflag & ARM_DRAWAXES){ + drawaxes(0.25f); + } + + /* now draw the bone itself */ + glTranslatef(0.0, -1.0, 0.0); + + if (id != -1) { + if (armflag & ARM_POSEMODE) + glLoadName((GLuint) id); + else{ + glLoadName ((GLuint) id|BONESEL_BONE); + } + } + + /* wire? */ + if(dt <= OB_WIRE) { + /* colors */ + if (armflag & ARM_EDITMODE) { + if (boneflag & BONE_ACTIVE) BIF_ThemeColor(TH_EDGE_SELECT); + else if (boneflag & BONE_SELECTED) BIF_ThemeColorShade(TH_EDGE_SELECT, -20); + else BIF_ThemeColor(TH_WIRE); + } + else if (armflag & ARM_POSEMODE){ + if(constflag) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + if(constflag & PCHAN_HAS_IK) glColor4ub(255, 255, 0, 100); + else if(constflag & PCHAN_HAS_CONST) glColor4ub(0, 255, 120, 100); + else BIF_ThemeColor4(TH_BONE_POSE); // PCHAN_HAS_ACTION + + draw_bone_solid_octahedral(); + glDisable(GL_BLEND); + + /* restore colors */ + if (boneflag & BONE_ACTIVE) BIF_ThemeColorShade(TH_BONE_POSE, 40); + else if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_BONE_POSE); + else BIF_ThemeColor(TH_WIRE); + } + } + draw_bone_octahedral(); + } + else { /* solid */ + + BIF_ThemeColor(TH_BONE_SOLID); + draw_bone_solid_octahedral(); + } + + /* disable solid drawing */ + if(dt>OB_WIRE) { + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_LIGHTING); + } + + /* Draw the bone name */ + if (name && (armflag & ARM_DRAWNAMES)) { + // patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing + if((G.f & G_PICKSEL) == 0) { + if (armflag & (ARM_EDITMODE|ARM_POSEMODE)) { + if(boneflag & BONE_SELECTED) BIF_ThemeColor(TH_TEXT_HI); + else BIF_ThemeColor(TH_TEXT); + } + else if(dt > OB_WIRE) BIF_ThemeColor(TH_TEXT); + glRasterPos3f(0, 0.5, 0); + BMF_DrawString(G.font, " "); + BMF_DrawString(G.font, name); + } + } +} + +/* assumes object is Armature with pose */ +static void draw_pose_channels(Object *ob, int dt) +{ + bPoseChannel *pchan; + Bone *bone; + bArmature *arm= ob->data; + GLfloat tmp; + int index= -1; + int do_dashed= 1; + short flag, constflag; + + /* little speedup, also make sure transparent only draws once */ + glCullFace(GL_BACK); + glEnable(GL_CULL_FACE); + + /* hacky... prevent outline select from drawing dashed helplines */ + glGetFloatv(GL_LINE_WIDTH, &tmp); + if(tmp > 1.1) do_dashed= 0; + + /* if solid we draw that first, with selection codes, but without names, axes etc */ + if(dt>OB_WIRE) { + if(arm->flag & ARM_POSEMODE) index= 0; + + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + bone= pchan->bone; + if(bone && !(bone->flag & BONE_HIDDEN)) { + glPushMatrix(); + glMultMatrixf(pchan->pose_mat); + + /* catch exception for bone with hidden parent */ + flag= bone->flag; + if(bone->parent && (bone->parent->flag & BONE_HIDDEN)) + flag &= ~BONE_IK_TOPARENT; + + draw_bone(OB_SOLID, arm->flag, flag, 0, index, bone->name, bone->length); + + glPopMatrix(); + } + if (index!= -1) index++; + } + glLoadName (-1); + index= -1; + } + + /* wire draw over solid only in posemode */ + if(dt<=OB_WIRE || (arm->flag & ARM_POSEMODE)) { + + /* if solid && posemode, we draw again with polygonoffset */ + if (dt>OB_WIRE && (arm->flag & ARM_POSEMODE)) + bglPolygonOffset(1.0); + else + /* and we use selection indices if not done yet */ + if (arm->flag & ARM_POSEMODE) index= 0; + + if (arm->flag & ARM_DRAWXRAY) { + if(G.zbuf) glDisable(GL_DEPTH_TEST); + } + + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + bone= pchan->bone; + if(bone && !(bone->flag & BONE_HIDDEN)) { + + // Draw a line from our root to the parent's tip + if (do_dashed && bone->parent && !(bone->flag & BONE_IK_TOPARENT) ){ + if (arm->flag & ARM_POSEMODE) { + glLoadName (-1); + BIF_ThemeColor(TH_WIRE); + } + setlinestyle(3); + glBegin(GL_LINES); + glVertex3fv(pchan->pose_head); + glVertex3fv(pchan->parent->pose_tail); + glEnd(); + setlinestyle(0); + } + + glPushMatrix(); + glMultMatrixf(pchan->pose_mat); + + /* catch exception for bone with hidden parent */ + flag= bone->flag; + if(bone->parent && (bone->parent->flag & BONE_HIDDEN)) + flag &= ~BONE_IK_TOPARENT; + + /* extra draw service for pose mode */ + constflag= pchan->constflag; + if(pchan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)) + constflag |= PCHAN_HAS_ACTION; + + draw_bone(OB_WIRE, arm->flag, flag, constflag, index, bone->name, bone->length); + + glPopMatrix(); + } + if (index!= -1) index++; + } + } + /* restore things */ + if (dt>OB_WIRE && (arm->flag & ARM_POSEMODE)) + bglPolygonOffset(0.0); + if (arm->flag & ARM_DRAWXRAY) { + if(G.zbuf) glEnable(GL_DEPTH_TEST); + } + glDisable(GL_CULL_FACE); + +} + +/* in editmode, we don't store the bone matrix... */ +static void set_matrix_editbone(EditBone *eBone) +{ + float delta[3],offset[3]; + float mat[3][3], bmat[4][4]; + + /* Compose the parent transforms (i.e. their translations) */ + VECCOPY (offset, eBone->head); + + glTranslatef (offset[0],offset[1],offset[2]); + + delta[0]= eBone->tail[0]-eBone->head[0]; + delta[1]= eBone->tail[1]-eBone->head[1]; + delta[2]= eBone->tail[2]-eBone->head[2]; + + eBone->length = sqrt (delta[0]*delta[0] + delta[1]*delta[1] +delta[2]*delta[2]); + + vec_roll_to_mat3(delta, eBone->roll, mat); + Mat4CpyMat3(bmat, mat); + + glMultMatrixf (bmat); +} + +/* called from drawobject.c */ +void draw_armature(Object *ob, int dt) +{ + bArmature *arm; + + if (ob==NULL || ob->data==NULL) return; // weird check... + arm= ob->data; + + /* we use color for solid lighting */ + glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); + + /* If we're in editmode, draw the Global edit data */ + if(ob==G.obedit || (G.obedit && ob->data==G.obedit->data)) { + EditBone *eBone; + unsigned int index; + + if(ob==G.obedit) arm->flag |= ARM_EDITMODE; + + /* if solid we draw it first */ + if(dt>OB_WIRE && (arm->flag & ARM_EDITMODE)) { + for (eBone=G.edbo.first; eBone; eBone=eBone->next){ + glPushMatrix(); + set_matrix_editbone(eBone); + draw_bone (OB_SOLID, arm->flag, eBone->flag, 0, -1, eBone->name, eBone->length); + glPopMatrix(); + } + } + + /* if wire over solid, set offset */ + if (dt>OB_WIRE) bglPolygonOffset(1.0); + + if (arm->flag & ARM_DRAWXRAY) { + if(G.zbuf) glDisable(GL_DEPTH_TEST); + } + + for (eBone=G.edbo.first, index=0; eBone; eBone=eBone->next, index++){ + + glPushMatrix(); + set_matrix_editbone(eBone); + draw_bone (OB_WIRE, arm->flag, eBone->flag, 0, index, eBone->name, eBone->length); + glPopMatrix(); + + /* offset to parent */ + if (eBone->parent) { + BIF_ThemeColor(TH_WIRE); + glLoadName (-1); + setlinestyle(3); + + glBegin(GL_LINES); + glVertex3fv(eBone->parent->tail); + glVertex3fv(eBone->head); + glEnd(); + + setlinestyle(0); + } + } + + /* restore */ + if (dt>OB_WIRE) bglPolygonOffset(0.0); + if (arm->flag & ARM_DRAWXRAY) { + if(G.zbuf) glEnable(GL_DEPTH_TEST); + } + + arm->flag &= ~ARM_EDITMODE; + } + else{ + /* Draw Pose */ + if(ob->pose) { + if (G.obpose == ob) arm->flag |= ARM_POSEMODE; + draw_pose_channels(ob, dt); + arm->flag &= ~ARM_POSEMODE; + } + } + +} + +/* *************** END Armature drawing ******************* */ + -- cgit v1.2.3