2.5
Drawing code for space_view3d module. It's still not cleaned, have to check on context usage still. Also missing is editmodes, armatures, and probably more. Known issue: splitting to 2nd window gives bad opengl lighting. Picture for fun: http://www.blender.org/bf/rt2.jpg Current stat: brought back almost 10k lines! :)
This commit is contained in:
110
source/blender/editors/include/BIF_retopo.h
Normal file
110
source/blender/editors/include/BIF_retopo.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2006 by Nicholas Bishop
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef BIF_RETOPO_H
|
||||
#define BIF_RETOPO_H
|
||||
|
||||
#include "DNA_vec_types.h"
|
||||
|
||||
/* For bglMats */
|
||||
#include "BIF_glutil.h"
|
||||
|
||||
struct EditVert;
|
||||
struct Mesh;
|
||||
struct View3D;
|
||||
|
||||
typedef struct RetopoViewData {
|
||||
bglMats mats;
|
||||
|
||||
char queue_matrix_update;
|
||||
} RetopoViewData;
|
||||
|
||||
typedef struct RetopoPaintPoint {
|
||||
struct RetopoPaintPoint *next, *prev;
|
||||
vec2s loc;
|
||||
short index;
|
||||
float co[3];
|
||||
struct EditVert *eve;
|
||||
} RetopoPaintPoint;
|
||||
|
||||
typedef struct RetopoPaintLine {
|
||||
struct RetopoPaintLine *next, *prev;
|
||||
ListBase points;
|
||||
ListBase hitlist; /* RetopoPaintHit */
|
||||
RetopoPaintPoint *cyclic;
|
||||
} RetopoPaintLine;
|
||||
|
||||
typedef struct RetopoPaintSel {
|
||||
struct RetopoPaintSel *next, *prev;
|
||||
RetopoPaintLine *line;
|
||||
char first;
|
||||
} RetopoPaintSel;
|
||||
|
||||
typedef struct RetopoPaintData {
|
||||
char in_drag;
|
||||
short sloc[2];
|
||||
|
||||
ListBase lines;
|
||||
ListBase intersections; /* RetopoPaintPoint */
|
||||
|
||||
short seldist;
|
||||
RetopoPaintSel nearest;
|
||||
|
||||
struct View3D *paint_v3d;
|
||||
} RetopoPaintData;
|
||||
|
||||
RetopoPaintData *get_retopo_paint_data(void);
|
||||
|
||||
char retopo_mesh_check(void);
|
||||
char retopo_curve_check(void);
|
||||
|
||||
void retopo_end_okee(void);
|
||||
|
||||
void retopo_free_paint_data(RetopoPaintData *rpd);
|
||||
void retopo_free_paint(void);
|
||||
|
||||
char retopo_mesh_paint_check(void);
|
||||
void retopo_paint_view_update(struct View3D *v3d);
|
||||
void retopo_force_update(void);
|
||||
void retopo_paint_toggle(void*,void*);
|
||||
char retopo_paint(const unsigned short event);
|
||||
void retopo_draw_paint_lines(void);
|
||||
RetopoPaintData *retopo_paint_data_copy(RetopoPaintData *rpd);
|
||||
|
||||
void retopo_toggle(void*,void*);
|
||||
void retopo_do_vert(struct View3D *v3d, float *v);
|
||||
void retopo_do_all(void);
|
||||
void retopo_do_all_cb(void *, void *);
|
||||
void retopo_queue_updates(struct View3D *v3d);
|
||||
|
||||
void retopo_matrix_update(struct View3D *v3d);
|
||||
|
||||
void retopo_free_view_data(struct View3D *v3d);
|
||||
|
||||
#endif
|
||||
@@ -31,8 +31,9 @@
|
||||
/* **************** GENERAL EDITOR-WIDE TYPES AND DEFINES ************************** */
|
||||
|
||||
/* old blender defines... should be depricated? */
|
||||
#define SELECT 1
|
||||
#define ACTIVE 2
|
||||
#define DESELECT 0
|
||||
#define SELECT 1
|
||||
#define ACTIVE 2
|
||||
|
||||
|
||||
#endif /* ED_TYPES_H */
|
||||
|
||||
@@ -48,6 +48,7 @@ CPPFLAGS += -I../../blenlib
|
||||
CPPFLAGS += -I../../makesdna
|
||||
CPPFLAGS += -I../../imbuf
|
||||
CPPFLAGS += -I../../python
|
||||
CPPFLAGS += -I../../gpu
|
||||
CPPFLAGS += -I../../render/extern/include
|
||||
CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
|
||||
|
||||
|
||||
@@ -6,5 +6,6 @@ sources = env.Glob('*.c')
|
||||
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
|
||||
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
|
||||
incs += ' ../../render/extern/include #/intern/guardedalloc #intern/bmfont'
|
||||
incs += ' ../../gpu'
|
||||
|
||||
env.BlenderLib ( 'bf_editors_space_view3d', sources, Split(incs), [], libtype=['core','intern'], priority=[35, 40] )
|
||||
|
||||
579
source/blender/editors/space_view3d/drawmesh.c
Normal file
579
source/blender/editors/space_view3d/drawmesh.c
Normal file
@@ -0,0 +1,579 @@
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Blender Foundation, full update, glsl support
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_edgehash.h"
|
||||
#include "BLI_editVert.h"
|
||||
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "DNA_image_types.h"
|
||||
#include "DNA_lamp_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_property_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "BKE_bmfont.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_displist.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_effect.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_property.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "BIF_gl.h"
|
||||
#include "BIF_glutil.h"
|
||||
|
||||
#include "UI_resources.h"
|
||||
#include "UI_interface_icons.h"
|
||||
|
||||
#include "GPU_extensions.h"
|
||||
#include "GPU_draw.h"
|
||||
|
||||
#include "view3d_intern.h" // own include
|
||||
|
||||
/***/
|
||||
|
||||
/* Flags for marked edges */
|
||||
enum {
|
||||
eEdge_Visible = (1<<0),
|
||||
eEdge_Select = (1<<1),
|
||||
};
|
||||
|
||||
/* Creates a hash of edges to flags indicating
|
||||
* adjacent tface select/active/etc flags.
|
||||
*/
|
||||
static void get_marked_edge_info__orFlags(EdgeHash *eh, int v0, int v1, int flags)
|
||||
{
|
||||
int *flags_p;
|
||||
|
||||
if (!BLI_edgehash_haskey(eh, v0, v1)) {
|
||||
BLI_edgehash_insert(eh, v0, v1, 0);
|
||||
}
|
||||
|
||||
flags_p = (int*) BLI_edgehash_lookup_p(eh, v0, v1);
|
||||
*flags_p |= flags;
|
||||
}
|
||||
|
||||
static EdgeHash *get_tface_mesh_marked_edge_info(Mesh *me)
|
||||
{
|
||||
EdgeHash *eh = BLI_edgehash_new();
|
||||
int i;
|
||||
MFace *mf;
|
||||
MTFace *tf = NULL;
|
||||
|
||||
for (i=0; i<me->totface; i++) {
|
||||
mf = &me->mface[i];
|
||||
if (me->mtface)
|
||||
tf = &me->mtface[i];
|
||||
|
||||
if (mf->v3) {
|
||||
if (!(mf->flag&ME_HIDE)) {
|
||||
unsigned int flags = eEdge_Visible;
|
||||
if (mf->flag&ME_FACE_SEL) flags |= eEdge_Select;
|
||||
|
||||
get_marked_edge_info__orFlags(eh, mf->v1, mf->v2, flags);
|
||||
get_marked_edge_info__orFlags(eh, mf->v2, mf->v3, flags);
|
||||
if (mf->v4) {
|
||||
get_marked_edge_info__orFlags(eh, mf->v3, mf->v4, flags);
|
||||
get_marked_edge_info__orFlags(eh, mf->v4, mf->v1, flags);
|
||||
} else {
|
||||
get_marked_edge_info__orFlags(eh, mf->v3, mf->v1, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return eh;
|
||||
}
|
||||
|
||||
|
||||
static int draw_tfaces3D__setHiddenOpts(void *userData, int index)
|
||||
{
|
||||
struct { Mesh *me; EdgeHash *eh; } *data = userData;
|
||||
MEdge *med = &data->me->medge[index];
|
||||
uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
|
||||
|
||||
if((G.f & G_DRAWSEAMS) && (med->flag&ME_SEAM)) {
|
||||
return 0;
|
||||
} else if(G.f & G_DRAWEDGES){
|
||||
if (G.f&G_HIDDENEDGES) {
|
||||
return 1;
|
||||
} else {
|
||||
return (flags & eEdge_Visible);
|
||||
}
|
||||
} else {
|
||||
return (flags & eEdge_Select);
|
||||
}
|
||||
}
|
||||
static int draw_tfaces3D__setSeamOpts(void *userData, int index)
|
||||
{
|
||||
struct { Mesh *me; EdgeHash *eh; } *data = userData;
|
||||
MEdge *med = &data->me->medge[index];
|
||||
uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
|
||||
|
||||
if (med->flag&ME_SEAM) {
|
||||
if (G.f&G_HIDDENEDGES) {
|
||||
return 1;
|
||||
} else {
|
||||
return (flags & eEdge_Visible);
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static int draw_tfaces3D__setSelectOpts(void *userData, int index)
|
||||
{
|
||||
struct { Mesh *me; EdgeHash *eh; } *data = userData;
|
||||
MEdge *med = &data->me->medge[index];
|
||||
uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
|
||||
|
||||
return flags & eEdge_Select;
|
||||
}
|
||||
static int draw_tfaces3D__setActiveOpts(void *userData, int index)
|
||||
{
|
||||
struct { Mesh *me; EdgeHash *eh; } *data = userData;
|
||||
MEdge *med = &data->me->medge[index];
|
||||
uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
|
||||
|
||||
if (flags & eEdge_Select) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static int draw_tfaces3D__drawFaceOpts(void *userData, int index)
|
||||
{
|
||||
Mesh *me = (Mesh*)userData;
|
||||
|
||||
MFace *mface = &me->mface[index];
|
||||
if (!(mface->flag&ME_HIDE) && (mface->flag&ME_FACE_SEL))
|
||||
return 2; /* Don't set color */
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
static void draw_tfaces3D(Object *ob, Mesh *me, DerivedMesh *dm)
|
||||
{
|
||||
struct { Mesh *me; EdgeHash *eh; } data;
|
||||
|
||||
data.me = me;
|
||||
data.eh = get_tface_mesh_marked_edge_info(me);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
bglPolygonOffset(1.0);
|
||||
|
||||
/* Draw (Hidden) Edges */
|
||||
UI_ThemeColor(TH_EDGE_FACESEL);
|
||||
dm->drawMappedEdges(dm, draw_tfaces3D__setHiddenOpts, &data);
|
||||
|
||||
/* Draw Seams */
|
||||
if(G.f & G_DRAWSEAMS) {
|
||||
UI_ThemeColor(TH_EDGE_SEAM);
|
||||
glLineWidth(2);
|
||||
|
||||
dm->drawMappedEdges(dm, draw_tfaces3D__setSeamOpts, &data);
|
||||
|
||||
glLineWidth(1);
|
||||
}
|
||||
|
||||
/* Draw Selected Faces */
|
||||
if(G.f & G_DRAWFACES) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
UI_ThemeColor4(TH_FACE_SELECT);
|
||||
|
||||
dm->drawMappedFacesTex(dm, draw_tfaces3D__drawFaceOpts, (void*)me);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
bglPolygonOffset(1.0);
|
||||
|
||||
/* Draw Stippled Outline for selected faces */
|
||||
glColor3ub(255, 255, 255);
|
||||
setlinestyle(1);
|
||||
dm->drawMappedEdges(dm, draw_tfaces3D__setSelectOpts, &data);
|
||||
setlinestyle(0);
|
||||
|
||||
dm->drawMappedEdges(dm, draw_tfaces3D__setActiveOpts, &data);
|
||||
|
||||
bglPolygonOffset(0.0); // resets correctly now, even after calling accumulated offsets
|
||||
|
||||
BLI_edgehash_free(data.eh, NULL);
|
||||
}
|
||||
|
||||
static Material *give_current_material_or_def(Object *ob, int matnr)
|
||||
{
|
||||
extern Material defmaterial; // render module abuse...
|
||||
Material *ma= give_current_material(ob, matnr);
|
||||
|
||||
return ma?ma:&defmaterial;
|
||||
}
|
||||
|
||||
static int set_draw_settings_cached(int clearcache, int textured, MTFace *texface, int lit, Object *litob, int litmatnr, int doublesided)
|
||||
{
|
||||
static int c_textured;
|
||||
static int c_lit;
|
||||
static int c_doublesided;
|
||||
static MTFace *c_texface;
|
||||
static Object *c_litob;
|
||||
static int c_litmatnr;
|
||||
static int c_badtex;
|
||||
|
||||
if (clearcache) {
|
||||
c_textured= c_lit= c_doublesided= -1;
|
||||
c_texface= (MTFace*) -1;
|
||||
c_litob= (Object*) -1;
|
||||
c_litmatnr= -1;
|
||||
c_badtex= 0;
|
||||
}
|
||||
|
||||
if (texface) {
|
||||
lit = lit && (lit==-1 || texface->mode&TF_LIGHT);
|
||||
textured = textured && (texface->mode&TF_TEX);
|
||||
doublesided = texface->mode&TF_TWOSIDE;
|
||||
} else {
|
||||
textured = 0;
|
||||
}
|
||||
|
||||
if (doublesided!=c_doublesided) {
|
||||
if (doublesided) glDisable(GL_CULL_FACE);
|
||||
else glEnable(GL_CULL_FACE);
|
||||
|
||||
c_doublesided= doublesided;
|
||||
}
|
||||
|
||||
if (textured!=c_textured || texface!=c_texface) {
|
||||
if (textured ) {
|
||||
c_badtex= !GPU_set_tpage(texface);
|
||||
} else {
|
||||
GPU_set_tpage(0);
|
||||
c_badtex= 0;
|
||||
}
|
||||
c_textured= textured;
|
||||
c_texface= texface;
|
||||
}
|
||||
|
||||
if (c_badtex) lit= 0;
|
||||
if (lit!=c_lit || litob!=c_litob || litmatnr!=c_litmatnr) {
|
||||
if (lit) {
|
||||
Material *ma= give_current_material_or_def(litob, litmatnr+1);
|
||||
float spec[4];
|
||||
|
||||
spec[0]= ma->spec*ma->specr;
|
||||
spec[1]= ma->spec*ma->specg;
|
||||
spec[2]= ma->spec*ma->specb;
|
||||
spec[3]= 1.0;
|
||||
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
}
|
||||
else {
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
}
|
||||
c_lit= lit;
|
||||
c_litob= litob;
|
||||
c_litmatnr= litmatnr;
|
||||
}
|
||||
|
||||
return c_badtex;
|
||||
}
|
||||
|
||||
/* Icky globals, fix with userdata parameter */
|
||||
|
||||
struct TextureDrawState {
|
||||
Object *ob;
|
||||
int islit, istex;
|
||||
unsigned char obcol[4];
|
||||
} Gtexdraw = {NULL, 0, 0, {0, 0, 0, 0}};
|
||||
|
||||
static void draw_textured_begin(Scene *scene, View3D *v3d, Object *ob)
|
||||
{
|
||||
unsigned char obcol[4];
|
||||
int istex, solidtex= 0;
|
||||
|
||||
if(v3d->drawtype==OB_SOLID || (ob==G.obedit && v3d->drawtype!=OB_TEXTURE)) {
|
||||
/* draw with default lights in solid draw mode and edit mode */
|
||||
solidtex= 1;
|
||||
Gtexdraw.islit= -1;
|
||||
}
|
||||
else
|
||||
/* draw with lights in the scene otherwise */
|
||||
Gtexdraw.islit= GPU_scene_object_lights(scene, ob, v3d->lay, v3d->viewmat);
|
||||
|
||||
obcol[0]= CLAMPIS(ob->col[0]*255, 0, 255);
|
||||
obcol[1]= CLAMPIS(ob->col[1]*255, 0, 255);
|
||||
obcol[2]= CLAMPIS(ob->col[2]*255, 0, 255);
|
||||
obcol[3]= CLAMPIS(ob->col[3]*255, 0, 255);
|
||||
|
||||
glCullFace(GL_BACK); glEnable(GL_CULL_FACE);
|
||||
if(solidtex || v3d->drawtype==OB_TEXTURE) istex= 1;
|
||||
else istex= 0;
|
||||
|
||||
Gtexdraw.ob = ob;
|
||||
Gtexdraw.istex = istex;
|
||||
memcpy(Gtexdraw.obcol, obcol, sizeof(obcol));
|
||||
set_draw_settings_cached(1, 0, 0, Gtexdraw.islit, 0, 0, 0);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
}
|
||||
|
||||
static void draw_textured_end()
|
||||
{
|
||||
/* switch off textures */
|
||||
GPU_set_tpage(0);
|
||||
|
||||
glShadeModel(GL_FLAT);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
/* XXX, bad patch - GPU_default_lights() calls
|
||||
* glLightfv(GL_LIGHT_POSITION, ...) which
|
||||
* is transformed by the current matrix... we
|
||||
* need to make sure that matrix is identity.
|
||||
*
|
||||
* It would be better if drawmesh.c kept track
|
||||
* of and restored the light settings it changed.
|
||||
* - zr
|
||||
*/
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
GPU_default_lights();
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
static int draw_tface__set_draw(MTFace *tface, MCol *mcol, int matnr)
|
||||
{
|
||||
if (tface && (tface->mode&TF_INVISIBLE)) return 0;
|
||||
|
||||
if (tface && set_draw_settings_cached(0, Gtexdraw.istex, tface, Gtexdraw.islit, Gtexdraw.ob, matnr, TF_TWOSIDE)) {
|
||||
glColor3ub(0xFF, 0x00, 0xFF);
|
||||
return 2; /* Don't set color */
|
||||
} else if (tface && tface->mode&TF_OBCOL) {
|
||||
glColor3ubv(Gtexdraw.obcol);
|
||||
return 2; /* Don't set color */
|
||||
} else if (!mcol) {
|
||||
if (tface) glColor3f(1.0, 1.0, 1.0);
|
||||
else {
|
||||
Material *ma= give_current_material(Gtexdraw.ob, matnr+1);
|
||||
if(ma) glColor3f(ma->r, ma->g, ma->b);
|
||||
else glColor3f(1.0, 1.0, 1.0);
|
||||
}
|
||||
return 2; /* Don't set color */
|
||||
} else {
|
||||
return 1; /* Set color from mcol */
|
||||
}
|
||||
}
|
||||
|
||||
static int draw_tface_mapped__set_draw(void *userData, int index)
|
||||
{
|
||||
Mesh *me = (Mesh*)userData;
|
||||
MTFace *tface = (me->mtface)? &me->mtface[index]: NULL;
|
||||
MFace *mface = (me->mface)? &me->mface[index]: NULL;
|
||||
MCol *mcol = (me->mcol)? &me->mcol[index]: NULL;
|
||||
int matnr = me->mface[index].mat_nr;
|
||||
if (mface && mface->flag&ME_HIDE) return 0;
|
||||
return draw_tface__set_draw(tface, mcol, matnr);
|
||||
}
|
||||
|
||||
static int draw_em_tf_mapped__set_draw(void *userData, int index)
|
||||
{
|
||||
EditMesh *em = userData;
|
||||
EditFace *efa= NULL; // XXX = EM_get_face_for_index(index);
|
||||
MTFace *tface;
|
||||
MCol *mcol;
|
||||
int matnr;
|
||||
|
||||
if (efa==NULL || efa->h)
|
||||
return 0;
|
||||
|
||||
tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
|
||||
mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
|
||||
matnr = efa->mat_nr;
|
||||
|
||||
return draw_tface__set_draw(tface, mcol, matnr);
|
||||
}
|
||||
|
||||
static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
|
||||
{
|
||||
Mesh *me = (Mesh*)userData;
|
||||
MTFace *tface = (me->mtface)? &me->mtface[index]: NULL;
|
||||
MFace *mface = (me->mface)? &me->mface[index]: NULL;
|
||||
|
||||
if ((mface->flag&ME_HIDE) || (tface && (tface->mode&TF_INVISIBLE)))
|
||||
return 0;
|
||||
|
||||
*drawSmooth_r = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void draw_mesh_text(Object *ob, int glsl)
|
||||
{
|
||||
Mesh *me = ob->data;
|
||||
DerivedMesh *ddm;
|
||||
MFace *mf, *mface= me->mface;
|
||||
MTFace *tface= me->mtface;
|
||||
MCol *mcol= me->mcol; /* why does mcol exist? */
|
||||
bProperty *prop = get_ob_property(ob, "Text");
|
||||
GPUVertexAttribs gattribs;
|
||||
int a, totface= me->totface;
|
||||
|
||||
/* don't draw without tfaces */
|
||||
if(!tface)
|
||||
return;
|
||||
|
||||
/* don't draw when editing */
|
||||
if(ob==G.obedit)
|
||||
return;
|
||||
else if(ob==OBACT)
|
||||
if(FACESEL_PAINT_TEST)
|
||||
return;
|
||||
|
||||
ddm = mesh_get_derived_deform(ob, CD_MASK_BAREMESH);
|
||||
|
||||
for(a=0, mf=mface; a<totface; a++, tface++, mf++) {
|
||||
int mode= tface->mode;
|
||||
int matnr= mf->mat_nr;
|
||||
int mf_smooth= mf->flag & ME_SMOOTH;
|
||||
|
||||
if (!(mf->flag&ME_HIDE) && !(mode&TF_INVISIBLE) && (mode&TF_BMFONT)) {
|
||||
float v1[3], v2[3], v3[3], v4[3];
|
||||
char string[MAX_PROPSTRING];
|
||||
int characters, i, glattrib= -1, badtex= 0;
|
||||
|
||||
if(glsl) {
|
||||
GPU_enable_material(matnr+1, &gattribs);
|
||||
|
||||
for(i=0; i<gattribs.totlayer; i++) {
|
||||
if(gattribs.layer[i].type == CD_MTFACE) {
|
||||
glattrib = gattribs.layer[i].glindex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
badtex = set_draw_settings_cached(0, Gtexdraw.istex, tface, Gtexdraw.islit, Gtexdraw.ob, matnr, TF_TWOSIDE);
|
||||
if (badtex) {
|
||||
if (mcol) mcol+=4;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ddm->getVertCo(ddm, mf->v1, v1);
|
||||
ddm->getVertCo(ddm, mf->v2, v2);
|
||||
ddm->getVertCo(ddm, mf->v3, v3);
|
||||
if (mf->v4) ddm->getVertCo(ddm, mf->v4, v4);
|
||||
|
||||
// The BM_FONT handling is in the gpu module, shared with the
|
||||
// game engine, was duplicated previously
|
||||
|
||||
set_property_valstr(prop, string);
|
||||
characters = strlen(string);
|
||||
|
||||
if(!BKE_image_get_ibuf(tface->tpage, NULL))
|
||||
characters = 0;
|
||||
|
||||
if (!mf_smooth) {
|
||||
float nor[3];
|
||||
|
||||
CalcNormFloat(v1, v2, v3, nor);
|
||||
|
||||
glNormal3fv(nor);
|
||||
}
|
||||
|
||||
GPU_render_text(tface, tface->mode, string, characters,
|
||||
(unsigned int*)mcol, v1, v2, v3, (mf->v4? v4: NULL), glattrib);
|
||||
}
|
||||
if (mcol) {
|
||||
mcol+=4;
|
||||
}
|
||||
}
|
||||
|
||||
ddm->release(ddm);
|
||||
}
|
||||
|
||||
void draw_mesh_textured(Scene *scene, View3D *v3d, Object *ob, DerivedMesh *dm, int faceselect)
|
||||
{
|
||||
Mesh *me= ob->data;
|
||||
|
||||
/* correct for negative scale */
|
||||
if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
|
||||
else glFrontFace(GL_CCW);
|
||||
|
||||
/* draw the textured mesh */
|
||||
draw_textured_begin(scene, v3d, ob);
|
||||
|
||||
if(ob==G.obedit) {
|
||||
dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, G.editMesh);
|
||||
} else if(faceselect) {
|
||||
if(G.f & G_WEIGHTPAINT)
|
||||
dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me, 1);
|
||||
else
|
||||
dm->drawMappedFacesTex(dm, draw_tface_mapped__set_draw, me);
|
||||
}
|
||||
else
|
||||
dm->drawFacesTex(dm, draw_tface__set_draw);
|
||||
|
||||
/* draw game engine text hack */
|
||||
if(get_ob_property(ob, "Text"))
|
||||
draw_mesh_text(ob, 0);
|
||||
|
||||
draw_textured_end();
|
||||
|
||||
/* draw edges and selected faces over textured mesh */
|
||||
if(!G.obedit && faceselect)
|
||||
draw_tfaces3D(ob, me, dm);
|
||||
|
||||
/* reset from negative scale correction */
|
||||
glFrontFace(GL_CCW);
|
||||
|
||||
/* in editmode, the blend mode needs to be set incase it was ADD */
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
5475
source/blender/editors/space_view3d/drawobject.c
Normal file
5475
source/blender/editors/space_view3d/drawobject.c
Normal file
@@ -0,0 +1,5475 @@
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Blender Foundation, full recode and added functions
|
||||
*
|
||||
* ***** END GPL 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_armature_types.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_modifier_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_particle_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
// FSPARTICLE
|
||||
#include "DNA_object_fluidsim.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_editVert.h"
|
||||
#include "BLI_edgehash.h"
|
||||
#include "BLI_rand.h"
|
||||
|
||||
#include "BKE_anim.h" //for the where_on_path function
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_constraint.h" // for the get_constraint_target function
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_displist.h"
|
||||
#include "BKE_effect.h"
|
||||
#include "BKE_font.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_ipo.h"
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_lattice.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_mball.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_particle.h"
|
||||
#include "BKE_property.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "BIF_gl.h"
|
||||
#include "BIF_glutil.h"
|
||||
|
||||
#include "GPU_draw.h"
|
||||
#include "GPU_material.h"
|
||||
#include "GPU_extensions.h"
|
||||
|
||||
#include "ED_types.h"
|
||||
#include "ED_util.h"
|
||||
|
||||
#include "UI_resources.h"
|
||||
#include "UI_interface_icons.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
#include "view3d_intern.h" // own include
|
||||
|
||||
|
||||
/* 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);
|
||||
|
||||
static void drawcube_size(float size);
|
||||
static void drawcircle_size(float size);
|
||||
static void draw_empty_sphere(float size);
|
||||
static void draw_empty_cone(float size);
|
||||
|
||||
EditVert *EM_get_vert_for_index(int x) {return 0;} // XXX
|
||||
EditEdge *EM_get_edge_for_index(int x) {return 0;} // XXX
|
||||
EditFace *EM_get_face_for_index(int x) {return 0;} // XXX
|
||||
void EM_init_index_arrays(int x, int y, int z) {} // XXX
|
||||
void EM_free_index_arrays(void) {} // XXX
|
||||
#define EM_FGON 0
|
||||
EditFace *EM_get_actFace(int x) {return NULL;} // XXX
|
||||
int draw_armature(Base *base, int x, int y) {return 0;} // XXX
|
||||
int em_solidoffs; // XXX
|
||||
int em_wireoffs;
|
||||
int em_vertoffs;
|
||||
|
||||
/* check for glsl drawing */
|
||||
|
||||
int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
|
||||
{
|
||||
if(!GPU_extensions_minimum_support())
|
||||
return 0;
|
||||
if(G.f & G_PICKSEL)
|
||||
return 0;
|
||||
if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
|
||||
return 0;
|
||||
if(ob==OBACT && (G.f & G_WEIGHTPAINT))
|
||||
return 0;
|
||||
|
||||
return ((G.fileflags & G_FILE_GAME_MAT) &&
|
||||
(G.fileflags & G_FILE_GAME_MAT_GLSL) && (dt >= OB_SHADED));
|
||||
}
|
||||
|
||||
static int check_material_alpha(Base *base, Object *ob, int glsl)
|
||||
{
|
||||
if(base->flag & OB_FROMDUPLI)
|
||||
return 0;
|
||||
|
||||
if(G.f & G_PICKSEL)
|
||||
return 0;
|
||||
|
||||
if(G.obedit && G.obedit->data==ob->data)
|
||||
return 0;
|
||||
|
||||
return (glsl || (ob->dtx & OB_DRAWTRANSP));
|
||||
}
|
||||
|
||||
/***/
|
||||
static unsigned int colortab[24]=
|
||||
{0x0, 0xFF88FF, 0xFFBBFF,
|
||||
0x403000, 0xFFFF88, 0xFFFFBB,
|
||||
0x104040, 0x66CCCC, 0x77CCCC,
|
||||
0x104010, 0x55BB55, 0x66FF66,
|
||||
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},
|
||||
};
|
||||
|
||||
/* ----------------- OpenGL Circle Drawing - Tables for Optimised Drawing Speed ------------------ */
|
||||
/* 32 values of sin function (still same result!) */
|
||||
static float sinval[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 cosval[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
|
||||
};
|
||||
|
||||
/* flag is same as for draw_object */
|
||||
void drawaxes(float size, int flag, char drawtype)
|
||||
{
|
||||
int axis;
|
||||
float v1[3]= {0.0, 0.0, 0.0};
|
||||
float v2[3]= {0.0, 0.0, 0.0};
|
||||
float v3[3]= {0.0, 0.0, 0.0};
|
||||
|
||||
if(G.f & G_RENDER_SHADOW)
|
||||
return;
|
||||
|
||||
switch(drawtype) {
|
||||
|
||||
case OB_PLAINAXES:
|
||||
for (axis=0; axis<3; axis++) {
|
||||
float v1[3]= {0.0, 0.0, 0.0};
|
||||
float v2[3]= {0.0, 0.0, 0.0};
|
||||
|
||||
glBegin(GL_LINES);
|
||||
|
||||
v1[axis]= size;
|
||||
v2[axis]= -size;
|
||||
glVertex3fv(v1);
|
||||
glVertex3fv(v2);
|
||||
|
||||
glEnd();
|
||||
}
|
||||
break;
|
||||
case OB_SINGLE_ARROW:
|
||||
|
||||
glBegin(GL_LINES);
|
||||
/* in positive z direction only */
|
||||
v1[2]= size;
|
||||
glVertex3fv(v1);
|
||||
glVertex3fv(v2);
|
||||
glEnd();
|
||||
|
||||
/* square pyramid */
|
||||
glBegin(GL_TRIANGLES);
|
||||
|
||||
v2[0]= size*0.035; v2[1] = size*0.035;
|
||||
v3[0]= size*-0.035; v3[1] = size*0.035;
|
||||
v2[2]= v3[2]= size*0.75;
|
||||
|
||||
for (axis=0; axis<4; axis++) {
|
||||
if (axis % 2 == 1) {
|
||||
v2[0] *= -1;
|
||||
v3[1] *= -1;
|
||||
} else {
|
||||
v2[1] *= -1;
|
||||
v3[0] *= -1;
|
||||
}
|
||||
|
||||
glVertex3fv(v1);
|
||||
glVertex3fv(v2);
|
||||
glVertex3fv(v3);
|
||||
|
||||
}
|
||||
glEnd();
|
||||
|
||||
break;
|
||||
case OB_CUBE:
|
||||
drawcube_size(size);
|
||||
break;
|
||||
|
||||
case OB_CIRCLE:
|
||||
drawcircle_size(size);
|
||||
break;
|
||||
|
||||
case OB_EMPTY_SPHERE:
|
||||
draw_empty_sphere(size);
|
||||
break;
|
||||
|
||||
case OB_EMPTY_CONE:
|
||||
draw_empty_cone(size);
|
||||
break;
|
||||
|
||||
case OB_ARROWS:
|
||||
default:
|
||||
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((flag & DRAW_PICKING) == 0) {
|
||||
if (axis==0)
|
||||
BMF_DrawString(G.font, "x");
|
||||
else if (axis==1)
|
||||
BMF_DrawString(G.font, "y");
|
||||
else
|
||||
BMF_DrawString(G.font, "z");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void drawcircball(int mode, float *cent, float rad, float tmat[][4])
|
||||
{
|
||||
float vec[3], vx[3], vy[3];
|
||||
int a, tot=32;
|
||||
|
||||
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] + *(sinval+a) * vx[0] + *(cosval+a) * vy[0];
|
||||
vec[1]= cent[1] + *(sinval+a) * vx[1] + *(cosval+a) * vy[1];
|
||||
vec[2]= cent[2] + *(sinval+a) * vx[2] + *(cosval+a) * vy[2];
|
||||
glVertex3fv(vec);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
/* circle for object centers, special_color is for library or ob users */
|
||||
static void drawcentercircle(View3D *v3d, float *vec, int selstate, int special_color)
|
||||
{
|
||||
float size;
|
||||
|
||||
size= v3d->persmat[0][3]*vec[0]+ v3d->persmat[1][3]*vec[1]+ v3d->persmat[2][3]*vec[2]+ v3d->persmat[3][3];
|
||||
size*= v3d->pixsize*((float)U.obcenter_dia*0.5f);
|
||||
|
||||
/* using gldepthfunc guarantees that it does write z values, but not checks for it, so centers remain visible independt order of drawing */
|
||||
if(v3d->zbuf) glDepthFunc(GL_ALWAYS);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
if(special_color) {
|
||||
if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
|
||||
|
||||
else glColor4ub(0x55, 0xCC, 0xCC, 155);
|
||||
}
|
||||
else {
|
||||
if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
|
||||
else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
|
||||
else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
|
||||
}
|
||||
drawcircball(GL_POLYGON, vec, size, v3d->viewinv);
|
||||
|
||||
UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
|
||||
drawcircball(GL_LINE_LOOP, vec, size, v3d->viewinv);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
if(v3d->zbuf) glDepthFunc(GL_LEQUAL);
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/* draws a cube on given the scaling of the cube, assuming that
|
||||
* all required matrices have been set (used for drawing empties)
|
||||
*/
|
||||
static void drawcube_size(float size)
|
||||
{
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
|
||||
glVertex3f(-size,-size,-size); glVertex3f(size,-size,-size);glVertex3f(size,-size,size); glVertex3f(size,size,size);
|
||||
glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
|
||||
glEnd();
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
|
||||
glEnd();
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3f(-size,size,size); glVertex3f(size,size,size);
|
||||
glEnd();
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
/* this is an unused (old) cube-drawing function based on a given size */
|
||||
#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 drawshadbuflimits(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];
|
||||
Normalize(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,angle;
|
||||
|
||||
Normalize(lvec);
|
||||
Normalize(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 */
|
||||
|
||||
Normalize(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 ;
|
||||
Normalize(&q[1]);
|
||||
|
||||
angle = saacos(plane[2])/2.0;
|
||||
co = cos(angle);
|
||||
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(const bContext *C, Scene *scene, View3D *v3d, Object *ob)
|
||||
{
|
||||
Lamp *la;
|
||||
float vec[3], lvec[3], vvec[3], circrad, x,y,z;
|
||||
float pixsize, lampsize;
|
||||
float imat[4][4], curcol[4];
|
||||
char col[4];
|
||||
|
||||
if(G.f & G_RENDER_SHADOW)
|
||||
return;
|
||||
|
||||
la= ob->data;
|
||||
|
||||
/* we first draw only the screen aligned & fixed scale stuff */
|
||||
glPushMatrix();
|
||||
wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
|
||||
|
||||
/* lets calculate the scale: */
|
||||
pixsize= v3d->persmat[0][3]*ob->obmat[3][0]+ v3d->persmat[1][3]*ob->obmat[3][1]+ v3d->persmat[2][3]*ob->obmat[3][2]+ v3d->persmat[3][3];
|
||||
pixsize*= v3d->pixsize;
|
||||
lampsize= pixsize*((float)U.obcenter_dia*0.5f);
|
||||
|
||||
/* and view aligned matrix: */
|
||||
Mat4CpyMat4(imat, v3d->viewinv);
|
||||
Normalize(imat[0]);
|
||||
Normalize(imat[1]);
|
||||
|
||||
/* for AA effects */
|
||||
glGetFloatv(GL_CURRENT_COLOR, curcol);
|
||||
curcol[3]= 0.6;
|
||||
glColor4fv(curcol);
|
||||
|
||||
if(ob->id.us>1) {
|
||||
if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
|
||||
else glColor4ub(0x77, 0xCC, 0xCC, 155);
|
||||
}
|
||||
|
||||
/* Inner Circle */
|
||||
VECCOPY(vec, ob->obmat[3]);
|
||||
glEnable(GL_BLEND);
|
||||
drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
|
||||
glDisable(GL_BLEND);
|
||||
drawcircball(GL_POLYGON, vec, lampsize, imat);
|
||||
|
||||
/* restore */
|
||||
if(ob->id.us>1)
|
||||
glColor4fv(curcol);
|
||||
|
||||
/* Outer circle */
|
||||
circrad = 3.0f*lampsize;
|
||||
drawcircball(GL_LINE_LOOP, vec, circrad, imat);
|
||||
|
||||
setlinestyle(3);
|
||||
|
||||
/* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
|
||||
if (la->type!=LA_HEMI) {
|
||||
if ((la->mode & LA_SHAD_RAY) ||
|
||||
((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT)) )
|
||||
{
|
||||
drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
|
||||
}
|
||||
}
|
||||
|
||||
/* draw the pretty sun rays */
|
||||
if(la->type==LA_SUN) {
|
||||
float v1[3], v2[3], mat[3][3];
|
||||
short axis;
|
||||
|
||||
/* setup a 45 degree rotation matrix */
|
||||
VecRotToMat3(imat[2], M_PI/4.0f, mat);
|
||||
|
||||
/* vectors */
|
||||
VECCOPY(v1, imat[0]);
|
||||
VecMulf(v1, circrad*1.2f);
|
||||
VECCOPY(v2, imat[0]);
|
||||
VecMulf(v2, circrad*2.5f);
|
||||
|
||||
/* center */
|
||||
glTranslatef(vec[0], vec[1], vec[2]);
|
||||
|
||||
setlinestyle(3);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
for (axis=0; axis<8; axis++) {
|
||||
glVertex3fv(v1);
|
||||
glVertex3fv(v2);
|
||||
Mat3MulVecfl(mat, v1);
|
||||
Mat3MulVecfl(mat, v2);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glTranslatef(-vec[0], -vec[1], -vec[2]);
|
||||
|
||||
}
|
||||
|
||||
if (la->type==LA_LOCAL) {
|
||||
if(la->mode & LA_SPHERE) {
|
||||
drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
|
||||
}
|
||||
/* yafray: for photonlight also draw lightcone as for spot */
|
||||
}
|
||||
|
||||
glPopMatrix(); /* back in object space */
|
||||
vec[0]= vec[1]= vec[2]= 0.0f;
|
||||
|
||||
if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {
|
||||
lvec[0]=lvec[1]= 0.0;
|
||||
lvec[2] = 1.0;
|
||||
x = v3d->persmat[0][2];
|
||||
y = v3d->persmat[1][2];
|
||||
z = v3d->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;
|
||||
|
||||
/* draw the angled sides of the cone */
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3fv(vvec);
|
||||
glVertex3fv(vec);
|
||||
glVertex3fv(lvec);
|
||||
glEnd();
|
||||
|
||||
z = x*sqrt(1.0 - y*y);
|
||||
x *= y;
|
||||
|
||||
/* draw the circle/square at the end of the cone */
|
||||
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));
|
||||
|
||||
/* draw the circle/square representing spotbl */
|
||||
if(la->type==LA_SPOT) {
|
||||
float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
|
||||
/* make sure the line is always visible - prevent it from reaching the outer border (or 0)
|
||||
* values are kinda arbitrary - just what seemed to work well */
|
||||
if (spotblcirc == 0) spotblcirc = 0.15;
|
||||
else if (spotblcirc == fabs(z)) spotblcirc = fabs(z) - 0.07;
|
||||
circ(0.0, 0.0, spotblcirc);
|
||||
}
|
||||
|
||||
}
|
||||
else if ELEM(la->type, LA_HEMI, LA_SUN) {
|
||||
|
||||
/* draw the line from the circle along the dist */
|
||||
glBegin(GL_LINE_STRIP);
|
||||
vec[2] = -circrad;
|
||||
glVertex3fv(vec);
|
||||
vec[2]= -la->dist;
|
||||
glVertex3fv(vec);
|
||||
glEnd();
|
||||
|
||||
if(la->type==LA_HEMI) {
|
||||
/* draw the hemisphere curves */
|
||||
short axis, steps, dir;
|
||||
float outdist, zdist, mul;
|
||||
vec[0]=vec[1]=vec[2]= 0.0;
|
||||
outdist = 0.14; mul = 1.4; dir = 1;
|
||||
|
||||
setlinestyle(4);
|
||||
/* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
|
||||
for (axis=0; axis<4; axis++) {
|
||||
float v[3]= {0.0, 0.0, 0.0};
|
||||
zdist = 0.02;
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
|
||||
for (steps=0; steps<6; steps++) {
|
||||
if (axis == 0 || axis == 1) { /* x axis up, x axis down */
|
||||
/* make the arcs start at the edge of the energy circle */
|
||||
if (steps == 0) v[0] = dir*circrad;
|
||||
else v[0] = v[0] + dir*(steps*outdist);
|
||||
} else if (axis == 2 || axis == 3) { /* y axis up, y axis down */
|
||||
/* make the arcs start at the edge of the energy circle */
|
||||
if (steps == 0) v[1] = dir*circrad;
|
||||
else v[1] = v[1] + dir*(steps*outdist);
|
||||
}
|
||||
|
||||
v[2] = v[2] - steps*zdist;
|
||||
|
||||
glVertex3fv(v);
|
||||
|
||||
zdist = zdist * mul;
|
||||
}
|
||||
|
||||
glEnd();
|
||||
/* flip the direction */
|
||||
dir = -dir;
|
||||
}
|
||||
}
|
||||
} else if(la->type==LA_AREA) {
|
||||
setlinestyle(3);
|
||||
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);
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3f(0.0,0.0,-circrad);
|
||||
glVertex3f(0.0,0.0,-la->dist);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
/* and back to viewspace */
|
||||
wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
|
||||
VECCOPY(vec, ob->obmat[3]);
|
||||
|
||||
setlinestyle(0);
|
||||
|
||||
if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
|
||||
drawshadbuflimits(la, ob->obmat);
|
||||
}
|
||||
|
||||
UI_GetThemeColor4ubv(TH_LAMP, col);
|
||||
glColor4ub(col[0], col[1], col[2], col[3]);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
if (vec[2]>0) vec[2] -= circrad;
|
||||
else vec[2] += circrad;
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3fv(vec);
|
||||
vec[2]= 0;
|
||||
glVertex3fv(vec);
|
||||
glEnd();
|
||||
|
||||
glPointSize(2.0);
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3fv(vec);
|
||||
glEnd();
|
||||
glPointSize(1.0);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
/* restore for drawing extra stuff */
|
||||
glColor3fv(curcol);
|
||||
|
||||
}
|
||||
|
||||
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) */
|
||||
/* qdn: now also enabled for Blender to set focus point for defocus composit node */
|
||||
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();
|
||||
}
|
||||
|
||||
/* flag similar to draw_object() */
|
||||
static void drawcamera(const bContext *C, Scene *scene, View3D *v3d, Object *ob, int flag)
|
||||
{
|
||||
/* 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;
|
||||
int i;
|
||||
|
||||
if(G.f & G_RENDER_SHADOW)
|
||||
return;
|
||||
|
||||
cam= ob->data;
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
if(v3d->persp>=2 && cam->type==CAM_ORTHO && ob==v3d->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(v3d->persp>=2 && ob==v3d->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(v3d->persp>=2 && ob==v3d->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;
|
||||
|
||||
|
||||
/* draw an outline arrow for inactive cameras and filled
|
||||
* for active cameras. We actually draw both outline+filled
|
||||
* for active cameras so the wire can be seen side-on */
|
||||
for (i=0;i<2;i++) {
|
||||
if (i==0) glBegin(GL_LINE_LOOP);
|
||||
else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
|
||||
else break;
|
||||
|
||||
vec[0][0]= -0.7*cam->drawsize;
|
||||
vec[0][1]= 1.1*cam->drawsize;
|
||||
glVertex3fv(vec[0]);
|
||||
|
||||
vec[0][0]= 0.0;
|
||||
vec[0][1]= 1.8*cam->drawsize;
|
||||
glVertex3fv(vec[0]);
|
||||
|
||||
vec[0][0]= 0.7*cam->drawsize;
|
||||
vec[0][1]= 1.1*cam->drawsize;
|
||||
glVertex3fv(vec[0]);
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
if(flag==0) {
|
||||
if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
|
||||
wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
|
||||
Mat4CpyMat4(vec, ob->obmat);
|
||||
Mat4Ortho(vec);
|
||||
wmMultMatrix(CTX_wm_window(C), vec);
|
||||
|
||||
MTC_Mat4SwapMat4(v3d->persmat, tmat);
|
||||
wmGetSingleMatrix(CTX_wm_window(C), v3d->persmat);
|
||||
|
||||
if(cam->flag & CAM_SHOWLIMITS) {
|
||||
draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
|
||||
/* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
|
||||
draw_focus_cross(dof_camera(ob), cam->drawsize);
|
||||
}
|
||||
|
||||
wrld= scene->world;
|
||||
if(cam->flag & CAM_SHOWMIST)
|
||||
if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
|
||||
|
||||
MTC_Mat4SwapMat4(v3d->persmat, tmat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
|
||||
{
|
||||
BPoint *bp = lt->def;
|
||||
float *co = dl?dl->verts:NULL;
|
||||
int u, v, w;
|
||||
|
||||
UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
|
||||
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
|
||||
bglBegin(GL_POINTS);
|
||||
|
||||
for(w=0; w<lt->pntsw; w++) {
|
||||
int wxt = (w==0 || w==lt->pntsw-1);
|
||||
for(v=0; v<lt->pntsv; v++) {
|
||||
int vxt = (v==0 || v==lt->pntsv-1);
|
||||
for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
|
||||
int uxt = (u==0 || u==lt->pntsu-1);
|
||||
if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
|
||||
if(bp->hide==0) {
|
||||
if((bp->f1 & SELECT)==sel) {
|
||||
bglVertex3fv(dl?co:bp->vec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glPointSize(1.0);
|
||||
bglEnd();
|
||||
}
|
||||
|
||||
void lattice_foreachScreenVert(void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
|
||||
{
|
||||
ARegion *ar= NULL; // XXX
|
||||
View3D *v3d= NULL; // XXX
|
||||
BPoint *bp = editLatt->def;
|
||||
DispList *dl = find_displist(&G.obedit->disp, DL_VERTS);
|
||||
float *co = dl?dl->verts:NULL;
|
||||
float pmat[4][4], vmat[4][4];
|
||||
int i, N = editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
|
||||
short s[2];
|
||||
|
||||
view3d_get_object_project_mat(v3d, G.obedit, pmat, vmat);
|
||||
|
||||
for (i=0; i<N; i++, bp++, co+=3) {
|
||||
if (bp->hide==0) {
|
||||
view3d_project_short_clip(ar, v3d, dl?co:bp->vec, s, pmat, vmat);
|
||||
func(userData, bp, s[0], s[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
|
||||
{
|
||||
int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
|
||||
|
||||
if(use_wcol) {
|
||||
#if 0
|
||||
XXX
|
||||
float col[3];
|
||||
MDeformWeight *mdw= get_defweight (lt->dvert+index, use_wcol-1);
|
||||
|
||||
weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
|
||||
glColor3fv(col);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (dl) {
|
||||
glVertex3fv(&dl->verts[index*3]);
|
||||
} else {
|
||||
glVertex3fv(lt->def[index].vec);
|
||||
}
|
||||
}
|
||||
|
||||
/* lattice color is hardcoded, now also shows weightgroup values in edit mode */
|
||||
static void drawlattice(View3D *v3d, Object *ob)
|
||||
{
|
||||
Lattice *lt;
|
||||
DispList *dl;
|
||||
int u, v, w;
|
||||
int use_wcol= 0;
|
||||
|
||||
lt= (ob==G.obedit)?editLatt:ob->data;
|
||||
|
||||
/* now we default make displist, this will modifiers work for non animated case */
|
||||
if(ob->disp.first==NULL)
|
||||
lattice_calc_modifiers(ob);
|
||||
dl= find_displist(&ob->disp, DL_VERTS);
|
||||
|
||||
if(ob==G.obedit) {
|
||||
cpack(0x004000);
|
||||
|
||||
if(ob->defbase.first && lt->dvert) {
|
||||
use_wcol= ob->actdef;
|
||||
glShadeModel(GL_SMOOTH);
|
||||
}
|
||||
}
|
||||
|
||||
glBegin(GL_LINES);
|
||||
for(w=0; w<lt->pntsw; w++) {
|
||||
int wxt = (w==0 || w==lt->pntsw-1);
|
||||
for(v=0; v<lt->pntsv; v++) {
|
||||
int vxt = (v==0 || v==lt->pntsv-1);
|
||||
for(u=0; u<lt->pntsu; u++) {
|
||||
int uxt = (u==0 || u==lt->pntsu-1);
|
||||
|
||||
if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
|
||||
drawlattice__point(lt, dl, u, v, w-1, use_wcol);
|
||||
drawlattice__point(lt, dl, u, v, w, use_wcol);
|
||||
}
|
||||
if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
|
||||
drawlattice__point(lt, dl, u, v-1, w, use_wcol);
|
||||
drawlattice__point(lt, dl, u, v, w, use_wcol);
|
||||
}
|
||||
if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
|
||||
drawlattice__point(lt, dl, u-1, v, w, use_wcol);
|
||||
drawlattice__point(lt, dl, u, v, w, use_wcol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* restoration for weight colors */
|
||||
if(use_wcol)
|
||||
glShadeModel(GL_FLAT);
|
||||
|
||||
if(ob==G.obedit) {
|
||||
if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
|
||||
|
||||
lattice_draw_verts(lt, dl, 0);
|
||||
lattice_draw_verts(lt, dl, 1);
|
||||
|
||||
if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
/* ***************** ******************** */
|
||||
|
||||
static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
|
||||
{
|
||||
struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
|
||||
ARegion *ar= NULL; // XXX
|
||||
View3D *v3d= NULL; // XXX
|
||||
EditVert *eve = EM_get_vert_for_index(index);
|
||||
short s[2];
|
||||
|
||||
if (eve->h==0) {
|
||||
if (data->clipVerts) {
|
||||
view3d_project_short_clip(ar, v3d, co, s, data->pmat, data->vmat);
|
||||
} else {
|
||||
view3d_project_short_noclip(ar, co, s, data->pmat);
|
||||
}
|
||||
|
||||
data->func(data->userData, eve, s[0], s[1], index);
|
||||
}
|
||||
}
|
||||
void mesh_foreachScreenVert(void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
|
||||
{
|
||||
struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
|
||||
View3D *v3d= NULL; // XXX
|
||||
DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
|
||||
|
||||
data.func = func;
|
||||
data.userData = userData;
|
||||
data.clipVerts = clipVerts;
|
||||
|
||||
view3d_get_object_project_mat(v3d, G.obedit, data.pmat, data.vmat);
|
||||
|
||||
EM_init_index_arrays(1, 0, 0);
|
||||
dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
|
||||
EM_free_index_arrays();
|
||||
|
||||
dm->release(dm);
|
||||
}
|
||||
|
||||
static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
|
||||
{
|
||||
struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
|
||||
ARegion *ar= NULL; // XXX
|
||||
View3D *v3d= NULL; // XXX
|
||||
EditEdge *eed = EM_get_edge_for_index(index);
|
||||
short s[2][2];
|
||||
|
||||
if (eed->h==0) {
|
||||
if (data->clipVerts==1) {
|
||||
view3d_project_short_clip(ar, v3d, v0co, s[0], data->pmat, data->vmat);
|
||||
view3d_project_short_clip(ar, v3d, v1co, s[1], data->pmat, data->vmat);
|
||||
} else {
|
||||
view3d_project_short_noclip(ar, v0co, s[0], data->pmat);
|
||||
view3d_project_short_noclip(ar, v1co, s[1], data->pmat);
|
||||
|
||||
if (data->clipVerts==2) {
|
||||
if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<ar->winx && s[0][1]<ar->winy))
|
||||
if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<ar->winx && s[1][1]<ar->winy))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
|
||||
}
|
||||
}
|
||||
void mesh_foreachScreenEdge(void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts)
|
||||
{
|
||||
struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
|
||||
View3D *v3d= NULL; // XXX
|
||||
DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
|
||||
|
||||
data.func = func;
|
||||
data.userData = userData;
|
||||
data.clipVerts = clipVerts;
|
||||
|
||||
view3d_get_object_project_mat(v3d, G.obedit, data.pmat, data.vmat);
|
||||
|
||||
EM_init_index_arrays(0, 1, 0);
|
||||
dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
|
||||
EM_free_index_arrays();
|
||||
|
||||
dm->release(dm);
|
||||
}
|
||||
|
||||
static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no)
|
||||
{
|
||||
struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; float pmat[4][4], vmat[4][4]; } *data = userData;
|
||||
ARegion *ar= NULL; // XXX
|
||||
View3D *v3d= NULL; // XXX
|
||||
EditFace *efa = EM_get_face_for_index(index);
|
||||
short s[2];
|
||||
|
||||
if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
|
||||
view3d_project_short_clip(ar, v3d, cent, s, data->pmat, data->vmat);
|
||||
|
||||
data->func(data->userData, efa, s[0], s[1], index);
|
||||
}
|
||||
}
|
||||
void mesh_foreachScreenFace(void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
|
||||
{
|
||||
struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; float pmat[4][4], vmat[4][4]; } data;
|
||||
DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
|
||||
View3D *v3d= NULL; // XXX
|
||||
|
||||
data.func = func;
|
||||
data.userData = userData;
|
||||
|
||||
view3d_get_object_project_mat(v3d, G.obedit, data.pmat, data.vmat);
|
||||
|
||||
EM_init_index_arrays(0, 0, 1);
|
||||
dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
|
||||
EM_free_index_arrays();
|
||||
|
||||
dm->release(dm);
|
||||
}
|
||||
|
||||
void nurbs_foreachScreenVert(void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
|
||||
{
|
||||
ARegion *ar= NULL; // XXX
|
||||
View3D *v3d= NULL; // XXX
|
||||
float pmat[4][4], vmat[4][4];
|
||||
short s[2];
|
||||
Nurb *nu;
|
||||
int i;
|
||||
|
||||
view3d_get_object_project_mat(v3d, G.obedit, pmat, vmat);
|
||||
|
||||
for (nu= editNurb.first; nu; nu=nu->next) {
|
||||
if((nu->type & 7)==CU_BEZIER) {
|
||||
for (i=0; i<nu->pntsu; i++) {
|
||||
BezTriple *bezt = &nu->bezt[i];
|
||||
|
||||
if(bezt->hide==0) {
|
||||
if (G.f & G_HIDDENHANDLES) {
|
||||
view3d_project_short_clip(ar, v3d, bezt->vec[1], s, pmat, vmat);
|
||||
if (s[0] != IS_CLIPPED)
|
||||
func(userData, nu, NULL, bezt, 1, s[0], s[1]);
|
||||
} else {
|
||||
view3d_project_short_clip(ar, v3d, bezt->vec[0], s, pmat, vmat);
|
||||
if (s[0] != IS_CLIPPED)
|
||||
func(userData, nu, NULL, bezt, 0, s[0], s[1]);
|
||||
view3d_project_short_clip(ar, v3d, bezt->vec[1], s, pmat, vmat);
|
||||
if (s[0] != IS_CLIPPED)
|
||||
func(userData, nu, NULL, bezt, 1, s[0], s[1]);
|
||||
view3d_project_short_clip(ar, v3d, bezt->vec[2], s, pmat, vmat);
|
||||
if (s[0] != IS_CLIPPED)
|
||||
func(userData, nu, NULL, bezt, 2, s[0], s[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i=0; i<nu->pntsu*nu->pntsv; i++) {
|
||||
BPoint *bp = &nu->bp[i];
|
||||
|
||||
if(bp->hide==0) {
|
||||
view3d_project_short_clip(ar, v3d, bp->vec, s, pmat, vmat);
|
||||
func(userData, nu, bp, NULL, -1, s[0], s[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ************** 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_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
|
||||
{
|
||||
Scene *scene= NULL; // XXX
|
||||
EditFace *efa = EM_get_face_for_index(index);
|
||||
|
||||
if (efa->h==0 && efa->fgonf!=EM_FGON) {
|
||||
glVertex3fv(cent);
|
||||
glVertex3f( cent[0] + no[0]*scene->editbutsize,
|
||||
cent[1] + no[1]*scene->editbutsize,
|
||||
cent[2] + no[2]*scene->editbutsize);
|
||||
}
|
||||
}
|
||||
static void draw_dm_face_normals(DerivedMesh *dm) {
|
||||
glBegin(GL_LINES);
|
||||
dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, 0);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *no)
|
||||
{
|
||||
EditFace *efa = EM_get_face_for_index(index);
|
||||
int sel = *((int*) userData);
|
||||
|
||||
if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
|
||||
bglVertex3fv(cent);
|
||||
}
|
||||
}
|
||||
static void draw_dm_face_centers(DerivedMesh *dm, int sel)
|
||||
{
|
||||
bglBegin(GL_POINTS);
|
||||
dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
|
||||
bglEnd();
|
||||
}
|
||||
|
||||
static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
|
||||
{
|
||||
Scene *scene= NULL; // XXX
|
||||
EditVert *eve = EM_get_vert_for_index(index);
|
||||
|
||||
if (eve->h==0) {
|
||||
glVertex3fv(co);
|
||||
|
||||
if (no_f) {
|
||||
glVertex3f( co[0] + no_f[0]*scene->editbutsize,
|
||||
co[1] + no_f[1]*scene->editbutsize,
|
||||
co[2] + no_f[2]*scene->editbutsize);
|
||||
} else {
|
||||
glVertex3f( co[0] + no_s[0]*scene->editbutsize/32767.0f,
|
||||
co[1] + no_s[1]*scene->editbutsize/32767.0f,
|
||||
co[2] + no_s[2]*scene->editbutsize/32767.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void draw_dm_vert_normals(DerivedMesh *dm) {
|
||||
glBegin(GL_LINES);
|
||||
dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, NULL);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
/* Draw verts with color set based on selection */
|
||||
static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
|
||||
{
|
||||
struct { int sel; EditVert *eve_act; } * data = userData;
|
||||
EditVert *eve = EM_get_vert_for_index(index);
|
||||
|
||||
if (eve->h==0 && (eve->f&SELECT)==data->sel) {
|
||||
/* draw active larger - need to stop/start point drawing for this :/ */
|
||||
if (eve==data->eve_act) {
|
||||
float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
|
||||
UI_ThemeColor4(TH_EDITMESH_ACTIVE);
|
||||
|
||||
bglEnd();
|
||||
|
||||
glPointSize(size);
|
||||
bglBegin(GL_POINTS);
|
||||
bglVertex3fv(co);
|
||||
bglEnd();
|
||||
|
||||
UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
|
||||
glPointSize(size);
|
||||
bglBegin(GL_POINTS);
|
||||
} else {
|
||||
bglVertex3fv(co);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
|
||||
{
|
||||
struct { int sel; EditVert *eve_act; } data;
|
||||
data.sel = sel;
|
||||
data.eve_act = eve_act;
|
||||
|
||||
bglBegin(GL_POINTS);
|
||||
dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
|
||||
bglEnd();
|
||||
}
|
||||
|
||||
/* Draw edges with color set based on selection */
|
||||
static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
|
||||
{
|
||||
EditEdge *eed = EM_get_edge_for_index(index);
|
||||
//unsigned char **cols = userData, *col;
|
||||
struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
|
||||
unsigned char *col;
|
||||
|
||||
if (eed->h==0) {
|
||||
if (eed==data->eed_act) {
|
||||
glColor4ubv(data->actCol);
|
||||
} else {
|
||||
if (eed->f&SELECT) {
|
||||
col = data->selCol;
|
||||
} else {
|
||||
col = data->baseCol;
|
||||
}
|
||||
/* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode */
|
||||
if (col[3]==0) return 0;
|
||||
|
||||
glColor4ubv(col);
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act)
|
||||
{
|
||||
struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
|
||||
|
||||
data.baseCol = baseCol;
|
||||
data.selCol = selCol;
|
||||
data.actCol = actCol;
|
||||
data.eed_act = eed_act;
|
||||
dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
|
||||
}
|
||||
|
||||
/* Draw edges */
|
||||
static int draw_dm_edges__setDrawOptions(void *userData, int index)
|
||||
{
|
||||
return EM_get_edge_for_index(index)->h==0;
|
||||
}
|
||||
static void draw_dm_edges(DerivedMesh *dm)
|
||||
{
|
||||
dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
|
||||
}
|
||||
|
||||
/* Draw edges with color interpolated based on selection */
|
||||
static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
|
||||
{
|
||||
return EM_get_edge_for_index(index)->h==0;
|
||||
}
|
||||
static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
|
||||
{
|
||||
EditEdge *eed = EM_get_edge_for_index(index);
|
||||
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->drawMappedEdgesInterp(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, int index)
|
||||
{
|
||||
EditEdge *eed = EM_get_edge_for_index(index);
|
||||
|
||||
return (eed->h==0 && eed->seam);
|
||||
}
|
||||
static void draw_dm_edges_seams(DerivedMesh *dm)
|
||||
{
|
||||
dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
|
||||
}
|
||||
|
||||
/* Draw only sharp edges */
|
||||
static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
|
||||
{
|
||||
EditEdge *eed = EM_get_edge_for_index(index);
|
||||
|
||||
return (eed->h==0 && eed->sharp);
|
||||
}
|
||||
static void draw_dm_edges_sharp(DerivedMesh *dm)
|
||||
{
|
||||
dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Draw faces with color set based on selection
|
||||
* return 2 for the active face so it renders with stipple enabled */
|
||||
static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r)
|
||||
{
|
||||
struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
|
||||
EditFace *efa = EM_get_face_for_index(index);
|
||||
unsigned char *col;
|
||||
|
||||
if (efa->h==0) {
|
||||
if (efa == data->efa_act) {
|
||||
glColor4ubv(data->cols[2]);
|
||||
return 2; /* stipple */
|
||||
} else {
|
||||
col = data->cols[(efa->f&SELECT)?1:0];
|
||||
if (col[3]==0) return 0;
|
||||
glColor4ubv(col);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* also draws the active face */
|
||||
static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act)
|
||||
{
|
||||
struct { unsigned char *cols[3]; EditFace *efa_act; } data;
|
||||
data.cols[0] = baseCol;
|
||||
data.cols[1] = selCol;
|
||||
data.cols[2] = actCol;
|
||||
data.efa_act = efa_act;
|
||||
|
||||
dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
|
||||
}
|
||||
|
||||
static int draw_dm_creases__setDrawOptions(void *userData, int index)
|
||||
{
|
||||
EditEdge *eed = EM_get_edge_for_index(index);
|
||||
|
||||
if (eed->h==0 && eed->crease!=0.0) {
|
||||
UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static void draw_dm_creases(DerivedMesh *dm)
|
||||
{
|
||||
glLineWidth(3.0);
|
||||
dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
|
||||
glLineWidth(1.0);
|
||||
}
|
||||
|
||||
static int draw_dm_bweights__setDrawOptions(void *userData, int index)
|
||||
{
|
||||
EditEdge *eed = EM_get_edge_for_index(index);
|
||||
|
||||
if (eed->h==0 && eed->bweight!=0.0) {
|
||||
UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
|
||||
{
|
||||
EditVert *eve = EM_get_vert_for_index(index);
|
||||
|
||||
if (eve->h==0 && eve->bweight!=0.0) {
|
||||
UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
|
||||
bglVertex3fv(co);
|
||||
}
|
||||
}
|
||||
static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
|
||||
{
|
||||
if (scene->selectmode & SCE_SELECT_VERTEX) {
|
||||
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
|
||||
bglBegin(GL_POINTS);
|
||||
dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
|
||||
bglEnd();
|
||||
}
|
||||
else {
|
||||
glLineWidth(3.0);
|
||||
dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
|
||||
glLineWidth(1.0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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(Scene *scene, View3D *v3d, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
|
||||
{
|
||||
int sel;
|
||||
|
||||
if(v3d->zbuf) glDepthMask(0); // disable write in zbuffer, zbuf select
|
||||
|
||||
for (sel=0; sel<2; sel++) {
|
||||
char col[4], fcol[4];
|
||||
int pass;
|
||||
|
||||
UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
|
||||
UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
|
||||
|
||||
for (pass=0; pass<2; pass++) {
|
||||
float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
|
||||
float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
|
||||
|
||||
if (pass==0) {
|
||||
if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
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(scene->selectmode & SCE_SELECT_VERTEX) {
|
||||
glPointSize(size);
|
||||
glColor4ubv((GLubyte *)col);
|
||||
draw_dm_verts(cageDM, sel, eve_act);
|
||||
}
|
||||
|
||||
if( CHECK_OB_DRAWFACEDOT(scene, v3d, G.obedit->dt) ) {
|
||||
glPointSize(fsize);
|
||||
glColor4ubv((GLubyte *)fcol);
|
||||
draw_dm_face_centers(cageDM, sel);
|
||||
}
|
||||
|
||||
if (pass==0) {
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(v3d->zbuf) glDepthMask(1);
|
||||
glPointSize(1.0);
|
||||
}
|
||||
|
||||
static void draw_em_fancy_edges(Scene *scene, View3D *v3d, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
|
||||
{
|
||||
int pass;
|
||||
unsigned char wireCol[4], selCol[4], actCol[4];
|
||||
|
||||
/* since this function does transparant... */
|
||||
UI_GetThemeColor4ubv(TH_EDGE_SELECT, (char *)selCol);
|
||||
UI_GetThemeColor4ubv(TH_WIRE, (char *)wireCol);
|
||||
UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)actCol);
|
||||
|
||||
/* when sel only is used, dont render wire, only selected, this is used for
|
||||
* textured draw mode when the 'edges' option is disabled */
|
||||
if (sel_only)
|
||||
wireCol[3] = 0;
|
||||
|
||||
for (pass=0; pass<2; pass++) {
|
||||
/* show wires in transparant when no zbuf clipping for select */
|
||||
if (pass==0) {
|
||||
if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
selCol[3] = 85;
|
||||
if (!sel_only) wireCol[3] = 85;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
selCol[3] = 255;
|
||||
if (!sel_only) wireCol[3] = 255;
|
||||
}
|
||||
|
||||
if(scene->selectmode == SCE_SELECT_FACE) {
|
||||
draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
|
||||
}
|
||||
else if( (G.f & G_DRAWEDGES) || (scene->selectmode & SCE_SELECT_EDGE) ) {
|
||||
if(cageDM->drawMappedEdgesInterp && (scene->selectmode & SCE_SELECT_VERTEX)) {
|
||||
glShadeModel(GL_SMOOTH);
|
||||
draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
|
||||
glShadeModel(GL_FLAT);
|
||||
} else {
|
||||
draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!sel_only) {
|
||||
glColor4ubv(wireCol);
|
||||
draw_dm_edges(cageDM);
|
||||
}
|
||||
}
|
||||
|
||||
if (pass==0) {
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_em_measure_stats(View3D *v3d, 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 */
|
||||
char conv_float[5]; /* Use a float conversion matching the grid size */
|
||||
float area, col[3]; /* area of the face, color of the text to draw */
|
||||
|
||||
if(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))
|
||||
return;
|
||||
|
||||
/* make the precission of the pronted value proportionate to the gridsize */
|
||||
if ((v3d->grid) < 0.01)
|
||||
strcpy(conv_float, "%.6f");
|
||||
else if ((v3d->grid) < 0.1)
|
||||
strcpy(conv_float, "%.5f");
|
||||
else if ((v3d->grid) < 1.0)
|
||||
strcpy(conv_float, "%.4f");
|
||||
else if ((v3d->grid) < 10.0)
|
||||
strcpy(conv_float, "%.3f");
|
||||
else
|
||||
strcpy(conv_float, "%.2f");
|
||||
|
||||
|
||||
if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
if(v3d->zbuf) bglPolygonOffset(5.0);
|
||||
|
||||
if(G.f & G_DRAW_EDGELEN) {
|
||||
UI_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) {
|
||||
/* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
|
||||
if((eed->h != EM_FGON) && ((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(v3d->flag & V3D_GLOBAL_STATS) {
|
||||
Mat4MulVecfl(ob->obmat, v1);
|
||||
Mat4MulVecfl(ob->obmat, v2);
|
||||
}
|
||||
|
||||
sprintf(val, conv_float, VecLenf(v1, v2));
|
||||
BMF_DrawString( G.fonts, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(G.f & G_DRAW_FACEAREA) {
|
||||
// XXX extern int faceselectedOR(EditFace *efa, int flag); // editmesh.h shouldn't be in this file... ok for now?
|
||||
|
||||
UI_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)) { // XXX || (G.moving && faceselectedOR(efa, SELECT)) ) {
|
||||
VECCOPY(v1, efa->v1->co);
|
||||
VECCOPY(v2, efa->v2->co);
|
||||
VECCOPY(v3, efa->v3->co);
|
||||
if (efa->v4) {
|
||||
VECCOPY(v4, efa->v4->co);
|
||||
}
|
||||
if(v3d->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, conv_float, area);
|
||||
glRasterPos3fv(efa->cent);
|
||||
BMF_DrawString( G.fonts, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(G.f & G_DRAW_EDGEANG) {
|
||||
EditEdge *e1, *e2, *e3, *e4;
|
||||
|
||||
UI_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(v3d->flag & V3D_GLOBAL_STATS) {
|
||||
Mat4MulVecfl(ob->obmat, v1);
|
||||
Mat4MulVecfl(ob->obmat, v2);
|
||||
Mat4MulVecfl(ob->obmat, v3);
|
||||
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));
|
||||
VecLerpf(fvec, efa->cent, efa->v1->co, 0.8);
|
||||
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));
|
||||
VecLerpf(fvec, efa->cent, efa->v2->co, 0.8);
|
||||
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));
|
||||
VecLerpf(fvec, efa->cent, efa->v3->co, 0.8);
|
||||
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));
|
||||
VecLerpf(fvec, efa->cent, efa->v4->co, 0.8);
|
||||
glRasterPos3fv(fvec);
|
||||
BMF_DrawString( G.fonts, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(v3d->zbuf) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
bglPolygonOffset(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
|
||||
{
|
||||
EditFace *efa = EM_get_face_for_index(index);
|
||||
|
||||
if (efa->h==0) {
|
||||
GPU_enable_material(efa->mat_nr+1, NULL);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
|
||||
{
|
||||
EditFace *efa = EM_get_face_for_index(index);
|
||||
|
||||
return (efa->h==0);
|
||||
}
|
||||
|
||||
static void draw_em_fancy(Scene *scene, View3D *v3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
|
||||
{
|
||||
Mesh *me = ob->data;
|
||||
EditFace *efa_act = EM_get_actFace(0); /* annoying but active faces is stored differently */
|
||||
EditEdge *eed_act = NULL;
|
||||
EditVert *eve_act = NULL;
|
||||
|
||||
if (G.editMesh->selected.last) {
|
||||
EditSelection *ese = G.editMesh->selected.last;
|
||||
/* face is handeled above */
|
||||
/*if (ese->type == EDITFACE ) {
|
||||
efa_act = (EditFace *)ese->data;
|
||||
} else */ if ( ese->type == EDITEDGE ) {
|
||||
eed_act = (EditEdge *)ese->data;
|
||||
} else if ( ese->type == EDITVERT ) {
|
||||
eve_act = (EditVert *)ese->data;
|
||||
}
|
||||
}
|
||||
|
||||
EM_init_index_arrays(1, 1, 1);
|
||||
|
||||
if(dt>OB_WIRE) {
|
||||
if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
|
||||
if(draw_glsl_material(scene, ob, v3d, dt)) {
|
||||
glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
|
||||
|
||||
finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
|
||||
draw_em_fancy__setGLSLFaceOpts, NULL);
|
||||
GPU_disable_material();
|
||||
|
||||
glFrontFace(GL_CCW);
|
||||
}
|
||||
else {
|
||||
draw_mesh_textured(scene, v3d, ob, finalDM, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
|
||||
|
||||
finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
|
||||
|
||||
glFrontFace(GL_CCW);
|
||||
glDisable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
// Setup for drawing wire over, disable zbuffer
|
||||
// write to show selected edge wires better
|
||||
UI_ThemeColor(TH_WIRE);
|
||||
|
||||
bglPolygonOffset(1.0);
|
||||
glDepthMask(0);
|
||||
}
|
||||
else {
|
||||
if (cageDM!=finalDM) {
|
||||
UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
|
||||
finalDM->drawEdges(finalDM, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if((G.f & (G_DRAWFACES)) || FACESEL_PAINT_TEST) { /* transp faces */
|
||||
unsigned char col1[4], col2[4], col3[4];
|
||||
|
||||
UI_GetThemeColor4ubv(TH_FACE, (char *)col1);
|
||||
UI_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
|
||||
UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glDepthMask(0); // disable write in zbuffer, needed for nice transp
|
||||
|
||||
/* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
|
||||
if CHECK_OB_DRAWTEXTURE(v3d, dt)
|
||||
col1[3] = 0;
|
||||
|
||||
draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDepthMask(1); // restore write in zbuffer
|
||||
} else if (efa_act) {
|
||||
/* even if draw faces is off it would be nice to draw the stipple face
|
||||
* Make all other faces zero alpha except for the active
|
||||
* */
|
||||
unsigned char col1[4], col2[4], col3[4];
|
||||
col1[3] = col2[3] = 0; /* dont draw */
|
||||
UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glDepthMask(0); // disable write in zbuffer, needed for nice transp
|
||||
|
||||
draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDepthMask(1); // restore write in zbuffer
|
||||
|
||||
}
|
||||
|
||||
/* here starts all fancy draw-extra over */
|
||||
if((G.f & G_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
|
||||
/* we are drawing textures and 'G_DRAWEDGES' is disabled, dont draw any edges */
|
||||
|
||||
/* only draw selected edges otherwise there is no way of telling if a face is selected */
|
||||
draw_em_fancy_edges(scene, v3d, cageDM, 1, eed_act);
|
||||
|
||||
} else {
|
||||
if(G.f & G_DRAWSEAMS) {
|
||||
UI_ThemeColor(TH_EDGE_SEAM);
|
||||
glLineWidth(2);
|
||||
|
||||
draw_dm_edges_seams(cageDM);
|
||||
|
||||
glColor3ub(0,0,0);
|
||||
glLineWidth(1);
|
||||
}
|
||||
|
||||
if(G.f & G_DRAWSHARP) {
|
||||
UI_ThemeColor(TH_EDGE_SHARP);
|
||||
glLineWidth(2);
|
||||
|
||||
draw_dm_edges_sharp(cageDM);
|
||||
|
||||
glColor3ub(0,0,0);
|
||||
glLineWidth(1);
|
||||
}
|
||||
|
||||
if(G.f & G_DRAWCREASES) {
|
||||
draw_dm_creases(cageDM);
|
||||
}
|
||||
if(G.f & G_DRAWBWEIGHTS) {
|
||||
draw_dm_bweights(scene, cageDM);
|
||||
}
|
||||
|
||||
draw_em_fancy_edges(scene, v3d, cageDM, 0, eed_act);
|
||||
}
|
||||
if(ob==G.obedit) {
|
||||
// XXX retopo_matrix_update(v3d);
|
||||
|
||||
draw_em_fancy_verts(scene, v3d, em, cageDM, eve_act);
|
||||
|
||||
if(G.f & G_DRAWNORMALS) {
|
||||
UI_ThemeColor(TH_NORMAL);
|
||||
draw_dm_face_normals(cageDM);
|
||||
}
|
||||
if(G.f & G_DRAW_VNORMALS) {
|
||||
UI_ThemeColor(TH_NORMAL);
|
||||
draw_dm_vert_normals(cageDM);
|
||||
}
|
||||
|
||||
if(G.f & (G_DRAW_EDGELEN|G_DRAW_FACEAREA|G_DRAW_EDGEANG))
|
||||
draw_em_measure_stats(v3d, ob, em);
|
||||
}
|
||||
|
||||
if(dt>OB_WIRE) {
|
||||
glDepthMask(1);
|
||||
bglPolygonOffset(0.0);
|
||||
GPU_disable_material();
|
||||
}
|
||||
|
||||
EM_free_index_arrays();
|
||||
}
|
||||
|
||||
/* Mesh drawing routines */
|
||||
|
||||
static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
|
||||
{
|
||||
|
||||
if(v3d->transp==0) { // not when we draw the transparent pass
|
||||
glLineWidth(2.0);
|
||||
glDepthMask(0);
|
||||
|
||||
/* if transparent, we cannot draw the edges for solid select... edges have no material info.
|
||||
drawFacesSolid() doesn't draw the transparent faces */
|
||||
if(ob->dtx & OB_DRAWTRANSP) {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
dm->drawFacesSolid(dm, GPU_enable_material);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
GPU_disable_material();
|
||||
}
|
||||
else {
|
||||
dm->drawEdges(dm, 0);
|
||||
}
|
||||
|
||||
glLineWidth(1.0);
|
||||
glDepthMask(1);
|
||||
}
|
||||
}
|
||||
|
||||
static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
|
||||
{
|
||||
*drawSmooth_r = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void draw_mesh_fancy(Scene *scene, View3D *v3d, Base *base, int dt, int flag)
|
||||
{
|
||||
Object *ob= base->object;
|
||||
Mesh *me = ob->data;
|
||||
Material *ma= give_current_material(ob, 1);
|
||||
int hasHaloMat = (ma && (ma->mode&MA_HALO));
|
||||
int draw_wire = 0;
|
||||
int totvert, totedge, totface;
|
||||
DispList *dl;
|
||||
DerivedMesh *dm= mesh_get_derived_final(ob, get_viewedit_datamask());
|
||||
|
||||
if(!dm)
|
||||
return;
|
||||
|
||||
if (ob->dtx&OB_DRAWWIRE) {
|
||||
draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
|
||||
}
|
||||
|
||||
totvert = dm->getNumVerts(dm);
|
||||
totedge = dm->getNumEdges(dm);
|
||||
totface = dm->getNumFaces(dm);
|
||||
|
||||
/* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
|
||||
if(dt!=OB_SHADED)
|
||||
glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
|
||||
|
||||
// Unwanted combination.
|
||||
if (ob==OBACT && FACESEL_PAINT_TEST) draw_wire = 0;
|
||||
|
||||
if(dt==OB_BOUNDBOX) {
|
||||
draw_bounding_volume(ob);
|
||||
}
|
||||
else if(hasHaloMat || (totface==0 && totedge==0)) {
|
||||
glPointSize(1.5);
|
||||
dm->drawVerts(dm);
|
||||
glPointSize(1.0);
|
||||
}
|
||||
else if(dt==OB_WIRE || totface==0) {
|
||||
draw_wire = 1; /* draw wire only, no depth buffer stuff */
|
||||
}
|
||||
else if( (ob==OBACT && (G.f & G_TEXTUREPAINT || FACESEL_PAINT_TEST)) ||
|
||||
CHECK_OB_DRAWTEXTURE(v3d, dt))
|
||||
{
|
||||
int faceselect= (ob==OBACT && FACESEL_PAINT_TEST);
|
||||
|
||||
if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&G_PICKSEL || FACESEL_PAINT_TEST) && !draw_wire) {
|
||||
draw_mesh_object_outline(v3d, ob, dm);
|
||||
}
|
||||
|
||||
if(draw_glsl_material(scene, ob, v3d, dt)) {
|
||||
glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
|
||||
|
||||
dm->drawFacesGLSL(dm, GPU_enable_material);
|
||||
// if(get_ob_property(ob, "Text"))
|
||||
// XXX draw_mesh_text(ob, 1);
|
||||
GPU_disable_material();
|
||||
|
||||
glFrontFace(GL_CCW);
|
||||
}
|
||||
else {
|
||||
draw_mesh_textured(scene, v3d, ob, dm, faceselect);
|
||||
}
|
||||
|
||||
if(!faceselect) {
|
||||
if(base->flag & SELECT)
|
||||
UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
|
||||
else
|
||||
UI_ThemeColor(TH_WIRE);
|
||||
|
||||
dm->drawLooseEdges(dm);
|
||||
}
|
||||
}
|
||||
else if(dt==OB_SOLID) {
|
||||
if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire)
|
||||
draw_mesh_object_outline(v3d, ob, dm);
|
||||
|
||||
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, GPU_enable_material);
|
||||
GPU_disable_material();
|
||||
|
||||
glFrontFace(GL_CCW);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
if(base->flag & SELECT) {
|
||||
UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
|
||||
} else {
|
||||
UI_ThemeColor(TH_WIRE);
|
||||
}
|
||||
dm->drawLooseEdges(dm);
|
||||
}
|
||||
else if(dt==OB_SHADED) {
|
||||
int do_draw= 1; /* to resolve all G.f settings below... */
|
||||
|
||||
if(ob==OBACT) {
|
||||
do_draw= 0;
|
||||
if( (G.f & G_WEIGHTPAINT)) {
|
||||
/* enforce default material settings */
|
||||
GPU_enable_material(0, NULL);
|
||||
|
||||
/* but set default spec */
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
|
||||
glEnable(GL_COLOR_MATERIAL); /* according manpages needed */
|
||||
glColor3ub(120, 120, 120);
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
/* diffuse */
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
|
||||
dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
GPU_disable_material();
|
||||
}
|
||||
else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->mcol) {
|
||||
dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1);
|
||||
}
|
||||
else if(G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) {
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0);
|
||||
}
|
||||
else do_draw= 1;
|
||||
}
|
||||
if(do_draw) {
|
||||
dl = ob->disp.first;
|
||||
if (!dl || !dl->col1) {
|
||||
/* release and reload derivedmesh because it might be freed in
|
||||
shadeDispList due to a different datamask */
|
||||
dm->release(dm);
|
||||
shadeDispList(base);
|
||||
dl = find_displist(&ob->disp, DL_VERTCOL);
|
||||
dm= mesh_get_derived_final(ob, get_viewedit_datamask());
|
||||
}
|
||||
|
||||
if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
|
||||
draw_mesh_object_outline(v3d, ob, dm);
|
||||
}
|
||||
|
||||
/* False for dupliframe objects */
|
||||
if (dl) {
|
||||
unsigned int *obCol1 = dl->col1;
|
||||
unsigned int *obCol2 = dl->col2;
|
||||
|
||||
dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
|
||||
}
|
||||
|
||||
if(base->flag & SELECT) {
|
||||
UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
|
||||
} else {
|
||||
UI_ThemeColor(TH_WIRE);
|
||||
}
|
||||
dm->drawLooseEdges(dm);
|
||||
}
|
||||
}
|
||||
|
||||
/* set default draw color back for wire or for draw-extra later on */
|
||||
if (dt!=OB_WIRE) {
|
||||
if(base->flag & SELECT) {
|
||||
if(ob==OBACT && ob->flag & OB_FROMGROUP)
|
||||
UI_ThemeColor(TH_GROUP_ACTIVE);
|
||||
else if(ob->flag & OB_FROMGROUP)
|
||||
UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
|
||||
else if(flag!=DRAW_CONSTCOLOR)
|
||||
UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
|
||||
else
|
||||
glColor3ub(80,80,80);
|
||||
} else {
|
||||
if (ob->flag & OB_FROMGROUP)
|
||||
UI_ThemeColor(TH_GROUP);
|
||||
else {
|
||||
if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
|
||||
glColor3ub(80,80,80);
|
||||
else
|
||||
UI_ThemeColor(TH_WIRE);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (draw_wire) {
|
||||
/* If drawing wire and drawtype is not OB_WIRE then we are
|
||||
* overlaying the wires.
|
||||
*
|
||||
* UPDATE bug #10290 - With this wire-only objects can draw
|
||||
* behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
|
||||
*
|
||||
* if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
|
||||
* otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
|
||||
*/
|
||||
if (dt!=OB_WIRE && draw_wire==2) {
|
||||
bglPolygonOffset(1.0);
|
||||
glDepthMask(0); // disable write in zbuffer, selected edge wires show better
|
||||
}
|
||||
|
||||
dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
|
||||
|
||||
if (dt!=OB_WIRE && draw_wire==2) {
|
||||
glDepthMask(1);
|
||||
bglPolygonOffset(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
dm->release(dm);
|
||||
}
|
||||
|
||||
/* returns 1 if nothing was drawn, for detecting to draw an object center */
|
||||
static int draw_mesh_object(Scene *scene, View3D *v3d, Base *base, int dt, int flag)
|
||||
{
|
||||
Object *ob= base->object;
|
||||
Mesh *me= ob->data;
|
||||
int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
|
||||
|
||||
if(G.obedit && ob!=G.obedit && ob->data==G.obedit->data) {
|
||||
if(ob_get_key(ob));
|
||||
else drawlinked= 1;
|
||||
}
|
||||
|
||||
if(ob==G.obedit || drawlinked) {
|
||||
DerivedMesh *finalDM, *cageDM;
|
||||
|
||||
if (G.obedit!=ob)
|
||||
finalDM = cageDM = editmesh_get_derived_base();
|
||||
else
|
||||
cageDM = editmesh_get_derived_cage_and_final(&finalDM,
|
||||
get_viewedit_datamask());
|
||||
|
||||
if(dt>OB_WIRE) {
|
||||
// no transp in editmode, the fancy draw over goes bad then
|
||||
glsl = draw_glsl_material(scene, ob, v3d, dt);
|
||||
GPU_set_object_materials(scene, ob, glsl, NULL);
|
||||
}
|
||||
|
||||
draw_em_fancy(scene, v3d, ob, G.editMesh, cageDM, finalDM, dt);
|
||||
|
||||
if (G.obedit!=ob && finalDM)
|
||||
finalDM->release(finalDM);
|
||||
}
|
||||
// else if(!G.obedit && (G.f & G_SCULPTMODE) &&(scene->sculptdata.flags & SCULPT_DRAW_FAST) &&
|
||||
// OBACT==ob && !sculpt_modifiers_active(ob)) {
|
||||
// XXX sculptmode_draw_mesh(0);
|
||||
// }
|
||||
else {
|
||||
/* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
|
||||
if(me->totface<=4 || boundbox_clip(v3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
|
||||
glsl = draw_glsl_material(scene, ob, v3d, dt);
|
||||
check_alpha = check_material_alpha(base, ob, glsl);
|
||||
|
||||
if(dt==OB_SOLID || glsl) {
|
||||
GPU_set_object_materials(scene, ob, glsl,
|
||||
(check_alpha)? &do_alpha_pass: NULL);
|
||||
}
|
||||
|
||||
draw_mesh_fancy(scene, v3d, base, dt, flag);
|
||||
|
||||
if(me->totvert==0) retval= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* GPU_set_object_materials checked if this is needed */
|
||||
if(do_alpha_pass) add_view3d_after(v3d, base, V3D_TRANSP, flag);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* ************** DRAW DISPLIST ****************** */
|
||||
|
||||
static int draw_index_wire= 1;
|
||||
static int index3_nors_incr= 1;
|
||||
|
||||
/* returns 1 when nothing was drawn */
|
||||
static int drawDispListwire(ListBase *dlbase)
|
||||
{
|
||||
DispList *dl;
|
||||
int parts, nr;
|
||||
float *data;
|
||||
|
||||
if(dlbase==NULL) return 1;
|
||||
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
for(dl= dlbase->first; dl; dl= dl->next) {
|
||||
if(dl->parts==0 || dl->nr==0)
|
||||
continue;
|
||||
|
||||
data= dl->verts;
|
||||
|
||||
switch(dl->type) {
|
||||
case DL_SEGM:
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, data);
|
||||
|
||||
for(parts=0; parts<dl->parts; parts++)
|
||||
glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
|
||||
|
||||
break;
|
||||
case DL_POLY:
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, data);
|
||||
|
||||
for(parts=0; parts<dl->parts; parts++)
|
||||
glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
|
||||
|
||||
break;
|
||||
case DL_SURF:
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, data);
|
||||
|
||||
for(parts=0; parts<dl->parts; parts++) {
|
||||
if(dl->flag & DL_CYCL_U)
|
||||
glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
|
||||
else
|
||||
glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
|
||||
}
|
||||
|
||||
for(nr=0; nr<dl->nr; nr++) {
|
||||
int ofs= 3*dl->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();
|
||||
|
||||
/* (ton) this code crashes for me when resolv is 86 or higher... no clue */
|
||||
// glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
|
||||
// if(dl->flag & DL_CYCL_V)
|
||||
// glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
|
||||
// else
|
||||
// glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
|
||||
}
|
||||
break;
|
||||
|
||||
case DL_INDEX3:
|
||||
if(draw_index_wire) {
|
||||
glVertexPointer(3, GL_FLOAT, 0, dl->verts);
|
||||
glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
|
||||
}
|
||||
break;
|
||||
|
||||
case DL_INDEX4:
|
||||
if(draw_index_wire) {
|
||||
glVertexPointer(3, GL_FLOAT, 0, dl->verts);
|
||||
glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)
|
||||
{
|
||||
DispList *dl;
|
||||
GPUVertexAttribs gattribs;
|
||||
float *data, curcol[4];
|
||||
float *ndata;
|
||||
|
||||
if(lb==NULL) return;
|
||||
|
||||
/* for drawing wire */
|
||||
glGetFloatv(GL_CURRENT_COLOR, curcol);
|
||||
|
||||
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_SEGM:
|
||||
if(ob->type==OB_SURF) {
|
||||
int nr;
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glColor3fv(curcol);
|
||||
|
||||
// glVertexPointer(3, GL_FLOAT, 0, dl->verts);
|
||||
// glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
for(nr= dl->nr; nr; nr--, data+=3)
|
||||
glVertex3fv(data);
|
||||
glEnd();
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
}
|
||||
break;
|
||||
case DL_POLY:
|
||||
if(ob->type==OB_SURF) {
|
||||
int nr;
|
||||
|
||||
UI_ThemeColor(TH_WIRE);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
/* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
|
||||
//glVertexPointer(3, GL_FLOAT, 0, dl->verts);
|
||||
//glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
|
||||
|
||||
glBegin(GL_LINE_LOOP);
|
||||
for(nr= dl->nr; nr; nr--, data+=3)
|
||||
glVertex3fv(data);
|
||||
glEnd();
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
break;
|
||||
}
|
||||
case DL_SURF:
|
||||
|
||||
if(dl->index) {
|
||||
GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
|
||||
|
||||
if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
|
||||
else glShadeModel(GL_FLAT);
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, dl->verts);
|
||||
glNormalPointer(GL_FLOAT, 0, dl->nors);
|
||||
glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
|
||||
GPU_disable_material();
|
||||
}
|
||||
break;
|
||||
|
||||
case DL_INDEX3:
|
||||
GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, dl->verts);
|
||||
|
||||
/* voor polys only one normal needed */
|
||||
if(index3_nors_incr==0) {
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glNormal3fv(ndata);
|
||||
}
|
||||
else
|
||||
glNormalPointer(GL_FLOAT, 0, dl->nors);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
|
||||
GPU_disable_material();
|
||||
|
||||
if(index3_nors_incr==0)
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
break;
|
||||
|
||||
case DL_INDEX4:
|
||||
GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, dl->verts);
|
||||
glNormalPointer(GL_FLOAT, 0, dl->nors);
|
||||
glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
|
||||
|
||||
GPU_disable_material();
|
||||
|
||||
break;
|
||||
}
|
||||
dl= dl->next;
|
||||
}
|
||||
|
||||
glShadeModel(GL_FLAT);
|
||||
glDisable(GL_LIGHTING);
|
||||
glFrontFace(GL_CCW);
|
||||
}
|
||||
|
||||
static void drawDispListshaded(ListBase *lb, Object *ob)
|
||||
{
|
||||
DispList *dl, *dlob;
|
||||
unsigned int *cdata;
|
||||
|
||||
if(lb==NULL) return;
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
dl= lb->first;
|
||||
dlob= ob->disp.first;
|
||||
while(dl && dlob) {
|
||||
|
||||
cdata= dlob->col1;
|
||||
if(cdata==NULL) break;
|
||||
|
||||
switch(dl->type) {
|
||||
case DL_SURF:
|
||||
if(dl->index) {
|
||||
glVertexPointer(3, GL_FLOAT, 0, dl->verts);
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
|
||||
glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
|
||||
}
|
||||
break;
|
||||
|
||||
case DL_INDEX3:
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, dl->verts);
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
|
||||
glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
|
||||
break;
|
||||
|
||||
case DL_INDEX4:
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, dl->verts);
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
|
||||
glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
|
||||
break;
|
||||
}
|
||||
|
||||
dl= dl->next;
|
||||
dlob= dlob->next;
|
||||
}
|
||||
|
||||
glShadeModel(GL_FLAT);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
/* returns 1 when nothing was drawn */
|
||||
static int drawDispList(Scene *scene, View3D *v3d, Base *base, int dt)
|
||||
{
|
||||
Object *ob= base->object;
|
||||
ListBase *lb=0;
|
||||
DispList *dl;
|
||||
Curve *cu;
|
||||
int solid, retval= 0;
|
||||
|
||||
solid= (dt > OB_WIRE);
|
||||
|
||||
switch(ob->type) {
|
||||
case OB_FONT:
|
||||
case OB_CURVE:
|
||||
cu= ob->data;
|
||||
|
||||
lb= &cu->disp;
|
||||
|
||||
if(solid) {
|
||||
dl= lb->first;
|
||||
if(dl==NULL) return 1;
|
||||
|
||||
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(draw_glsl_material(scene, ob, v3d, dt)) {
|
||||
GPU_set_object_materials(scene, ob, 1, NULL);
|
||||
drawDispListsolid(lb, ob, 1);
|
||||
}
|
||||
else if(dt == OB_SHADED) {
|
||||
if(ob->disp.first==0) shadeDispList(base);
|
||||
drawDispListshaded(lb, ob);
|
||||
}
|
||||
else {
|
||||
GPU_set_object_materials(scene, ob, 0, NULL);
|
||||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
|
||||
drawDispListsolid(lb, ob, 0);
|
||||
}
|
||||
if(ob==G.obedit && cu->bevobj==NULL && cu->taperobj==NULL && cu->ext1 == 0.0 && cu->ext2 == 0.0) {
|
||||
cpack(0);
|
||||
draw_index_wire= 0;
|
||||
drawDispListwire(lb);
|
||||
draw_index_wire= 1;
|
||||
}
|
||||
}
|
||||
index3_nors_incr= 1;
|
||||
}
|
||||
else {
|
||||
draw_index_wire= 0;
|
||||
retval= drawDispListwire(lb);
|
||||
draw_index_wire= 1;
|
||||
}
|
||||
break;
|
||||
case OB_SURF:
|
||||
|
||||
lb= &((Curve *)ob->data)->disp;
|
||||
|
||||
if(solid) {
|
||||
dl= lb->first;
|
||||
if(dl==NULL) return 1;
|
||||
|
||||
if(dl->nors==NULL) addnormalsDispList(ob, lb);
|
||||
|
||||
if(draw_glsl_material(scene, ob, v3d, dt)) {
|
||||
GPU_set_object_materials(scene, ob, 1, NULL);
|
||||
drawDispListsolid(lb, ob, 1);
|
||||
}
|
||||
else if(dt==OB_SHADED) {
|
||||
if(ob->disp.first==NULL) shadeDispList(base);
|
||||
drawDispListshaded(lb, ob);
|
||||
}
|
||||
else {
|
||||
GPU_set_object_materials(scene, ob, 0, NULL);
|
||||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
|
||||
|
||||
drawDispListsolid(lb, ob, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
retval= drawDispListwire(lb);
|
||||
}
|
||||
break;
|
||||
case OB_MBALL:
|
||||
|
||||
if( is_basis_mball(ob)) {
|
||||
lb= &ob->disp;
|
||||
if(lb->first==NULL) makeDispListMBall(ob);
|
||||
if(lb->first==NULL) return 1;
|
||||
|
||||
if(solid) {
|
||||
|
||||
if(draw_glsl_material(scene, ob, v3d, dt)) {
|
||||
GPU_set_object_materials(scene, ob, 1, NULL);
|
||||
drawDispListsolid(lb, ob, 1);
|
||||
}
|
||||
else if(dt == OB_SHADED) {
|
||||
dl= lb->first;
|
||||
if(dl && dl->col1==0) shadeDispList(base);
|
||||
drawDispListshaded(lb, ob);
|
||||
}
|
||||
else {
|
||||
GPU_set_object_materials(scene, ob, 0, NULL);
|
||||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
|
||||
|
||||
drawDispListsolid(lb, ob, 0);
|
||||
}
|
||||
}
|
||||
else{
|
||||
/* MetaBalls use DL_INDEX4 type of DispList */
|
||||
retval= drawDispListwire(lb);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* unified drawing of all new particle systems draw types except dupli ob & group */
|
||||
/* mostly tries to use vertex arrays for speed */
|
||||
|
||||
/* 1. check that everything is ok & updated */
|
||||
/* 2. start initialising things */
|
||||
/* 3. initialize according to draw type */
|
||||
/* 4. allocate drawing data arrays */
|
||||
/* 5. start filling the arrays */
|
||||
/* 6. draw the arrays */
|
||||
/* 7. clean up */
|
||||
static void draw_new_particle_system(const bContext *C, View3D *v3d, Base *base, ParticleSystem *psys, int dt)
|
||||
{
|
||||
Object *ob=base->object;
|
||||
ParticleSystemModifierData *psmd;
|
||||
ParticleSettings *part;
|
||||
ParticleData *pars, *pa;
|
||||
ParticleKey state, *states=0;
|
||||
ParticleCacheKey *cache=0;
|
||||
Material *ma;
|
||||
Object *bb_ob=0;
|
||||
float vel[3], vec[3], vec2[3], imat[4][4], onevec[3]={0.0f,0.0f,0.0f}, bb_center[3];
|
||||
float timestep, pixsize=1.0, pa_size, pa_time, r_tilt;
|
||||
float cfra=bsystem_time(ob,(float)CFRA,0.0);
|
||||
float *vdata=0, *vedata=0, *cdata=0, *ndata=0, *vd=0, *ved=0, *cd=0, *nd=0, xvec[3], yvec[3], zvec[3];
|
||||
float ma_r=0.0f, ma_g=0.0f, ma_b=0.0f;
|
||||
int a, k, k_max=0, totpart, totpoint=0, draw_as, path_nbr=0;
|
||||
int path_possible=0, keys_possible=0, draw_keys=0, totchild=0;
|
||||
int select=ob->flag&SELECT, create_cdata=0;
|
||||
GLint polygonmode[2];
|
||||
char val[32];
|
||||
|
||||
/* 1. */
|
||||
if(psys==0)
|
||||
return;
|
||||
|
||||
part=psys->part;
|
||||
pars=psys->particles;
|
||||
|
||||
if(part==0 || !psys_check_enabled(ob, psys))
|
||||
return;
|
||||
|
||||
if(pars==0) return;
|
||||
|
||||
if(!G.obedit && psys_in_edit_mode(psys)
|
||||
&& psys->flag & PSYS_HAIR_DONE && part->draw_as==PART_DRAW_PATH)
|
||||
return;
|
||||
|
||||
if(part->draw_as==PART_DRAW_NOT) return;
|
||||
|
||||
/* 2. */
|
||||
if(part->phystype==PART_PHYS_KEYED){
|
||||
if(psys->flag & PSYS_FIRST_KEYED){
|
||||
if(psys->flag&PSYS_KEYED){
|
||||
select=psys_count_keyed_targets(ob,psys);
|
||||
if(psys->totkeyed==0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
if(select){
|
||||
select=0;
|
||||
if(psys_get_current(ob)==psys)
|
||||
select=1;
|
||||
}
|
||||
|
||||
psys->flag|=PSYS_DRAWING;
|
||||
|
||||
if(part->type==PART_HAIR && !psys->childcache)
|
||||
totchild=0;
|
||||
else
|
||||
totchild=psys->totchild*part->disp/100;
|
||||
|
||||
ma= give_current_material(ob,part->omat);
|
||||
|
||||
if(ma) {
|
||||
ma_r = ma->r;
|
||||
ma_g = ma->g;
|
||||
ma_b = ma->b;
|
||||
}
|
||||
|
||||
if(v3d->zbuf) glDepthMask(1);
|
||||
|
||||
if(select)
|
||||
cpack(0xFFFFFF);
|
||||
else if((ma) && (part->draw&PART_DRAW_MAT_COL)) {
|
||||
glColor3f(ma->r,ma->g,ma->b);
|
||||
create_cdata = 1;
|
||||
}
|
||||
else
|
||||
cpack(0);
|
||||
|
||||
psmd= psys_get_modifier(ob,psys);
|
||||
|
||||
timestep= psys_get_timestep(part);
|
||||
|
||||
wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
|
||||
|
||||
if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) {
|
||||
float mat[4][4];
|
||||
Mat4MulMat4(mat, psys->imat, ob->obmat);
|
||||
wmMultMatrix(CTX_wm_window(C), mat);
|
||||
}
|
||||
|
||||
totpart=psys->totpart;
|
||||
draw_as=part->draw_as;
|
||||
|
||||
if(part->flag&PART_GLOB_TIME)
|
||||
cfra=bsystem_time(0,(float)CFRA,0.0);
|
||||
|
||||
if(psys->pathcache){
|
||||
path_possible=1;
|
||||
keys_possible=1;
|
||||
}
|
||||
if(draw_as==PART_DRAW_PATH && path_possible==0)
|
||||
draw_as=PART_DRAW_DOT;
|
||||
|
||||
if(draw_as!=PART_DRAW_PATH && keys_possible && part->draw&PART_DRAW_KEYS){
|
||||
path_nbr=part->keys_step;
|
||||
draw_keys=1;
|
||||
}
|
||||
|
||||
/* 3. */
|
||||
switch(draw_as){
|
||||
case PART_DRAW_DOT:
|
||||
if(part->draw_size)
|
||||
glPointSize(part->draw_size);
|
||||
else
|
||||
glPointSize(2.0); /* default dot size */
|
||||
break;
|
||||
case PART_DRAW_CIRC:
|
||||
/* calculate view aligned matrix: */
|
||||
Mat4CpyMat4(imat, v3d->viewinv);
|
||||
Normalize(imat[0]);
|
||||
Normalize(imat[1]);
|
||||
/* no break! */
|
||||
case PART_DRAW_CROSS:
|
||||
case PART_DRAW_AXIS:
|
||||
/* lets calculate the scale: */
|
||||
pixsize= v3d->persmat[0][3]*ob->obmat[3][0]+ v3d->persmat[1][3]*ob->obmat[3][1]+ v3d->persmat[2][3]*ob->obmat[3][2]+ v3d->persmat[3][3];
|
||||
pixsize*= v3d->pixsize;
|
||||
if(part->draw_size==0.0)
|
||||
pixsize*=2.0;
|
||||
else
|
||||
pixsize*=part->draw_size;
|
||||
break;
|
||||
case PART_DRAW_OB:
|
||||
if(part->dup_ob==0)
|
||||
draw_as=PART_DRAW_DOT;
|
||||
else
|
||||
draw_as=0;
|
||||
break;
|
||||
case PART_DRAW_GR:
|
||||
if(part->dup_group==0)
|
||||
draw_as=PART_DRAW_DOT;
|
||||
else
|
||||
draw_as=0;
|
||||
break;
|
||||
case PART_DRAW_BB:
|
||||
if(v3d->camera==0 && part->bb_ob==0){
|
||||
// XXX error("Billboards need an active camera or a target object!");
|
||||
|
||||
draw_as=part->draw_as=PART_DRAW_DOT;
|
||||
|
||||
if(part->draw_size)
|
||||
glPointSize(part->draw_size);
|
||||
else
|
||||
glPointSize(2.0); /* default dot size */
|
||||
}
|
||||
else if(part->bb_ob)
|
||||
bb_ob=part->bb_ob;
|
||||
else
|
||||
bb_ob=v3d->camera;
|
||||
|
||||
if(part->bb_align<PART_BB_VIEW)
|
||||
onevec[part->bb_align]=1.0f;
|
||||
break;
|
||||
case PART_DRAW_PATH:
|
||||
break;
|
||||
}
|
||||
if(part->draw & PART_DRAW_SIZE && part->draw_as!=PART_DRAW_CIRC){
|
||||
Mat4CpyMat4(imat, v3d->viewinv);
|
||||
Normalize(imat[0]);
|
||||
Normalize(imat[1]);
|
||||
}
|
||||
|
||||
/* 4. */
|
||||
if(draw_as && draw_as!=PART_DRAW_PATH){
|
||||
if(draw_as!=PART_DRAW_CIRC){
|
||||
switch(draw_as){
|
||||
case PART_DRAW_AXIS:
|
||||
case PART_DRAW_CROSS:
|
||||
if(draw_as!=PART_DRAW_CROSS || create_cdata)
|
||||
cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_cdata");
|
||||
vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_vdata");
|
||||
break;
|
||||
case PART_DRAW_LINE:
|
||||
if(create_cdata)
|
||||
cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_cdata");
|
||||
vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_vdata");
|
||||
break;
|
||||
case PART_DRAW_BB:
|
||||
if(create_cdata)
|
||||
cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_cdata");
|
||||
vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
|
||||
ndata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
|
||||
break;
|
||||
default:
|
||||
if(create_cdata)
|
||||
cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_cdata");
|
||||
vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_vdata");
|
||||
}
|
||||
}
|
||||
|
||||
if(part->draw&PART_DRAW_VEL && draw_as!=PART_DRAW_LINE)
|
||||
vedata=MEM_callocN((totpart+totchild)*2*3*(path_nbr+1)*sizeof(float), "particle_vedata");
|
||||
|
||||
vd=vdata;
|
||||
ved=vedata;
|
||||
cd=cdata;
|
||||
nd=ndata;
|
||||
|
||||
psys->lattice=psys_get_lattice(ob,psys);
|
||||
}
|
||||
|
||||
if(draw_as){
|
||||
/* 5. */
|
||||
for(a=0,pa=pars; a<totpart+totchild; a++, pa++){
|
||||
if(a<totpart){
|
||||
if(totchild && (part->draw&PART_DRAW_PARENT)==0) continue;
|
||||
if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue;
|
||||
|
||||
pa_time=(cfra-pa->time)/pa->lifetime;
|
||||
pa_size=pa->size;
|
||||
|
||||
if((part->flag&PART_ABS_TIME)==0){
|
||||
if(ma && ma->ipo){
|
||||
IpoCurve *icu;
|
||||
|
||||
/* correction for lifetime */
|
||||
calc_ipo(ma->ipo, 100.0f*pa_time);
|
||||
|
||||
for(icu = ma->ipo->curve.first; icu; icu=icu->next) {
|
||||
if(icu->adrcode == MA_COL_R)
|
||||
ma_r = icu->curval;
|
||||
else if(icu->adrcode == MA_COL_G)
|
||||
ma_g = icu->curval;
|
||||
else if(icu->adrcode == MA_COL_B)
|
||||
ma_b = icu->curval;
|
||||
}
|
||||
}
|
||||
if(part->ipo) {
|
||||
IpoCurve *icu;
|
||||
|
||||
/* correction for lifetime */
|
||||
calc_ipo(part->ipo, 100*pa_time);
|
||||
|
||||
for(icu = part->ipo->curve.first; icu; icu=icu->next) {
|
||||
if(icu->adrcode == PART_SIZE)
|
||||
pa_size = icu->curval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r_tilt=1.0f+pa->r_ave[0];
|
||||
|
||||
if(path_nbr){
|
||||
cache=psys->pathcache[a];
|
||||
k_max=(int)(cache->steps);
|
||||
}
|
||||
}
|
||||
else{
|
||||
ChildParticle *cpa= &psys->child[a-totpart];
|
||||
|
||||
pa_time=psys_get_child_time(psys,cpa,cfra);
|
||||
|
||||
if((part->flag&PART_ABS_TIME)==0) {
|
||||
if(ma && ma->ipo){
|
||||
IpoCurve *icu;
|
||||
|
||||
/* correction for lifetime */
|
||||
calc_ipo(ma->ipo, 100.0f*pa_time);
|
||||
|
||||
for(icu = ma->ipo->curve.first; icu; icu=icu->next) {
|
||||
if(icu->adrcode == MA_COL_R)
|
||||
ma_r = icu->curval;
|
||||
else if(icu->adrcode == MA_COL_G)
|
||||
ma_g = icu->curval;
|
||||
else if(icu->adrcode == MA_COL_B)
|
||||
ma_b = icu->curval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pa_size=psys_get_child_size(psys,cpa,cfra,0);
|
||||
|
||||
r_tilt=2.0f*cpa->rand[2];
|
||||
if(path_nbr){
|
||||
cache=psys->childcache[a-totpart];
|
||||
k_max=(int)(cache->steps);
|
||||
}
|
||||
}
|
||||
|
||||
if(draw_as!=PART_DRAW_PATH){
|
||||
int next_pa=0;
|
||||
for(k=0; k<=path_nbr; k++){
|
||||
if(draw_keys){
|
||||
state.time=(float)k/(float)path_nbr;
|
||||
psys_get_particle_on_path(ob,psys,a,&state,1);
|
||||
}
|
||||
else if(path_nbr){
|
||||
if(k<=k_max){
|
||||
VECCOPY(state.co,(cache+k)->co);
|
||||
VECCOPY(state.vel,(cache+k)->vel);
|
||||
QUATCOPY(state.rot,(cache+k)->rot);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else{
|
||||
state.time=cfra;
|
||||
if(psys_get_particle_state(ob,psys,a,&state,0)==0){
|
||||
next_pa=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(draw_as){
|
||||
case PART_DRAW_DOT:
|
||||
if(cd) {
|
||||
cd[0]=ma_r;
|
||||
cd[1]=ma_g;
|
||||
cd[2]=ma_b;
|
||||
cd+=3;
|
||||
}
|
||||
if(vd){
|
||||
VECCOPY(vd,state.co) vd+=3;
|
||||
}
|
||||
break;
|
||||
case PART_DRAW_CROSS:
|
||||
case PART_DRAW_AXIS:
|
||||
vec[0]=2.0f*pixsize;
|
||||
vec[1]=vec[2]=0.0;
|
||||
QuatMulVecf(state.rot,vec);
|
||||
if(draw_as==PART_DRAW_AXIS){
|
||||
cd[1]=cd[2]=cd[4]=cd[5]=0.0;
|
||||
cd[0]=cd[3]=1.0;
|
||||
cd[6]=cd[8]=cd[9]=cd[11]=0.0;
|
||||
cd[7]=cd[10]=1.0;
|
||||
cd[13]=cd[12]=cd[15]=cd[16]=0.0;
|
||||
cd[14]=cd[17]=1.0;
|
||||
cd+=18;
|
||||
|
||||
VECCOPY(vec2,state.co);
|
||||
}
|
||||
else {
|
||||
if(cd) {
|
||||
cd[0]=cd[3]=cd[6]=cd[9]=cd[12]=cd[15]=ma_r;
|
||||
cd[1]=cd[4]=cd[7]=cd[10]=cd[13]=cd[16]=ma_g;
|
||||
cd[2]=cd[5]=cd[8]=cd[11]=cd[14]=cd[17]=ma_b;
|
||||
cd+=18;
|
||||
}
|
||||
VECSUB(vec2,state.co,vec);
|
||||
}
|
||||
|
||||
VECADD(vec,state.co,vec);
|
||||
VECCOPY(vd,vec); vd+=3;
|
||||
VECCOPY(vd,vec2); vd+=3;
|
||||
|
||||
vec[1]=2.0f*pixsize;
|
||||
vec[0]=vec[2]=0.0;
|
||||
QuatMulVecf(state.rot,vec);
|
||||
if(draw_as==PART_DRAW_AXIS){
|
||||
VECCOPY(vec2,state.co);
|
||||
}
|
||||
else VECSUB(vec2,state.co,vec);
|
||||
|
||||
VECADD(vec,state.co,vec);
|
||||
VECCOPY(vd,vec); vd+=3;
|
||||
VECCOPY(vd,vec2); vd+=3;
|
||||
|
||||
vec[2]=2.0f*pixsize;
|
||||
vec[0]=vec[1]=0.0;
|
||||
QuatMulVecf(state.rot,vec);
|
||||
if(draw_as==PART_DRAW_AXIS){
|
||||
VECCOPY(vec2,state.co);
|
||||
}
|
||||
else VECSUB(vec2,state.co,vec);
|
||||
|
||||
VECADD(vec,state.co,vec);
|
||||
|
||||
VECCOPY(vd,vec); vd+=3;
|
||||
VECCOPY(vd,vec2); vd+=3;
|
||||
break;
|
||||
case PART_DRAW_LINE:
|
||||
VECCOPY(vec,state.vel);
|
||||
Normalize(vec);
|
||||
if(part->draw & PART_DRAW_VEL_LENGTH)
|
||||
VecMulf(vec,VecLength(state.vel));
|
||||
VECADDFAC(vd,state.co,vec,-part->draw_line[0]); vd+=3;
|
||||
VECADDFAC(vd,state.co,vec,part->draw_line[1]); vd+=3;
|
||||
if(cd) {
|
||||
cd[0]=cd[3]=ma_r;
|
||||
cd[1]=cd[4]=ma_g;
|
||||
cd[2]=cd[5]=ma_b;
|
||||
cd+=3;
|
||||
}
|
||||
break;
|
||||
case PART_DRAW_CIRC:
|
||||
if(create_cdata)
|
||||
glColor3f(ma_r,ma_g,ma_b);
|
||||
drawcircball(GL_LINE_LOOP, state.co, pixsize, imat);
|
||||
break;
|
||||
case PART_DRAW_BB:
|
||||
if(cd) {
|
||||
cd[0]=cd[3]=cd[6]=cd[9]=ma_r;
|
||||
cd[1]=cd[4]=cd[7]=cd[10]=ma_g;
|
||||
cd[2]=cd[5]=cd[8]=cd[11]=ma_b;
|
||||
cd+=12;
|
||||
}
|
||||
if(part->draw&PART_DRAW_BB_LOCK && part->bb_align==PART_BB_VIEW){
|
||||
VECCOPY(xvec,bb_ob->obmat[0]);
|
||||
Normalize(xvec);
|
||||
VECCOPY(yvec,bb_ob->obmat[1]);
|
||||
Normalize(yvec);
|
||||
VECCOPY(zvec,bb_ob->obmat[2]);
|
||||
Normalize(zvec);
|
||||
}
|
||||
else if(part->bb_align==PART_BB_VEL){
|
||||
float temp[3];
|
||||
VECCOPY(temp,state.vel);
|
||||
Normalize(temp);
|
||||
VECSUB(zvec,bb_ob->obmat[3],state.co);
|
||||
if(part->draw&PART_DRAW_BB_LOCK){
|
||||
float fac=-Inpf(zvec,temp);
|
||||
VECADDFAC(zvec,zvec,temp,fac);
|
||||
}
|
||||
Normalize(zvec);
|
||||
Crossf(xvec,temp,zvec);
|
||||
Normalize(xvec);
|
||||
Crossf(yvec,zvec,xvec);
|
||||
}
|
||||
else{
|
||||
VECSUB(zvec,bb_ob->obmat[3],state.co);
|
||||
if(part->draw&PART_DRAW_BB_LOCK)
|
||||
zvec[part->bb_align]=0.0f;
|
||||
Normalize(zvec);
|
||||
|
||||
if(part->bb_align<PART_BB_VIEW)
|
||||
Crossf(xvec,onevec,zvec);
|
||||
else
|
||||
Crossf(xvec,bb_ob->obmat[1],zvec);
|
||||
Normalize(xvec);
|
||||
Crossf(yvec,zvec,xvec);
|
||||
}
|
||||
|
||||
VECCOPY(vec,xvec);
|
||||
VECCOPY(vec2,yvec);
|
||||
|
||||
VecMulf(xvec,cos(part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt)*(float)M_PI));
|
||||
VecMulf(vec2,sin(part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt)*(float)M_PI));
|
||||
VECADD(xvec,xvec,vec2);
|
||||
|
||||
VecMulf(yvec,cos(part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt)*(float)M_PI));
|
||||
VecMulf(vec,-sin(part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt)*(float)M_PI));
|
||||
VECADD(yvec,yvec,vec);
|
||||
|
||||
VecMulf(xvec,pa_size);
|
||||
VecMulf(yvec,pa_size);
|
||||
|
||||
VECADDFAC(bb_center,state.co,xvec,part->bb_offset[0]);
|
||||
VECADDFAC(bb_center,bb_center,yvec,part->bb_offset[1]);
|
||||
|
||||
VECADD(vd,bb_center,xvec);
|
||||
VECADD(vd,vd,yvec); vd+=3;
|
||||
|
||||
VECSUB(vd,bb_center,xvec);
|
||||
VECADD(vd,vd,yvec); vd+=3;
|
||||
|
||||
VECSUB(vd,bb_center,xvec);
|
||||
VECSUB(vd,vd,yvec); vd+=3;
|
||||
|
||||
VECADD(vd,bb_center,xvec);
|
||||
VECSUB(vd,vd,yvec); vd+=3;
|
||||
|
||||
VECCOPY(nd, zvec); nd+=3;
|
||||
VECCOPY(nd, zvec); nd+=3;
|
||||
VECCOPY(nd, zvec); nd+=3;
|
||||
VECCOPY(nd, zvec); nd+=3;
|
||||
break;
|
||||
}
|
||||
|
||||
if(vedata){
|
||||
VECCOPY(ved,state.co);
|
||||
ved+=3;
|
||||
VECCOPY(vel,state.vel);
|
||||
VecMulf(vel,timestep);
|
||||
VECADD(ved,state.co,vel);
|
||||
ved+=3;
|
||||
}
|
||||
|
||||
if(part->draw & PART_DRAW_SIZE){
|
||||
setlinestyle(3);
|
||||
drawcircball(GL_LINE_LOOP, state.co, pa_size, imat);
|
||||
setlinestyle(0);
|
||||
}
|
||||
|
||||
totpoint++;
|
||||
}
|
||||
if(next_pa)
|
||||
continue;
|
||||
if(part->draw&PART_DRAW_NUM && !(G.f & G_RENDER_SHADOW)){
|
||||
/* in path drawing state.co is the end point */
|
||||
glRasterPos3f(state.co[0], state.co[1], state.co[2]);
|
||||
sprintf(val," %i",a);
|
||||
BMF_DrawString(G.font, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 6. */
|
||||
|
||||
glGetIntegerv(GL_POLYGON_MODE, polygonmode);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
if(draw_as != PART_DRAW_CIRC){
|
||||
if(draw_as==PART_DRAW_PATH){
|
||||
ParticleCacheKey **cache, *path;
|
||||
float *cd2=0,*cdata2=0;
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if(dt > OB_WIRE) {
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
if(part->draw&PART_DRAW_MAT_COL)
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
}
|
||||
else {
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
glDisable(GL_LIGHTING);
|
||||
UI_ThemeColor(TH_WIRE);
|
||||
}
|
||||
|
||||
if(totchild && (part->draw&PART_DRAW_PARENT)==0)
|
||||
totpart=0;
|
||||
|
||||
cache=psys->pathcache;
|
||||
for(a=0, pa=psys->particles; a<totpart; a++, pa++){
|
||||
path=cache[a];
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
|
||||
|
||||
if(dt > OB_WIRE) {
|
||||
glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
|
||||
if(part->draw&PART_DRAW_MAT_COL)
|
||||
glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
|
||||
}
|
||||
|
||||
glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
|
||||
}
|
||||
|
||||
cache=psys->childcache;
|
||||
for(a=0; a<totchild; a++){
|
||||
path=cache[a];
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
|
||||
|
||||
if(dt > OB_WIRE) {
|
||||
glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
|
||||
if(part->draw&PART_DRAW_MAT_COL)
|
||||
glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
|
||||
}
|
||||
|
||||
glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
|
||||
}
|
||||
|
||||
if(dt > OB_WIRE) {
|
||||
if(part->draw&PART_DRAW_MAT_COL)
|
||||
glDisable(GL_COLOR_ARRAY);
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
}
|
||||
|
||||
if(cdata2)
|
||||
MEM_freeN(cdata2);
|
||||
cd2=cdata2=0;
|
||||
|
||||
glLineWidth(1.0f);
|
||||
|
||||
/* draw particle edit mode key points*/
|
||||
}
|
||||
|
||||
if(draw_as!=PART_DRAW_PATH){
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
if(vdata){
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(3, GL_FLOAT, 0, vdata);
|
||||
}
|
||||
else
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if(ndata && dt>OB_WIRE){
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glNormalPointer(GL_FLOAT, 0, ndata);
|
||||
glEnable(GL_LIGHTING);
|
||||
}
|
||||
else{
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
if(cdata){
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glColorPointer(3, GL_FLOAT, 0, cdata);
|
||||
}
|
||||
|
||||
switch(draw_as){
|
||||
case PART_DRAW_AXIS:
|
||||
case PART_DRAW_CROSS:
|
||||
glDrawArrays(GL_LINES, 0, 6*totpoint);
|
||||
break;
|
||||
case PART_DRAW_LINE:
|
||||
glDrawArrays(GL_LINES, 0, 2*totpoint);
|
||||
break;
|
||||
case PART_DRAW_BB:
|
||||
if(dt<=OB_WIRE)
|
||||
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
||||
|
||||
glDrawArrays(GL_QUADS, 0, 4*totpoint);
|
||||
break;
|
||||
default:
|
||||
glDrawArrays(GL_POINTS, 0, totpoint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if(vedata){
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
cpack(0xC0C0C0);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(3, GL_FLOAT, 0, vedata);
|
||||
|
||||
glDrawArrays(GL_LINES, 0, 2*totpoint);
|
||||
}
|
||||
|
||||
glPolygonMode(GL_FRONT, polygonmode[0]);
|
||||
glPolygonMode(GL_BACK, polygonmode[1]);
|
||||
}
|
||||
|
||||
/* 7. */
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
if(states)
|
||||
MEM_freeN(states);
|
||||
if(vdata)
|
||||
MEM_freeN(vdata);
|
||||
if(vedata)
|
||||
MEM_freeN(vedata);
|
||||
if(cdata)
|
||||
MEM_freeN(cdata);
|
||||
if(ndata)
|
||||
MEM_freeN(ndata);
|
||||
|
||||
psys->flag &= ~PSYS_DRAWING;
|
||||
|
||||
if(psys->lattice){
|
||||
end_latt_deform();
|
||||
psys->lattice=0;
|
||||
}
|
||||
|
||||
wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
|
||||
wmMultMatrix(CTX_wm_window(C), ob->obmat); // bring back local matrix for dtx
|
||||
}
|
||||
|
||||
static void draw_particle_edit(const bContext *C, Scene *scene, View3D *v3d, Object *ob, ParticleSystem *psys, int dt)
|
||||
{
|
||||
ParticleEdit *edit = psys->edit;
|
||||
ParticleData *pa;
|
||||
ParticleCacheKey **path;
|
||||
ParticleEditKey *key;
|
||||
ParticleEditSettings *pset = NULL; // XXX PE_settings();
|
||||
int i, k, totpart = psys->totpart, totchild=0, timed = pset->draw_timed;
|
||||
char nosel[4], sel[4];
|
||||
float sel_col[3];
|
||||
float nosel_col[3];
|
||||
char val[32];
|
||||
|
||||
/* create path and child path cache if it doesn't exist already */
|
||||
if(psys->pathcache==0){
|
||||
// XXX PE_hide_keys_time(psys,CFRA);
|
||||
psys_cache_paths(ob,psys,CFRA,0);
|
||||
}
|
||||
if(psys->pathcache==0)
|
||||
return;
|
||||
|
||||
if(pset->flag & PE_SHOW_CHILD && psys->part->draw_as == PART_DRAW_PATH) {
|
||||
if(psys->childcache==0)
|
||||
psys_cache_child_paths(ob, psys, CFRA, 0);
|
||||
}
|
||||
else if(!(pset->flag & PE_SHOW_CHILD) && psys->childcache)
|
||||
free_child_path_cache(psys);
|
||||
|
||||
/* opengl setup */
|
||||
if((v3d->flag & V3D_ZBUF_SELECT)==0)
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
|
||||
|
||||
/* get selection theme colors */
|
||||
UI_GetThemeColor3ubv(TH_VERTEX_SELECT, sel);
|
||||
UI_GetThemeColor3ubv(TH_VERTEX, nosel);
|
||||
sel_col[0]=(float)sel[0]/255.0f;
|
||||
sel_col[1]=(float)sel[1]/255.0f;
|
||||
sel_col[2]=(float)sel[2]/255.0f;
|
||||
nosel_col[0]=(float)nosel[0]/255.0f;
|
||||
nosel_col[1]=(float)nosel[1]/255.0f;
|
||||
nosel_col[2]=(float)nosel[2]/255.0f;
|
||||
|
||||
if(psys->childcache)
|
||||
totchild = psys->totchildcache;
|
||||
|
||||
/* draw paths */
|
||||
if(timed)
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if(dt > OB_WIRE) {
|
||||
/* solid shaded with lighting */
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
|
||||
}
|
||||
else {
|
||||
/* flat wire color */
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisable(GL_LIGHTING);
|
||||
UI_ThemeColor(TH_WIRE);
|
||||
}
|
||||
|
||||
/* only draw child paths with lighting */
|
||||
if(dt > OB_WIRE)
|
||||
glEnable(GL_LIGHTING);
|
||||
|
||||
if(psys->part->draw_as == PART_DRAW_PATH) {
|
||||
for(i=0, path=psys->childcache; i<totchild; i++,path++){
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->co);
|
||||
if(dt > OB_WIRE) {
|
||||
glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel);
|
||||
glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col);
|
||||
}
|
||||
|
||||
glDrawArrays(GL_LINE_STRIP, 0, (int)(*path)->steps + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if(dt > OB_WIRE)
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
if(pset->brushtype == PE_BRUSH_WEIGHT) {
|
||||
glLineWidth(2.0f);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glDisable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
/* draw parents last without lighting */
|
||||
for(i=0, pa=psys->particles, path = psys->pathcache; i<totpart; i++, pa++, path++){
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->co);
|
||||
if(dt > OB_WIRE)
|
||||
glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel);
|
||||
if(dt > OB_WIRE || pset->brushtype == PE_BRUSH_WEIGHT)
|
||||
glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col);
|
||||
|
||||
glDrawArrays(GL_LINE_STRIP, 0, (int)(*path)->steps + 1);
|
||||
}
|
||||
|
||||
/* draw edit vertices */
|
||||
if(scene->selectmode!=SCE_SELECT_PATH){
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glDisable(GL_LIGHTING);
|
||||
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
|
||||
|
||||
if(scene->selectmode==SCE_SELECT_POINT){
|
||||
float *cd=0,*cdata=0;
|
||||
cd=cdata=MEM_callocN(edit->totkeys*(timed?4:3)*sizeof(float), "particle edit color data");
|
||||
|
||||
for(i=0, pa=psys->particles; i<totpart; i++, pa++){
|
||||
for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++){
|
||||
if(key->flag&PEK_SELECT){
|
||||
VECCOPY(cd,sel_col);
|
||||
}
|
||||
else{
|
||||
VECCOPY(cd,nosel_col);
|
||||
}
|
||||
if(timed)
|
||||
*(cd+3) = (key->flag&PEK_HIDE)?0.0f:1.0f;
|
||||
cd += (timed?4:3);
|
||||
}
|
||||
}
|
||||
cd=cdata;
|
||||
for(i=0, pa=psys->particles; i<totpart; i++, pa++){
|
||||
if((pa->flag & PARS_HIDE)==0){
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(ParticleEditKey), edit->keys[i]->world_co);
|
||||
glColorPointer((timed?4:3), GL_FLOAT, (timed?4:3)*sizeof(float), cd);
|
||||
glDrawArrays(GL_POINTS, 0, pa->totkey);
|
||||
}
|
||||
cd += (timed?4:3) * pa->totkey;
|
||||
|
||||
if((pset->flag&PE_SHOW_TIME) && (pa->flag&PARS_HIDE)==0 && !(G.f & G_RENDER_SHADOW)){
|
||||
for(k=0, key=edit->keys[i]+k; k<pa->totkey; k++, key++){
|
||||
if(key->flag & PEK_HIDE) continue;
|
||||
|
||||
glRasterPos3fv(key->world_co);
|
||||
sprintf(val," %.1f",*key->time);
|
||||
BMF_DrawString(G.font, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(cdata)
|
||||
MEM_freeN(cdata);
|
||||
cd=cdata=0;
|
||||
}
|
||||
else if(scene->selectmode == SCE_SELECT_END){
|
||||
for(i=0, pa=psys->particles; i<totpart; i++, pa++){
|
||||
if((pa->flag & PARS_HIDE)==0){
|
||||
key = edit->keys[i] + pa->totkey - 1;
|
||||
if(key->flag & PEK_SELECT)
|
||||
glColor3fv(sel_col);
|
||||
else
|
||||
glColor3fv(nosel_col);
|
||||
/* has to be like this.. otherwise selection won't work, have try glArrayElement later..*/
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3fv(key->world_co);
|
||||
glEnd();
|
||||
|
||||
if((pset->flag & PE_SHOW_TIME) && !(G.f & G_RENDER_SHADOW)){
|
||||
glRasterPos3fv(key->world_co);
|
||||
sprintf(val," %.1f",*key->time);
|
||||
BMF_DrawString(G.font, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glLineWidth(1.0f);
|
||||
|
||||
wmMultMatrix(CTX_wm_window(C), ob->obmat); // bring back local matrix for dtx
|
||||
glPointSize(1.0);
|
||||
}
|
||||
|
||||
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 || (G.f & G_HIDDENHANDLES)) return;
|
||||
|
||||
glBegin(GL_LINES);
|
||||
|
||||
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 & SELECT)==sel) {
|
||||
fp= bezt->vec[0];
|
||||
|
||||
cpack(col[bezt->h1]);
|
||||
glVertex3fv(fp);
|
||||
glVertex3fv(fp+3);
|
||||
|
||||
cpack(col[bezt->h2]);
|
||||
glVertex3fv(fp+3);
|
||||
glVertex3fv(fp+6);
|
||||
}
|
||||
else if( (bezt->f1 & SELECT)==sel) {
|
||||
fp= bezt->vec[0];
|
||||
|
||||
cpack(col[bezt->h1]);
|
||||
glVertex3fv(fp);
|
||||
glVertex3fv(fp+3);
|
||||
}
|
||||
else if( (bezt->f3 & SELECT)==sel) {
|
||||
fp= bezt->vec[1];
|
||||
|
||||
cpack(col[bezt->h2]);
|
||||
glVertex3fv(fp);
|
||||
glVertex3fv(fp+3);
|
||||
}
|
||||
}
|
||||
bezt++;
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void tekenvertsN(Nurb *nu, short sel)
|
||||
{
|
||||
BezTriple *bezt;
|
||||
BPoint *bp;
|
||||
float size;
|
||||
int a;
|
||||
|
||||
if(nu->hide) return;
|
||||
|
||||
if(sel) UI_ThemeColor(TH_VERTEX_SELECT);
|
||||
else UI_ThemeColor(TH_VERTEX);
|
||||
|
||||
size= UI_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 (G.f & G_HIDDENHANDLES) {
|
||||
if((bezt->f2 & SELECT)==sel) bglVertex3fv(bezt->vec[1]);
|
||||
} else {
|
||||
if((bezt->f1 & SELECT)==sel) bglVertex3fv(bezt->vec[0]);
|
||||
if((bezt->f2 & SELECT)==sel) bglVertex3fv(bezt->vec[1]);
|
||||
if((bezt->f3 & SELECT)==sel) bglVertex3fv(bezt->vec[2]);
|
||||
}
|
||||
}
|
||||
bezt++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
bp= nu->bp;
|
||||
a= nu->pntsu*nu->pntsv;
|
||||
while(a--) {
|
||||
if(bp->hide==0) {
|
||||
if((bp->f1 & SELECT)==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);
|
||||
}
|
||||
|
||||
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 & SELECT) && ( bp1->f1 & SELECT ) ) {
|
||||
cpack(nurbcol[5]);
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3fv(bp->vec);
|
||||
glVertex3fv(bp1->vec);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( (bp->f1 & SELECT) && ( bp1->f1 & SELECT) );
|
||||
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 & SELECT) && ( bp1->f1 & SELECT) ) {
|
||||
cpack(nurbcol[7]);
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3fv(bp->vec);
|
||||
glVertex3fv(bp1->vec);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( (bp->f1 & SELECT) && ( bp1->f1 & SELECT) );
|
||||
else {
|
||||
cpack(nurbcol[3]);
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3fv(bp->vec);
|
||||
glVertex3fv(bp1->vec);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
bp1= bp;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
nu= nu->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void drawnurb(Scene *scene, View3D *v3d, Base *base, Nurb *nurb, int dt)
|
||||
{
|
||||
Object *ob= base->object;
|
||||
Curve *cu = ob->data;
|
||||
Nurb *nu;
|
||||
BevList *bl;
|
||||
|
||||
// XXX retopo_matrix_update(v3d);
|
||||
|
||||
/* DispList */
|
||||
UI_ThemeColor(TH_WIRE);
|
||||
drawDispList(scene, v3d, base, dt);
|
||||
|
||||
if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
|
||||
|
||||
/* first non-selected handles */
|
||||
for(nu=nurb; nu; nu=nu->next) {
|
||||
if((nu->type & 7)==CU_BEZIER) {
|
||||
tekenhandlesN(nu, 0);
|
||||
}
|
||||
}
|
||||
draw_editnurb(ob, nurb, 0);
|
||||
draw_editnurb(ob, nurb, 1);
|
||||
/* selected handles */
|
||||
for(nu=nurb; nu; nu=nu->next) {
|
||||
if((nu->type & 7)==1) tekenhandlesN(nu, 1);
|
||||
tekenvertsN(nu, 0);
|
||||
}
|
||||
|
||||
if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
|
||||
|
||||
/* direction vectors for 3d curve paths
|
||||
when at its lowest, dont render normals */
|
||||
if(cu->flag & CU_3D && scene->editbutsize > 0.0015) {
|
||||
UI_ThemeColor(TH_WIRE);
|
||||
for (bl=cu->bev.first,nu=nurb; nu && bl; bl=bl->next,nu=nu->next) {
|
||||
BevPoint *bevp= (BevPoint *)(bl+1);
|
||||
int nr= bl->nr;
|
||||
int skip= nu->resolu/16;
|
||||
|
||||
while (nr-->0) { /* accounts for empty bevel lists */
|
||||
float fac= bevp->radius * scene->editbutsize;
|
||||
float ox,oy,oz; // Offset perpendicular to the curve
|
||||
float dx,dy,dz; // Delta along the curve
|
||||
|
||||
ox = fac*bevp->mat[0][0];
|
||||
oy = fac*bevp->mat[0][1];
|
||||
oz = fac*bevp->mat[0][2];
|
||||
|
||||
dx = fac*bevp->mat[2][0];
|
||||
dy = fac*bevp->mat[2][1];
|
||||
dz = fac*bevp->mat[2][2];
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3f(bevp->x - ox - dx, bevp->y - oy - dy, bevp->z - oz - dz);
|
||||
glVertex3f(bevp->x, bevp->y, bevp->z);
|
||||
glVertex3f(bevp->x + ox - dx, bevp->y + oy - dy, bevp->z + oz - dz);
|
||||
glEnd();
|
||||
|
||||
bevp += skip+1;
|
||||
nr -= skip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
|
||||
|
||||
for(nu=nurb; nu; nu=nu->next) {
|
||||
tekenvertsN(nu, 1);
|
||||
}
|
||||
|
||||
if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
/* draw a sphere for use as an empty drawtype */
|
||||
static void draw_empty_sphere (float size)
|
||||
{
|
||||
float cent=0;
|
||||
GLUquadricObj *qobj = gluNewQuadric();
|
||||
gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(cent, cent, cent);
|
||||
glScalef(size, size, size);
|
||||
gluSphere(qobj, 1.0, 8, 5);
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
gluDeleteQuadric(qobj);
|
||||
}
|
||||
|
||||
/* draw a cone for use as an empty drawtype */
|
||||
static void draw_empty_cone (float size)
|
||||
{
|
||||
float cent=0;
|
||||
float radius;
|
||||
GLUquadricObj *qobj = gluNewQuadric();
|
||||
gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
|
||||
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
radius = size;
|
||||
glTranslatef(cent,cent, cent);
|
||||
glScalef(radius, 2.0*size, radius);
|
||||
glRotatef(-90., 1.0, 0.0, 0.0);
|
||||
gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
gluDeleteQuadric(qobj);
|
||||
}
|
||||
|
||||
/* draw points on curve speed handles */
|
||||
static void curve_draw_speed(Scene *scene, Object *ob)
|
||||
{
|
||||
Curve *cu= ob->data;
|
||||
IpoCurve *icu;
|
||||
BezTriple *bezt;
|
||||
float loc[4], dir[3];
|
||||
int a;
|
||||
|
||||
if(cu->ipo==NULL)
|
||||
return;
|
||||
|
||||
icu= cu->ipo->curve.first;
|
||||
if(icu==NULL || icu->totvert<2)
|
||||
return;
|
||||
|
||||
glPointSize( UI_GetThemeValuef(TH_VERTEX_SIZE) );
|
||||
bglBegin(GL_POINTS);
|
||||
|
||||
for(a=0, bezt= icu->bezt; a<icu->totvert; a++, bezt++) {
|
||||
if( where_on_path(ob, bezt->vec[1][1], loc, dir)) {
|
||||
UI_ThemeColor((bezt->f2 & SELECT) && ob==OBACT?TH_VERTEX_SELECT:TH_VERTEX);
|
||||
bglVertex3fv(loc);
|
||||
}
|
||||
}
|
||||
|
||||
glPointSize(1.0);
|
||||
bglEnd();
|
||||
}
|
||||
|
||||
|
||||
static void tekentextcurs(void)
|
||||
{
|
||||
cpack(0);
|
||||
|
||||
set_inverted_drawing(1);
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2fv(G.textcurs[0]);
|
||||
glVertex2fv(G.textcurs[1]);
|
||||
glVertex2fv(G.textcurs[2]);
|
||||
glVertex2fv(G.textcurs[3]);
|
||||
glEnd();
|
||||
set_inverted_drawing(0);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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] + *(sinval+a+start) * (vx[0] * (float)a/(float)tot) + *(cosval+a+start) * (vy[0] * (float)a/(float)tot);
|
||||
vec[1]= cent[1] + *(sinval+a+start) * (vx[1] * (float)a/(float)tot) + *(cosval+a+start) * (vy[1] * (float)a/(float)tot);
|
||||
vec[2]= cent[2] + *(sinval+a+start) * (vx[2] * (float)a/(float)tot) + *(cosval+a+start) * (vy[2] * (float)a/(float)tot);
|
||||
glVertex3fv(vec);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
else {
|
||||
a=0;
|
||||
vec[0]= cent[0] + *(sinval+a+start) * (vx[0] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[0] * (float)(-a+31)/(float)tot);
|
||||
vec[1]= cent[1] + *(sinval+a+start) * (vx[1] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[1] * (float)(-a+31)/(float)tot);
|
||||
vec[2]= cent[2] + *(sinval+a+start) * (vx[2] * (float)(-a+31)/(float)tot) + *(cosval+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] + *(sinval+a+start) * (vx[0] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[0] * (float)(-a+31)/(float)tot);
|
||||
vec[1]= cent[1] + *(sinval+a+start) * (vx[1] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[1] * (float)(-a+31)/(float)tot);
|
||||
vec[2]= cent[2] + *(sinval+a+start) * (vx[2] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[2] * (float)(-a+31)/(float)tot);
|
||||
glVertex3fv(vec);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* draws a circle on x-z plane given the scaling of the circle, assuming that
|
||||
* all required matrices have been set (used for drawing empties)
|
||||
*/
|
||||
static void drawcircle_size(float size)
|
||||
{
|
||||
float x, y;
|
||||
short degrees;
|
||||
|
||||
glBegin(GL_LINE_LOOP);
|
||||
|
||||
/* coordinates are: cos(degrees*11.25)=x, sin(degrees*11.25)=y, 0.0f=z */
|
||||
for (degrees=0; degrees<32; degrees++) {
|
||||
x= *(cosval + degrees);
|
||||
y= *(sinval + degrees);
|
||||
|
||||
glVertex3f(x*size, 0.0f, y*size);
|
||||
}
|
||||
|
||||
glEnd();
|
||||
|
||||
}
|
||||
|
||||
/* needs fixing if non-identity matrice used */
|
||||
static void drawtube(float *vec, float radius, float height, float tmat[][4])
|
||||
{
|
||||
float cur[3];
|
||||
drawcircball(GL_LINE_LOOP, vec, radius, tmat);
|
||||
|
||||
VecCopyf(cur,vec);
|
||||
cur[2]+=height;
|
||||
|
||||
drawcircball(GL_LINE_LOOP, cur, radius, tmat);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(vec[0]+radius,vec[1],vec[2]);
|
||||
glVertex3f(cur[0]+radius,cur[1],cur[2]);
|
||||
glVertex3f(vec[0]-radius,vec[1],vec[2]);
|
||||
glVertex3f(cur[0]-radius,cur[1],cur[2]);
|
||||
glVertex3f(vec[0],vec[1]+radius,vec[2]);
|
||||
glVertex3f(cur[0],cur[1]+radius,cur[2]);
|
||||
glVertex3f(vec[0],vec[1]-radius,vec[2]);
|
||||
glVertex3f(cur[0],cur[1]-radius,cur[2]);
|
||||
glEnd();
|
||||
}
|
||||
/* needs fixing if non-identity matrice used */
|
||||
static void drawcone(float *vec, float radius, float height, float tmat[][4])
|
||||
{
|
||||
float cur[3];
|
||||
|
||||
VecCopyf(cur,vec);
|
||||
cur[2]+=height;
|
||||
|
||||
drawcircball(GL_LINE_LOOP, cur, radius, tmat);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(vec[0],vec[1],vec[2]);
|
||||
glVertex3f(cur[0]+radius,cur[1],cur[2]);
|
||||
glVertex3f(vec[0],vec[1],vec[2]);
|
||||
glVertex3f(cur[0]-radius,cur[1],cur[2]);
|
||||
glVertex3f(vec[0],vec[1],vec[2]);
|
||||
glVertex3f(cur[0],cur[1]+radius,cur[2]);
|
||||
glVertex3f(vec[0],vec[1],vec[2]);
|
||||
glVertex3f(cur[0],cur[1]-radius,cur[2]);
|
||||
glEnd();
|
||||
}
|
||||
/* return 1 if nothing was drawn */
|
||||
static int drawmball(const bContext *C, Scene *scene, View3D *v3d, Base *base, int dt)
|
||||
{
|
||||
Object *ob= base->object;
|
||||
MetaBall *mb;
|
||||
MetaElem *ml;
|
||||
float imat[4][4], tmat[4][4];
|
||||
int code= 1;
|
||||
|
||||
mb= ob->data;
|
||||
|
||||
if(ob==G.obedit) {
|
||||
UI_ThemeColor(TH_WIRE);
|
||||
if((G.f & G_PICKSEL)==0 ) drawDispList(scene, v3d, base, dt);
|
||||
ml= editelems.first;
|
||||
}
|
||||
else {
|
||||
if((base->flag & OB_FROMDUPLI)==0)
|
||||
drawDispList(scene, v3d, base, dt);
|
||||
ml= mb->elems.first;
|
||||
}
|
||||
|
||||
if(ml==NULL) return 1;
|
||||
|
||||
/* in case solid draw, reset wire colors */
|
||||
if(ob!=G.obedit && (ob->flag & SELECT)) {
|
||||
if(ob==OBACT) UI_ThemeColor(TH_ACTIVE);
|
||||
else UI_ThemeColor(TH_SELECT);
|
||||
}
|
||||
else UI_ThemeColor(TH_WIRE);
|
||||
|
||||
wmGetMatrix(CTX_wm_window(C), tmat);
|
||||
Mat4Invert(imat, tmat);
|
||||
Normalize(imat[0]);
|
||||
Normalize(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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void draw_forcefield(const bContext *C, Scene *scene, Object *ob)
|
||||
{
|
||||
PartDeflect *pd= ob->pd;
|
||||
float imat[4][4], tmat[4][4];
|
||||
float vec[3]= {0.0, 0.0, 0.0};
|
||||
int curcol;
|
||||
float size;
|
||||
|
||||
if(G.f & G_RENDER_SHADOW)
|
||||
return;
|
||||
|
||||
if(ob!=G.obedit && (ob->flag & SELECT)) {
|
||||
if(ob==OBACT) curcol= TH_ACTIVE;
|
||||
else curcol= TH_SELECT;
|
||||
}
|
||||
else curcol= TH_WIRE;
|
||||
|
||||
/* scale size of circle etc with the empty drawsize */
|
||||
if (ob->type == OB_EMPTY) size = ob->empty_drawsize;
|
||||
else size = 1.0;
|
||||
|
||||
/* calculus here, is reused in PFIELD_FORCE */
|
||||
wmGetMatrix(CTX_wm_window(C), tmat);
|
||||
Mat4Invert(imat, tmat);
|
||||
// Normalize(imat[0]); // we don't do this because field doesnt scale either... apart from wind!
|
||||
// Normalize(imat[1]);
|
||||
|
||||
if (pd->forcefield == PFIELD_WIND) {
|
||||
float force_val;
|
||||
|
||||
Mat4One(tmat);
|
||||
UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
|
||||
|
||||
if (has_ipo_code(ob->ipo, OB_PD_FSTR))
|
||||
force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra);
|
||||
else
|
||||
force_val = pd->f_strength;
|
||||
force_val*= 0.1;
|
||||
drawcircball(GL_LINE_LOOP, vec, size, tmat);
|
||||
vec[2]= 0.5*force_val;
|
||||
drawcircball(GL_LINE_LOOP, vec, size, tmat);
|
||||
vec[2]= 1.0*force_val;
|
||||
drawcircball(GL_LINE_LOOP, vec, size, tmat);
|
||||
vec[2]= 1.5*force_val;
|
||||
drawcircball(GL_LINE_LOOP, vec, size, tmat);
|
||||
vec[2] = 0; /* reset vec for max dist circle */
|
||||
|
||||
}
|
||||
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, scene->r.cfra);
|
||||
else
|
||||
ffall_val = pd->f_power;
|
||||
|
||||
UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
|
||||
drawcircball(GL_LINE_LOOP, vec, size, imat);
|
||||
UI_ThemeColorBlend(curcol, TH_BACK, 0.9 - 0.4 / pow(1.5, (double)ffall_val));
|
||||
drawcircball(GL_LINE_LOOP, vec, size*1.5, imat);
|
||||
UI_ThemeColorBlend(curcol, TH_BACK, 0.9 - 0.4 / pow(2.0, (double)ffall_val));
|
||||
drawcircball(GL_LINE_LOOP, vec, size*2.0, imat);
|
||||
}
|
||||
else if (pd->forcefield == PFIELD_VORTEX) {
|
||||
float ffall_val, force_val;
|
||||
|
||||
Mat4One(tmat);
|
||||
if (has_ipo_code(ob->ipo, OB_PD_FFALL))
|
||||
ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, 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, scene->r.cfra);
|
||||
else
|
||||
force_val = pd->f_strength;
|
||||
|
||||
UI_ThemeColorBlend(curcol, TH_BACK, 0.7);
|
||||
if (force_val < 0) {
|
||||
drawspiral(vec, size*1.0, tmat, 1);
|
||||
drawspiral(vec, size*1.0, tmat, 16);
|
||||
}
|
||||
else {
|
||||
drawspiral(vec, size*1.0, tmat, -1);
|
||||
drawspiral(vec, size*1.0, tmat, -16);
|
||||
}
|
||||
}
|
||||
else if (pd->forcefield == PFIELD_GUIDE && ob->type==OB_CURVE) {
|
||||
Curve *cu= ob->data;
|
||||
if((cu->flag & CU_PATH) && cu->path && cu->path->data) {
|
||||
float mindist, guidevec1[4], guidevec2[3];
|
||||
|
||||
if (has_ipo_code(ob->ipo, OB_PD_FSTR))
|
||||
mindist = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra);
|
||||
else
|
||||
mindist = pd->f_strength;
|
||||
|
||||
/*path end*/
|
||||
setlinestyle(3);
|
||||
where_on_path(ob, 1.0f, guidevec1, guidevec2);
|
||||
UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
|
||||
drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
|
||||
|
||||
/*path beginning*/
|
||||
setlinestyle(0);
|
||||
where_on_path(ob, 0.0f, guidevec1, guidevec2);
|
||||
UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
|
||||
drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
|
||||
|
||||
VECCOPY(vec, guidevec1); /* max center */
|
||||
}
|
||||
}
|
||||
|
||||
setlinestyle(3);
|
||||
UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
|
||||
|
||||
if(pd->falloff==PFIELD_FALL_SPHERE){
|
||||
/* as last, guide curve alters it */
|
||||
if(pd->flag & PFIELD_USEMAX)
|
||||
drawcircball(GL_LINE_LOOP, vec, pd->maxdist, imat);
|
||||
|
||||
if(pd->flag & PFIELD_USEMIN)
|
||||
drawcircball(GL_LINE_LOOP, vec, pd->mindist, imat);
|
||||
}
|
||||
else if(pd->falloff==PFIELD_FALL_TUBE){
|
||||
float radius,distance;
|
||||
|
||||
Mat4One(tmat);
|
||||
|
||||
vec[0]=vec[1]=0.0f;
|
||||
radius=(pd->flag&PFIELD_USEMAXR)?pd->maxrad:1.0f;
|
||||
distance=(pd->flag&PFIELD_USEMAX)?pd->maxdist:0.0f;
|
||||
vec[2]=distance;
|
||||
distance=(pd->flag&PFIELD_POSZ)?-distance:-2.0f*distance;
|
||||
|
||||
if(pd->flag & (PFIELD_USEMAX|PFIELD_USEMAXR))
|
||||
drawtube(vec,radius,distance,tmat);
|
||||
|
||||
radius=(pd->flag&PFIELD_USEMINR)?pd->minrad:1.0f;
|
||||
distance=(pd->flag&PFIELD_USEMIN)?pd->mindist:0.0f;
|
||||
vec[2]=distance;
|
||||
distance=(pd->flag&PFIELD_POSZ)?-distance:-2.0f*distance;
|
||||
|
||||
if(pd->flag & (PFIELD_USEMIN|PFIELD_USEMINR))
|
||||
drawtube(vec,radius,distance,tmat);
|
||||
}
|
||||
else if(pd->falloff==PFIELD_FALL_CONE){
|
||||
float radius,distance;
|
||||
|
||||
Mat4One(tmat);
|
||||
|
||||
radius=(pd->flag&PFIELD_USEMAXR)?pd->maxrad:1.0f;
|
||||
radius*=(float)M_PI/180.0f;
|
||||
distance=(pd->flag&PFIELD_USEMAX)?pd->maxdist:0.0f;
|
||||
|
||||
if(pd->flag & (PFIELD_USEMAX|PFIELD_USEMAXR)){
|
||||
drawcone(vec,distance*sin(radius),distance*cos(radius),tmat);
|
||||
if((pd->flag & PFIELD_POSZ)==0)
|
||||
drawcone(vec,distance*sin(radius),-distance*cos(radius),tmat);
|
||||
}
|
||||
|
||||
radius=(pd->flag&PFIELD_USEMINR)?pd->minrad:1.0f;
|
||||
radius*=(float)M_PI/180.0f;
|
||||
distance=(pd->flag&PFIELD_USEMIN)?pd->mindist:0.0f;
|
||||
|
||||
if(pd->flag & (PFIELD_USEMIN|PFIELD_USEMINR)){
|
||||
drawcone(vec,distance*sin(radius),distance*cos(radius),tmat);
|
||||
if((pd->flag & PFIELD_POSZ)==0)
|
||||
drawcone(vec,distance*sin(radius),-distance*cos(radius),tmat);
|
||||
}
|
||||
}
|
||||
setlinestyle(0);
|
||||
}
|
||||
|
||||
static void draw_box(float vec[8][3])
|
||||
{
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3fv(vec[0]); glVertex3fv(vec[1]);glVertex3fv(vec[2]); glVertex3fv(vec[3]);
|
||||
glVertex3fv(vec[0]); glVertex3fv(vec[4]);glVertex3fv(vec[5]); glVertex3fv(vec[6]);
|
||||
glVertex3fv(vec[7]); glVertex3fv(vec[4]);
|
||||
glEnd();
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex3fv(vec[1]); glVertex3fv(vec[5]);
|
||||
glVertex3fv(vec[2]); glVertex3fv(vec[6]);
|
||||
glVertex3fv(vec[3]); glVertex3fv(vec[7]);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
/* uses boundbox, function used by Ketsji */
|
||||
void get_local_bounds(Object *ob, float *center, float *size)
|
||||
{
|
||||
BoundBox *bb= object_get_boundbox(ob);
|
||||
|
||||
if(bb==NULL) {
|
||||
center[0]= center[1]= center[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]);
|
||||
|
||||
center[0]= (bb->vec[0][0] + bb->vec[4][0])/2.0;
|
||||
center[1]= (bb->vec[0][1] + bb->vec[2][1])/2.0;
|
||||
center[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_get_bb(ob);
|
||||
}
|
||||
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==0) {
|
||||
makeDispListMBall(ob);
|
||||
bb= ob->bb;
|
||||
}
|
||||
}
|
||||
else {
|
||||
drawcube();
|
||||
return;
|
||||
}
|
||||
|
||||
if(bb==0) return;
|
||||
|
||||
if(ob->boundtype==OB_BOUND_BOX) draw_box(bb->vec);
|
||||
else draw_bb_quadric(bb, ob->boundtype);
|
||||
|
||||
}
|
||||
|
||||
static void drawtexspace(Object *ob)
|
||||
{
|
||||
float vec[8][3], loc[3], size[3];
|
||||
|
||||
if(ob->type==OB_MESH) {
|
||||
mesh_get_texspace(ob->data, loc, NULL, size);
|
||||
}
|
||||
else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
|
||||
Curve *cu= ob->data;
|
||||
VECCOPY(size, cu->size);
|
||||
VECCOPY(loc, cu->loc);
|
||||
}
|
||||
else if(ob->type==OB_MBALL) {
|
||||
MetaBall *mb= ob->data;
|
||||
VECCOPY(size, mb->size);
|
||||
VECCOPY(loc, mb->loc);
|
||||
}
|
||||
else return;
|
||||
|
||||
vec[0][0]=vec[1][0]=vec[2][0]=vec[3][0]= loc[0]-size[0];
|
||||
vec[4][0]=vec[5][0]=vec[6][0]=vec[7][0]= loc[0]+size[0];
|
||||
|
||||
vec[0][1]=vec[1][1]=vec[4][1]=vec[5][1]= loc[1]-size[1];
|
||||
vec[2][1]=vec[3][1]=vec[6][1]=vec[7][1]= loc[1]+size[1];
|
||||
|
||||
vec[0][2]=vec[3][2]=vec[4][2]=vec[7][2]= loc[2]-size[2];
|
||||
vec[1][2]=vec[2][2]=vec[5][2]=vec[6][2]= loc[2]+size[2];
|
||||
|
||||
setlinestyle(2);
|
||||
|
||||
draw_box(vec);
|
||||
|
||||
setlinestyle(0);
|
||||
}
|
||||
|
||||
/* draws wire outline */
|
||||
static void drawSolidSelect(View3D *v3d, Base *base)
|
||||
{
|
||||
Object *ob= base->object;
|
||||
|
||||
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(v3d, ob->obmat, cu->bb)) {
|
||||
draw_index_wire= 0;
|
||||
drawDispListwire(&cu->disp);
|
||||
draw_index_wire= 1;
|
||||
}
|
||||
} else if (ob->type==OB_MBALL) {
|
||||
if((base->flag & OB_FROMDUPLI)==0)
|
||||
drawDispListwire(&ob->disp);
|
||||
}
|
||||
else if(ob->type==OB_ARMATURE) {
|
||||
if(!(ob->flag & OB_POSEMODE))
|
||||
draw_armature(base, OB_WIRE, 0);
|
||||
}
|
||||
|
||||
glLineWidth(1.0);
|
||||
glDepthMask(1);
|
||||
}
|
||||
|
||||
static void drawWireExtra(Scene *scene, View3D *v3d, Object *ob)
|
||||
{
|
||||
if(ob!=G.obedit && (ob->flag & SELECT)) {
|
||||
if(ob==OBACT) {
|
||||
if(ob->flag & OB_FROMGROUP) UI_ThemeColor(TH_GROUP_ACTIVE);
|
||||
else UI_ThemeColor(TH_ACTIVE);
|
||||
}
|
||||
else if(ob->flag & OB_FROMGROUP)
|
||||
UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
|
||||
else
|
||||
UI_ThemeColor(TH_SELECT);
|
||||
}
|
||||
else {
|
||||
if(ob->flag & OB_FROMGROUP)
|
||||
UI_ThemeColor(TH_GROUP);
|
||||
else {
|
||||
if(ob->dtx & OB_DRAWWIRE) {
|
||||
glColor3ub(80,80,80);
|
||||
} else {
|
||||
UI_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(v3d, 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)
|
||||
{
|
||||
ModifierData *md;
|
||||
float vec[3];
|
||||
|
||||
for (md=ob->modifiers.first; md; md=md->next) {
|
||||
if (md->type==eModifierType_Hook) {
|
||||
HookModifierData *hmd = (HookModifierData*) md;
|
||||
|
||||
VecMat4MulVecfl(vec, ob->obmat, hmd->cent);
|
||||
|
||||
if(hmd->object) {
|
||||
setlinestyle(3);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3fv(hmd->object->obmat[3]);
|
||||
glVertex3fv(vec);
|
||||
glEnd();
|
||||
setlinestyle(0);
|
||||
}
|
||||
|
||||
glPointSize(3.0);
|
||||
bglBegin(GL_POINTS);
|
||||
bglVertex3fv(vec);
|
||||
bglEnd();
|
||||
glPointSize(1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//<rcruiz>
|
||||
void drawRBpivot(bRigidBodyJointConstraint *data)
|
||||
{
|
||||
float radsPerDeg = 6.283185307179586232f / 360.f;
|
||||
int axis;
|
||||
float v1[3]= {data->pivX, data->pivY, data->pivZ};
|
||||
float eu[3]= {radsPerDeg*data->axX, radsPerDeg*data->axY, radsPerDeg*data->axZ};
|
||||
float mat[4][4];
|
||||
|
||||
if(G.f & G_RENDER_SHADOW)
|
||||
return;
|
||||
|
||||
EulToMat4(eu,mat);
|
||||
glLineWidth (4.0f);
|
||||
setlinestyle(2);
|
||||
for (axis=0; axis<3; axis++) {
|
||||
float dir[3] = {0,0,0};
|
||||
float v[3]= {data->pivX, data->pivY, data->pivZ};
|
||||
|
||||
dir[axis] = 1.f;
|
||||
glBegin(GL_LINES);
|
||||
Mat4MulVecfl(mat,dir);
|
||||
v[0] += dir[0];
|
||||
v[1] += dir[1];
|
||||
v[2] += dir[2];
|
||||
glVertex3fv(v1);
|
||||
glVertex3fv(v);
|
||||
glEnd();
|
||||
glRasterPos3fv(v);
|
||||
if (axis==0)
|
||||
BMF_DrawString(G.font, "px");
|
||||
else if (axis==1)
|
||||
BMF_DrawString(G.font, "py");
|
||||
else
|
||||
BMF_DrawString(G.font, "pz");
|
||||
}
|
||||
glLineWidth (1.0f);
|
||||
setlinestyle(0);
|
||||
}
|
||||
|
||||
/* flag can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET */
|
||||
void draw_object(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
|
||||
{
|
||||
static int warning_recursive= 0;
|
||||
Object *ob;
|
||||
Curve *cu;
|
||||
float cfraont;
|
||||
float vec1[3], vec2[3];
|
||||
unsigned int col=0;
|
||||
int sel, drawtype, colindex= 0, ipoflag;
|
||||
int i, selstart, selend, empty_object=0;
|
||||
short dt, dtx, zbufoff= 0;
|
||||
|
||||
/* only once set now, will be removed too, should become a global standard */
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
ob= base->object;
|
||||
|
||||
if (ob!=G.obedit) {
|
||||
if (ob->restrictflag & OB_RESTRICT_VIEW)
|
||||
return;
|
||||
}
|
||||
|
||||
/* xray delay? */
|
||||
if((flag & DRAW_PICKING)==0 && (base->flag & OB_FROMDUPLI)==0) {
|
||||
/* don't do xray in particle mode, need the z-buffer */
|
||||
if(!(G.f & G_PARTICLEEDIT)) {
|
||||
/* xray and transp are set when it is drawing the 2nd/3rd pass */
|
||||
if(!v3d->xray && !v3d->transp && (ob->dtx & OB_DRAWXRAY)) {
|
||||
add_view3d_after(v3d, base, V3D_XRAY, flag);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* draw keys? */
|
||||
if(base==(scene->basact) || (base->flag & (SELECT+BA_WAS_SEL))) {
|
||||
if(flag==0 && warning_recursive==0 && ob!=G.obedit) {
|
||||
if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
|
||||
ListBase elems;
|
||||
CfraElem *ce;
|
||||
float temp[7][3];
|
||||
|
||||
warning_recursive= 1;
|
||||
|
||||
elems.first= elems.last= 0;
|
||||
// warning: no longer checks for certain ob-keys only... (so does this need to use the proper ipokeys then?)
|
||||
make_cfra_list(ob->ipo, &elems);
|
||||
|
||||
cfraont= (scene->r.cfra);
|
||||
drawtype= v3d->drawtype;
|
||||
if(drawtype>OB_WIRE) v3d->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) {
|
||||
(scene->r.cfra)= ce->cfra/scene->r.framelen;
|
||||
|
||||
base->flag= 0;
|
||||
|
||||
where_is_object_time(ob, (scene->r.cfra));
|
||||
draw_object(C, scene, ar, v3d, base, 0);
|
||||
}
|
||||
ce= ce->next;
|
||||
}
|
||||
}
|
||||
|
||||
ce= elems.first;
|
||||
while(ce) {
|
||||
if(ce->sel) {
|
||||
(scene->r.cfra)= ce->cfra/scene->r.framelen;
|
||||
|
||||
base->flag= SELECT;
|
||||
|
||||
where_is_object_time(ob, (scene->r.cfra));
|
||||
draw_object(C, scene, ar, v3d, base, 0);
|
||||
}
|
||||
ce= ce->next;
|
||||
}
|
||||
|
||||
set_no_parent_ipo(0);
|
||||
disable_speed_curve(0);
|
||||
|
||||
base->flag= sel;
|
||||
ob->ipoflag= ipoflag;
|
||||
|
||||
/* restore icu->curval */
|
||||
(scene->r.cfra)= cfraont;
|
||||
|
||||
memcpy(&ob->loc, temp, 7*3*sizeof(float));
|
||||
where_is_object(ob);
|
||||
v3d->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_(scene->r.cfra)) where_is_object(ob); */
|
||||
|
||||
wmMultMatrix(CTX_wm_window(C), ob->obmat);
|
||||
|
||||
/* which wire color */
|
||||
if((flag & DRAW_CONSTCOLOR) == 0) {
|
||||
project_short(ar, v3d, ob->obmat[3], &base->sx);
|
||||
|
||||
if((G.moving & G_TRANSFORM_OBJ) && (base->flag & (SELECT+BA_WAS_SEL))) UI_ThemeColor(TH_TRANSFORM);
|
||||
else {
|
||||
|
||||
if(ob->type==OB_LAMP) UI_ThemeColor(TH_LAMP);
|
||||
else UI_ThemeColor(TH_WIRE);
|
||||
|
||||
if((scene->basact)==base) {
|
||||
if(base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_ACTIVE);
|
||||
}
|
||||
else {
|
||||
if(base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_SELECT);
|
||||
}
|
||||
|
||||
// no theme yet
|
||||
if(ob->id.lib) {
|
||||
if(base->flag & (SELECT+BA_WAS_SEL)) colindex = 4;
|
||||
else colindex = 3;
|
||||
}
|
||||
else if(warning_recursive==1) {
|
||||
if(base->flag & (SELECT+BA_WAS_SEL)) {
|
||||
if(scene->basact==base) colindex = 8;
|
||||
else colindex= 7;
|
||||
}
|
||||
else colindex = 6;
|
||||
}
|
||||
else if(ob->flag & OB_FROMGROUP) {
|
||||
if(base->flag & (SELECT+BA_WAS_SEL)) {
|
||||
if(scene->basact==base) UI_ThemeColor(TH_GROUP_ACTIVE);
|
||||
else UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
|
||||
}
|
||||
else UI_ThemeColor(TH_GROUP);
|
||||
colindex= 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(colindex) {
|
||||
col= colortab[colindex];
|
||||
cpack(col);
|
||||
}
|
||||
}
|
||||
|
||||
/* maximum drawtype */
|
||||
dt= MIN2(v3d->drawtype, ob->dt);
|
||||
if(v3d->zbuf==0 && dt>OB_WIRE) dt= OB_WIRE;
|
||||
dtx= 0;
|
||||
|
||||
/* faceselect exception: also draw solid when dt==wire, except in editmode */
|
||||
if(ob==OBACT && (G.f & (G_VERTEXPAINT+G_TEXTUREPAINT+G_WEIGHTPAINT))) {
|
||||
if(ob->type==OB_MESH) {
|
||||
|
||||
if(ob==G.obedit);
|
||||
else {
|
||||
if(dt<OB_SOLID)
|
||||
zbufoff= 1;
|
||||
|
||||
dt= OB_SHADED;
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(dt<OB_SOLID) {
|
||||
dt= OB_SOLID;
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
zbufoff= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* draw-extra supported for boundbox drawmode too */
|
||||
if(dt>=OB_BOUNDBOX ) {
|
||||
|
||||
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((v3d->flag & V3D_SELECT_OUTLINE) && ob->type!=OB_MESH) {
|
||||
if(dt>OB_WIRE && dt<OB_TEXTURE && ob!=G.obedit && (flag && DRAW_SCENESET)==0) {
|
||||
if (!(ob->dtx&OB_DRAWWIRE) && (ob->flag&SELECT) && !(flag&DRAW_PICKING)) {
|
||||
drawSolidSelect(v3d, base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch( ob->type) {
|
||||
case OB_MESH:
|
||||
if (!(base->flag&OB_RADIO)) {
|
||||
empty_object= draw_mesh_object(scene, v3d, base, dt, flag);
|
||||
if(flag!=DRAW_CONSTCOLOR) dtx &= ~OB_DRAWWIRE; // mesh draws wire itself
|
||||
}
|
||||
|
||||
break;
|
||||
case OB_FONT:
|
||||
cu= ob->data;
|
||||
if (cu->disp.first==NULL) makeDispListCurveTypes(ob, 0);
|
||||
if(ob==G.obedit) {
|
||||
tekentextcurs();
|
||||
|
||||
if (cu->flag & CU_FAST) {
|
||||
cpack(0xFFFFFF);
|
||||
set_inverted_drawing(1);
|
||||
drawDispList(scene, v3d, base, OB_WIRE);
|
||||
set_inverted_drawing(0);
|
||||
} else {
|
||||
drawDispList(scene, v3d, base, dt);
|
||||
}
|
||||
|
||||
if (cu->linewidth != 0.0) {
|
||||
cpack(0xff44ff);
|
||||
UI_ThemeColor(TH_WIRE);
|
||||
VECCOPY(vec1, ob->orig);
|
||||
VECCOPY(vec2, ob->orig);
|
||||
vec1[0] += cu->linewidth;
|
||||
vec2[0] += cu->linewidth;
|
||||
vec1[1] += cu->linedist * cu->fsize;
|
||||
vec2[1] -= cu->lines * cu->linedist * cu->fsize;
|
||||
setlinestyle(3);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex2fv(vec1);
|
||||
glVertex2fv(vec2);
|
||||
glEnd();
|
||||
setlinestyle(0);
|
||||
}
|
||||
|
||||
setlinestyle(3);
|
||||
for (i=0; i<cu->totbox; i++) {
|
||||
if (cu->tb[i].w != 0.0) {
|
||||
if (i == (cu->actbox-1))
|
||||
UI_ThemeColor(TH_ACTIVE);
|
||||
else
|
||||
UI_ThemeColor(TH_WIRE);
|
||||
vec1[0] = cu->tb[i].x;
|
||||
vec1[1] = cu->tb[i].y + cu->fsize;
|
||||
vec1[2] = 0.001;
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex3fv(vec1);
|
||||
vec1[0] += cu->tb[i].w;
|
||||
glVertex3fv(vec1);
|
||||
vec1[1] -= cu->tb[i].h;
|
||||
glVertex3fv(vec1);
|
||||
vec1[0] -= cu->tb[i].w;
|
||||
glVertex3fv(vec1);
|
||||
vec1[1] += cu->tb[i].h;
|
||||
glVertex3fv(vec1);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
setlinestyle(0);
|
||||
|
||||
|
||||
if (getselection(&selstart, &selend) && selboxes) {
|
||||
float selboxw;
|
||||
|
||||
cpack(0xffffff);
|
||||
set_inverted_drawing(1);
|
||||
for (i=0; i<(selend-selstart+1); i++) {
|
||||
SelBox *sb = &(selboxes[i]);
|
||||
|
||||
if (i<(selend-selstart)) {
|
||||
if (selboxes[i+1].y == sb->y)
|
||||
selboxw= selboxes[i+1].x - sb->x;
|
||||
else
|
||||
selboxw= sb->w;
|
||||
}
|
||||
else {
|
||||
selboxw= sb->w;
|
||||
}
|
||||
glBegin(GL_QUADS);
|
||||
glVertex3f(sb->x, sb->y, 0.001);
|
||||
glVertex3f(sb->x+selboxw, sb->y, 0.001);
|
||||
glVertex3f(sb->x+selboxw, sb->y+sb->h, 0.001);
|
||||
glVertex3f(sb->x, sb->y+sb->h, 0.001);
|
||||
glEnd();
|
||||
}
|
||||
set_inverted_drawing(0);
|
||||
}
|
||||
}
|
||||
else if(dt==OB_BOUNDBOX)
|
||||
draw_bounding_volume(ob);
|
||||
else if(boundbox_clip(v3d, ob->obmat, cu->bb))
|
||||
empty_object= drawDispList(scene, v3d, base, dt);
|
||||
|
||||
break;
|
||||
case OB_CURVE:
|
||||
case OB_SURF:
|
||||
cu= ob->data;
|
||||
/* still needed for curves hidden in other layers. depgraph doesnt handle that yet */
|
||||
if (cu->disp.first==NULL) makeDispListCurveTypes(ob, 0);
|
||||
|
||||
if(ob==G.obedit) {
|
||||
drawnurb(scene, v3d, base, editNurb.first, dt);
|
||||
}
|
||||
else if(dt==OB_BOUNDBOX)
|
||||
draw_bounding_volume(ob);
|
||||
else if(boundbox_clip(v3d, ob->obmat, cu->bb)) {
|
||||
empty_object= drawDispList(scene, v3d, base, dt);
|
||||
|
||||
if(cu->path)
|
||||
curve_draw_speed(scene, ob);
|
||||
}
|
||||
break;
|
||||
case OB_MBALL:
|
||||
if(ob==G.obedit)
|
||||
drawmball(C, scene, v3d, base, dt);
|
||||
else if(dt==OB_BOUNDBOX)
|
||||
draw_bounding_volume(ob);
|
||||
else
|
||||
empty_object= drawmball(C, scene, v3d, base, dt);
|
||||
break;
|
||||
case OB_EMPTY:
|
||||
drawaxes(ob->empty_drawsize, flag, ob->empty_drawtype);
|
||||
break;
|
||||
case OB_LAMP:
|
||||
drawlamp(C, scene, v3d, ob);
|
||||
if(dtx || (base->flag & SELECT)) wmMultMatrix(CTX_wm_window(C), ob->obmat);
|
||||
break;
|
||||
case OB_CAMERA:
|
||||
drawcamera(C, scene, v3d, ob, flag);
|
||||
break;
|
||||
case OB_LATTICE:
|
||||
drawlattice(v3d, ob);
|
||||
break;
|
||||
case OB_ARMATURE:
|
||||
if(dt>OB_WIRE) GPU_enable_material(0, NULL); // we use default material
|
||||
empty_object= draw_armature(base, dt, flag);
|
||||
if(dt>OB_WIRE) GPU_disable_material();
|
||||
break;
|
||||
default:
|
||||
drawaxes(1.0, flag, OB_ARROWS);
|
||||
}
|
||||
if(ob->pd && ob->pd->forcefield) draw_forcefield(C, scene, ob);
|
||||
|
||||
/* code for new particle system */
|
||||
if( (warning_recursive==0) &&
|
||||
(ob->particlesystem.first) &&
|
||||
(flag & DRAW_PICKING)==0 &&
|
||||
(ob!=G.obedit)
|
||||
) {
|
||||
ParticleSystem *psys;
|
||||
if(col || (ob->flag & SELECT)) cpack(0xFFFFFF); /* for visibility, also while wpaint */
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
for(psys=ob->particlesystem.first; psys; psys=psys->next)
|
||||
draw_new_particle_system(C, v3d, base, psys, dt);
|
||||
|
||||
if(G.f & G_PARTICLEEDIT && ob==OBACT) {
|
||||
psys= NULL; // XXX PE_get_current(ob);
|
||||
if(psys && !G.obedit && psys_in_edit_mode(psys))
|
||||
draw_particle_edit(C, scene, v3d, ob, psys, dt);
|
||||
}
|
||||
glDepthMask(GL_TRUE);
|
||||
if(col) cpack(col);
|
||||
}
|
||||
|
||||
{
|
||||
bConstraint *con;
|
||||
for(con=ob->constraints.first; con; con= con->next)
|
||||
{
|
||||
if(con->type==CONSTRAINT_TYPE_RIGIDBODYJOINT)
|
||||
{
|
||||
bRigidBodyJointConstraint *data = (bRigidBodyJointConstraint*)con->data;
|
||||
if(data->flag&CONSTRAINT_DRAW_PIVOT)
|
||||
drawRBpivot(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* draw extra: after normal draw because of makeDispList */
|
||||
if(dtx && !(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))) {
|
||||
if(dtx & OB_AXIS) {
|
||||
drawaxes(1.0f, flag, OB_ARROWS);
|
||||
}
|
||||
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 */
|
||||
/* but, we also dont draw names for sets or duplicators */
|
||||
if(flag == 0) {
|
||||
if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
|
||||
glRasterPos3f(0.0, 0.0, 0.0);
|
||||
|
||||
BMF_DrawString(G.font, " ");
|
||||
BMF_DrawString(G.font, ob->id.name+2);
|
||||
if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
/*if(dtx & OB_DRAWIMAGE) drawDispListwire(&ob->disp);*/
|
||||
if((dtx & OB_DRAWWIRE) && dt>=OB_SOLID) drawWireExtra(scene, v3d, ob);
|
||||
}
|
||||
|
||||
if(dt<OB_SHADED) {
|
||||
if((ob->gameflag & OB_DYNAMIC) ||
|
||||
((ob->gameflag & OB_BOUNDS) && (ob->boundtype == OB_BOUND_SPHERE))) {
|
||||
float tmat[4][4], imat[4][4], vec[3];
|
||||
|
||||
vec[0]= vec[1]= vec[2]= 0.0;
|
||||
wmGetMatrix(CTX_wm_window(C), tmat);
|
||||
Mat4Invert(imat, tmat);
|
||||
|
||||
setlinestyle(2);
|
||||
drawcircball(GL_LINE_LOOP, vec, ob->inertia, imat);
|
||||
setlinestyle(0);
|
||||
}
|
||||
}
|
||||
|
||||
wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
|
||||
|
||||
if(zbufoff) glDisable(GL_DEPTH_TEST);
|
||||
|
||||
if(warning_recursive) return;
|
||||
if(base->flag & (OB_FROMDUPLI|OB_RADIO)) return;
|
||||
if(G.f & G_RENDER_SHADOW) return;
|
||||
|
||||
/* object centers, need to be drawn in viewmat space for speed, but OK for picking select */
|
||||
if(ob!=OBACT || (G.f & (G_VERTEXPAINT|G_TEXTUREPAINT|G_WEIGHTPAINT))==0) {
|
||||
int do_draw_center= -1; /* defines below are zero or positive... */
|
||||
|
||||
if((scene->basact)==base)
|
||||
do_draw_center= ACTIVE;
|
||||
else if(base->flag & SELECT)
|
||||
do_draw_center= SELECT;
|
||||
else if(empty_object || (v3d->flag & V3D_DRAW_CENTERS))
|
||||
do_draw_center= DESELECT;
|
||||
|
||||
if(do_draw_center != -1) {
|
||||
if(flag & DRAW_PICKING) {
|
||||
/* draw a single point for opengl selection */
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3fv(ob->obmat[3]);
|
||||
glEnd();
|
||||
}
|
||||
else if((flag & DRAW_CONSTCOLOR)==0) {
|
||||
/* we don't draw centers for duplicators and sets */
|
||||
drawcentercircle(v3d, ob->obmat[3], do_draw_center, ob->id.lib || ob->id.us>1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* not for sets, duplicators or picking */
|
||||
if(flag==0 && (!(v3d->flag & V3D_HIDE_HELPLINES))) {
|
||||
ListBase *list;
|
||||
|
||||
/* draw hook center and offset line */
|
||||
if(ob!=G.obedit) draw_hooks(ob);
|
||||
|
||||
/* help lines and so */
|
||||
if(ob!=G.obedit && ob->parent && (ob->parent->lay & v3d->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) {
|
||||
bConstraint *curcon;
|
||||
bConstraintOb *cob;
|
||||
char col[4], col2[4];
|
||||
|
||||
UI_GetThemeColor3ubv(TH_GRID, col);
|
||||
make_axis_color(col, col2, 'z');
|
||||
glColor3ubv((GLubyte *)col2);
|
||||
|
||||
cob= constraints_make_evalob(ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
|
||||
|
||||
for (curcon = list->first; curcon; curcon=curcon->next) {
|
||||
bConstraintTypeInfo *cti= constraint_get_typeinfo(curcon);
|
||||
ListBase targets = {NULL, NULL};
|
||||
bConstraintTarget *ct;
|
||||
|
||||
if ((curcon->flag & CONSTRAINT_EXPAND) && (cti) && (cti->get_constraint_targets)) {
|
||||
cti->get_constraint_targets(curcon, &targets);
|
||||
|
||||
for (ct= targets.first; ct; ct= ct->next) {
|
||||
/* calculate target's matrix */
|
||||
if (cti->get_target_matrix)
|
||||
cti->get_target_matrix(curcon, cob, ct, bsystem_time(ob, (float)(scene->r.cfra), give_timeoffset(ob)));
|
||||
else
|
||||
Mat4One(ct->matrix);
|
||||
|
||||
setlinestyle(3);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3fv(ct->matrix[3]);
|
||||
glVertex3fv(ob->obmat[3]);
|
||||
glEnd();
|
||||
setlinestyle(0);
|
||||
}
|
||||
|
||||
if (cti->flush_constraint_targets)
|
||||
cti->flush_constraint_targets(curcon, &targets, 1);
|
||||
}
|
||||
}
|
||||
|
||||
constraints_clear_evalob(cob);
|
||||
}
|
||||
}
|
||||
|
||||
free_old_images();
|
||||
}
|
||||
|
||||
void draw_object_ext(const bContext *C, ARegion *ar, View3D *v3d, Scene *scene, Base *base)
|
||||
{
|
||||
|
||||
if(v3d==NULL || base==NULL) return;
|
||||
|
||||
if(v3d->drawtype > OB_WIRE) {
|
||||
v3d->zbuf= 1;
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
G.f |= G_DRAW_EXT;
|
||||
|
||||
glDrawBuffer(GL_FRONT);
|
||||
// XXX persp(PERSP_VIEW);
|
||||
|
||||
if(v3d->flag & V3D_CLIPPING)
|
||||
view3d_set_clipping(v3d);
|
||||
|
||||
draw_object(C, scene, ar, v3d, base, 0);
|
||||
|
||||
if(v3d->flag & V3D_CLIPPING)
|
||||
view3d_clr_clipping();
|
||||
|
||||
G.f &= ~G_DRAW_EXT;
|
||||
|
||||
bglFlush(); /* reveil frontbuffer drawing */
|
||||
glDrawBuffer(GL_BACK);
|
||||
|
||||
if(v3d->zbuf) {
|
||||
v3d->zbuf= 0;
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
// XXX ar->win_swap= WIN_FRONT_OK;
|
||||
}
|
||||
|
||||
/* ***************** BACKBUF SEL (BBS) ********* */
|
||||
|
||||
static void bbs_mesh_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
|
||||
{
|
||||
int offset = (intptr_t) userData;
|
||||
EditVert *eve = EM_get_vert_for_index(index);
|
||||
|
||||
if (eve->h==0) {
|
||||
WM_set_framebuffer_index_color(offset+index);
|
||||
bglVertex3fv(co);
|
||||
}
|
||||
}
|
||||
static int bbs_mesh_verts(DerivedMesh *dm, int offset)
|
||||
{
|
||||
glPointSize( UI_GetThemeValuef(TH_VERTEX_SIZE) );
|
||||
bglBegin(GL_POINTS);
|
||||
dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, (void*)(intptr_t) offset);
|
||||
bglEnd();
|
||||
glPointSize(1.0);
|
||||
|
||||
return offset + G.totvert;
|
||||
}
|
||||
|
||||
static int bbs_mesh_wire__setDrawOptions(void *userData, int index)
|
||||
{
|
||||
int offset = (intptr_t) userData;
|
||||
EditEdge *eed = EM_get_edge_for_index(index);
|
||||
|
||||
if (eed->h==0) {
|
||||
WM_set_framebuffer_index_color(offset+index);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static int bbs_mesh_wire(DerivedMesh *dm, int offset)
|
||||
{
|
||||
dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, (void*)(intptr_t) offset);
|
||||
|
||||
return offset + G.totedge;
|
||||
}
|
||||
|
||||
static int bbs_mesh_solid__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
|
||||
{
|
||||
if (EM_get_face_for_index(index)->h==0) {
|
||||
if (userData) {
|
||||
WM_set_framebuffer_index_color(index+1);
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void bbs_mesh_solid__drawCenter(void *userData, int index, float *cent, float *no)
|
||||
{
|
||||
EditFace *efa = EM_get_face_for_index(index);
|
||||
|
||||
if (efa->h==0 && efa->fgonf!=EM_FGON) {
|
||||
WM_set_framebuffer_index_color(index+1);
|
||||
|
||||
bglVertex3fv(cent);
|
||||
}
|
||||
}
|
||||
|
||||
/* two options, facecolors or black */
|
||||
static int bbs_mesh_solid_EM(Scene *scene, View3D *v3d, DerivedMesh *dm, int facecol)
|
||||
{
|
||||
cpack(0);
|
||||
|
||||
if (facecol) {
|
||||
dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*)(intptr_t) 1, 0);
|
||||
|
||||
if( CHECK_OB_DRAWFACEDOT(scene, v3d, G.obedit->dt) ) {
|
||||
glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE));
|
||||
|
||||
bglBegin(GL_POINTS);
|
||||
dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, NULL);
|
||||
bglEnd();
|
||||
}
|
||||
|
||||
return 1+G.totface;
|
||||
} else {
|
||||
dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*) 0, 0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int bbs_mesh_solid__setDrawOpts(void *userData, int index, int *drawSmooth_r)
|
||||
{
|
||||
Mesh *me = userData;
|
||||
|
||||
if (!(me->mface[index].flag&ME_HIDE)) {
|
||||
WM_set_framebuffer_index_color(index+1);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO remove this - since face select mode now only works with painting */
|
||||
static void bbs_mesh_solid(Object *ob)
|
||||
{
|
||||
DerivedMesh *dm = mesh_get_derived_final(ob, get_viewedit_datamask());
|
||||
Mesh *me = (Mesh*)ob->data;
|
||||
|
||||
glColor3ub(0, 0, 0);
|
||||
dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, me, 0);
|
||||
|
||||
dm->release(dm);
|
||||
}
|
||||
|
||||
void draw_object_backbufsel(const bContext *C, Scene *scene, View3D *v3d, Object *ob)
|
||||
{
|
||||
|
||||
wmMultMatrix(CTX_wm_window(C), ob->obmat);
|
||||
|
||||
glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
switch( ob->type) {
|
||||
case OB_MESH:
|
||||
if(ob==G.obedit) {
|
||||
DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
|
||||
|
||||
EM_init_index_arrays(1, 1, 1);
|
||||
|
||||
em_solidoffs= bbs_mesh_solid_EM(scene, v3d, dm, scene->selectmode & SCE_SELECT_FACE);
|
||||
|
||||
bglPolygonOffset(1.0);
|
||||
|
||||
// we draw edges always, for loop (select) tools
|
||||
em_wireoffs= bbs_mesh_wire(dm, em_solidoffs);
|
||||
|
||||
// we draw verts if vert select mode or if in transform (for snap).
|
||||
if(scene->selectmode & SCE_SELECT_VERTEX || G.moving & G_TRANSFORM_EDIT)
|
||||
em_vertoffs= bbs_mesh_verts(dm, em_wireoffs);
|
||||
else em_vertoffs= em_wireoffs;
|
||||
|
||||
bglPolygonOffset(0.0);
|
||||
|
||||
dm->release(dm);
|
||||
|
||||
EM_free_index_arrays();
|
||||
}
|
||||
else bbs_mesh_solid(ob);
|
||||
|
||||
break;
|
||||
case OB_CURVE:
|
||||
case OB_SURF:
|
||||
break;
|
||||
}
|
||||
|
||||
wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
|
||||
}
|
||||
|
||||
|
||||
/* ************* draw object instances for bones, for example ****************** */
|
||||
/* assumes all matrices/etc set OK */
|
||||
|
||||
/* helper function for drawing object instances - meshes */
|
||||
static void draw_object_mesh_instance(Scene *scene, View3D *v3d, Object *ob, int dt, int outline)
|
||||
{
|
||||
DerivedMesh *dm=NULL, *edm=NULL;
|
||||
int glsl;
|
||||
|
||||
if(G.obedit && ob->data==G.obedit->data)
|
||||
edm= editmesh_get_derived_base();
|
||||
else
|
||||
dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
|
||||
|
||||
if(dt<=OB_WIRE) {
|
||||
if(dm)
|
||||
dm->drawEdges(dm, 1);
|
||||
else if(edm)
|
||||
edm->drawEdges(edm, 1);
|
||||
}
|
||||
else {
|
||||
if(outline)
|
||||
draw_mesh_object_outline(v3d, ob, dm?dm:edm);
|
||||
|
||||
if(dm) {
|
||||
glsl = draw_glsl_material(scene, ob, v3d, dt);
|
||||
GPU_set_object_materials(scene, ob, glsl, NULL);
|
||||
}
|
||||
else {
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
UI_ThemeColor(TH_BONE_SOLID);
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
}
|
||||
|
||||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
|
||||
glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
|
||||
glEnable(GL_LIGHTING);
|
||||
|
||||
if(dm) {
|
||||
dm->drawFacesSolid(dm, GPU_enable_material);
|
||||
GPU_disable_material();
|
||||
}
|
||||
else if(edm)
|
||||
edm->drawMappedFaces(edm, NULL, NULL, 0);
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
if(edm) edm->release(edm);
|
||||
if(dm) dm->release(dm);
|
||||
}
|
||||
|
||||
void draw_object_instance(Scene *scene, View3D *v3d, Object *ob, int dt, int outline)
|
||||
{
|
||||
if (ob == NULL)
|
||||
return;
|
||||
|
||||
switch (ob->type) {
|
||||
case OB_MESH:
|
||||
draw_object_mesh_instance(scene, v3d, ob, dt, outline);
|
||||
break;
|
||||
case OB_EMPTY:
|
||||
drawaxes(ob->empty_drawsize, 0, ob->empty_drawtype);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "DNA_action_types.h"
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_group_types.h"
|
||||
#include "DNA_key_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
@@ -72,12 +73,16 @@
|
||||
|
||||
#include "ED_screen.h"
|
||||
#include "ED_util.h"
|
||||
#include "ED_types.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_interface_icons.h"
|
||||
#include "UI_resources.h"
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#include "GPU_draw.h"
|
||||
#include "GPU_material.h"
|
||||
|
||||
#include "view3d_intern.h" // own include
|
||||
|
||||
|
||||
@@ -1145,6 +1150,178 @@ static void draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d)
|
||||
// XXX areawinset(ar->win); // restore viewport / scissor
|
||||
}
|
||||
|
||||
/* ****************** View3d afterdraw *************** */
|
||||
|
||||
typedef struct View3DAfter {
|
||||
struct View3DAfter *next, *prev;
|
||||
struct Base *base;
|
||||
int type, flag;
|
||||
} View3DAfter;
|
||||
|
||||
/* temp storage of Objects that need to be drawn as last */
|
||||
void add_view3d_after(View3D *v3d, Base *base, int type, int flag)
|
||||
{
|
||||
View3DAfter *v3da= MEM_callocN(sizeof(View3DAfter), "View 3d after");
|
||||
|
||||
BLI_addtail(&v3d->afterdraw, v3da);
|
||||
v3da->base= base;
|
||||
v3da->type= type;
|
||||
v3da->flag= flag;
|
||||
}
|
||||
|
||||
/* clears zbuffer and draws it over */
|
||||
static void view3d_draw_xray(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d, int clear)
|
||||
{
|
||||
View3DAfter *v3da, *next;
|
||||
int doit= 0;
|
||||
|
||||
for(v3da= v3d->afterdraw.first; v3da; v3da= v3da->next)
|
||||
if(v3da->type==V3D_XRAY) doit= 1;
|
||||
|
||||
if(doit) {
|
||||
if(clear && v3d->zbuf) glClear(GL_DEPTH_BUFFER_BIT);
|
||||
v3d->xray= TRUE;
|
||||
|
||||
for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
|
||||
next= v3da->next;
|
||||
if(v3da->type==V3D_XRAY) {
|
||||
draw_object(C, scene, ar, v3d, v3da->base, v3da->flag);
|
||||
BLI_remlink(&v3d->afterdraw, v3da);
|
||||
MEM_freeN(v3da);
|
||||
}
|
||||
}
|
||||
v3d->xray= FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* disables write in zbuffer and draws it over */
|
||||
static void view3d_draw_transp(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d)
|
||||
{
|
||||
View3DAfter *v3da, *next;
|
||||
|
||||
glDepthMask(0);
|
||||
v3d->transp= TRUE;
|
||||
|
||||
for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
|
||||
next= v3da->next;
|
||||
if(v3da->type==V3D_TRANSP) {
|
||||
draw_object(C, scene, ar, v3d, v3da->base, v3da->flag);
|
||||
BLI_remlink(&v3d->afterdraw, v3da);
|
||||
MEM_freeN(v3da);
|
||||
}
|
||||
}
|
||||
v3d->transp= FALSE;
|
||||
|
||||
glDepthMask(1);
|
||||
|
||||
}
|
||||
|
||||
/* *********************** */
|
||||
|
||||
/*
|
||||
In most cases call draw_dupli_objects,
|
||||
draw_dupli_objects_color was added because when drawing set dupli's
|
||||
we need to force the color
|
||||
*/
|
||||
static void draw_dupli_objects_color(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d, Base *base, int color)
|
||||
{
|
||||
ListBase *lb;
|
||||
DupliObject *dob;
|
||||
Base tbase;
|
||||
BoundBox *bb= NULL;
|
||||
GLuint displist=0;
|
||||
short transflag, use_displist= -1; /* -1 is initialize */
|
||||
char dt, dtx;
|
||||
|
||||
if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
|
||||
|
||||
tbase.flag= OB_FROMDUPLI|base->flag;
|
||||
lb= object_duplilist(scene, base->object);
|
||||
|
||||
for(dob= lb->first; dob; dob= dob->next) {
|
||||
if(dob->no_draw);
|
||||
else {
|
||||
tbase.object= dob->ob;
|
||||
|
||||
/* extra service: draw the duplicator in drawtype of parent */
|
||||
/* MIN2 for the drawtype to allow bounding box objects in groups for lods */
|
||||
dt= tbase.object->dt; tbase.object->dt= MIN2(tbase.object->dt, base->object->dt);
|
||||
dtx= tbase.object->dtx; tbase.object->dtx= base->object->dtx;
|
||||
|
||||
/* negative scale flag has to propagate */
|
||||
transflag= tbase.object->transflag;
|
||||
if(base->object->transflag & OB_NEG_SCALE)
|
||||
tbase.object->transflag ^= OB_NEG_SCALE;
|
||||
|
||||
UI_ThemeColorBlend(color, TH_BACK, 0.5);
|
||||
|
||||
/* generate displist, test for new object */
|
||||
if(use_displist==1 && dob->prev && dob->prev->ob!=dob->ob) {
|
||||
use_displist= -1;
|
||||
glDeleteLists(displist, 1);
|
||||
}
|
||||
/* generate displist */
|
||||
if(use_displist == -1) {
|
||||
|
||||
/* lamp drawing messes with matrices, could be handled smarter... but this works */
|
||||
if(dob->ob->type==OB_LAMP || dob->type==OB_DUPLIGROUP)
|
||||
use_displist= 0;
|
||||
else {
|
||||
/* disable boundbox check for list creation */
|
||||
object_boundbox_flag(dob->ob, OB_BB_DISABLED, 1);
|
||||
/* need this for next part of code */
|
||||
bb= object_get_boundbox(dob->ob);
|
||||
|
||||
Mat4One(dob->ob->obmat); /* obmat gets restored */
|
||||
|
||||
displist= glGenLists(1);
|
||||
glNewList(displist, GL_COMPILE);
|
||||
draw_object(C, scene, ar, v3d, &tbase, DRAW_CONSTCOLOR);
|
||||
glEndList();
|
||||
|
||||
use_displist= 1;
|
||||
object_boundbox_flag(dob->ob, OB_BB_DISABLED, 0);
|
||||
}
|
||||
}
|
||||
if(use_displist) {
|
||||
wmMultMatrix(CTX_wm_window(C), dob->mat);
|
||||
if(boundbox_clip(v3d, dob->mat, bb))
|
||||
glCallList(displist);
|
||||
wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
|
||||
}
|
||||
else {
|
||||
Mat4CpyMat4(dob->ob->obmat, dob->mat);
|
||||
draw_object(C, scene, ar, v3d, &tbase, DRAW_CONSTCOLOR);
|
||||
}
|
||||
|
||||
tbase.object->dt= dt;
|
||||
tbase.object->dtx= dtx;
|
||||
tbase.object->transflag= transflag;
|
||||
}
|
||||
}
|
||||
|
||||
/* Transp afterdraw disabled, afterdraw only stores base pointers, and duplis can be same obj */
|
||||
|
||||
free_object_duplilist(lb); /* does restore */
|
||||
|
||||
if(use_displist)
|
||||
glDeleteLists(displist, 1);
|
||||
}
|
||||
|
||||
static void draw_dupli_objects(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d, Base *base)
|
||||
{
|
||||
/* define the color here so draw_dupli_objects_color can be called
|
||||
* from the set loop */
|
||||
|
||||
int color= (base->flag & SELECT)?TH_SELECT:TH_WIRE;
|
||||
/* debug */
|
||||
if(base->object->dup_group && base->object->dup_group->id.us<1)
|
||||
color= TH_REDALERT;
|
||||
|
||||
draw_dupli_objects_color(C, scene, ar, v3d, base, color);
|
||||
}
|
||||
|
||||
|
||||
void view3d_update_depths(ARegion *ar, View3D *v3d)
|
||||
{
|
||||
/* Create storage for, and, if necessary, copy depth buffer */
|
||||
@@ -1174,7 +1351,7 @@ void view3d_update_depths(ARegion *ar, View3D *v3d)
|
||||
}
|
||||
|
||||
/* Enable sculpting in wireframe mode by drawing sculpt object only to the depth buffer */
|
||||
static void draw_sculpt_depths(Scene *scene, View3D *v3d)
|
||||
static void draw_sculpt_depths(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d)
|
||||
{
|
||||
Object *ob = OBACT;
|
||||
|
||||
@@ -1193,7 +1370,7 @@ static void draw_sculpt_depths(Scene *scene, View3D *v3d)
|
||||
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
// XXX draw_object(BASACT, 0);
|
||||
draw_object(C, scene, ar, v3d, BASACT, 0);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
if(!depth_on)
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
@@ -1204,6 +1381,185 @@ static void draw_sculpt_depths(Scene *scene, View3D *v3d)
|
||||
}
|
||||
}
|
||||
|
||||
void draw_depth(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d, int (* func)(void *))
|
||||
{
|
||||
Base *base;
|
||||
Scene *sce;
|
||||
short zbuf, flag;
|
||||
float glalphaclip;
|
||||
/* temp set drawtype to solid */
|
||||
|
||||
/* Setting these temporarily is not nice */
|
||||
zbuf = v3d->zbuf;
|
||||
flag = v3d->flag;
|
||||
glalphaclip = U.glalphaclip;
|
||||
|
||||
U.glalphaclip = 0.5; /* not that nice but means we wont zoom into billboards */
|
||||
v3d->flag &= ~V3D_SELECT_OUTLINE;
|
||||
|
||||
setwinmatrixview3d(CTX_wm_window(C), v3d, ar->winx, ar->winy, NULL); /* 0= no pick rect */
|
||||
setviewmatrixview3d(v3d); /* note: calls where_is_object for camera... */
|
||||
|
||||
Mat4MulMat4(v3d->persmat, v3d->viewmat, v3d->winmat);
|
||||
Mat4Invert(v3d->persinv, v3d->persmat);
|
||||
Mat4Invert(v3d->viewinv, v3d->viewmat);
|
||||
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
|
||||
// persp(PERSP_STORE); // store correct view for persp(PERSP_VIEW) calls
|
||||
|
||||
if(v3d->flag & V3D_CLIPPING) {
|
||||
view3d_set_clipping(v3d);
|
||||
}
|
||||
|
||||
v3d->zbuf= TRUE;
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
/* draw set first */
|
||||
if(scene->set) {
|
||||
for(SETLOOPER(scene->set, base)) {
|
||||
if(v3d->lay & base->lay) {
|
||||
if (func == NULL || func(base)) {
|
||||
draw_object(C, scene, ar, v3d, base, 0);
|
||||
if(base->object->transflag & OB_DUPLI) {
|
||||
draw_dupli_objects_color(C, scene, ar, v3d, base, TH_WIRE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(base= scene->base.first; base; base= base->next) {
|
||||
if(v3d->lay & base->lay) {
|
||||
if (func == NULL || func(base)) {
|
||||
/* dupli drawing */
|
||||
if(base->object->transflag & OB_DUPLI) {
|
||||
draw_dupli_objects(C, scene, ar, v3d, base);
|
||||
}
|
||||
draw_object(C, scene, ar, v3d, base, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* this isnt that nice, draw xray objects as if they are normal */
|
||||
if (v3d->afterdraw.first) {
|
||||
View3DAfter *v3da, *next;
|
||||
int num = 0;
|
||||
v3d->xray= TRUE;
|
||||
|
||||
glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */
|
||||
for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
|
||||
next= v3da->next;
|
||||
if(v3da->type==V3D_XRAY) {
|
||||
draw_object(C, scene, ar, v3d, v3da->base, 0);
|
||||
num++;
|
||||
}
|
||||
/* dont remove this time */
|
||||
}
|
||||
v3d->xray= FALSE;
|
||||
|
||||
glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */
|
||||
for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
|
||||
next= v3da->next;
|
||||
if(v3da->type==V3D_XRAY) {
|
||||
v3d->xray= TRUE; v3d->transp= FALSE;
|
||||
} else if (v3da->type==V3D_TRANSP) {
|
||||
v3d->xray= FALSE; v3d->transp= TRUE;
|
||||
}
|
||||
|
||||
draw_object(C, scene, ar, v3d, v3da->base, 0); /* Draw Xray or Transp objects normally */
|
||||
BLI_remlink(&v3d->afterdraw, v3da);
|
||||
MEM_freeN(v3da);
|
||||
}
|
||||
v3d->xray= FALSE;
|
||||
v3d->transp= FALSE;
|
||||
}
|
||||
|
||||
v3d->zbuf = zbuf;
|
||||
U.glalphaclip = glalphaclip;
|
||||
v3d->flag = flag;
|
||||
}
|
||||
|
||||
typedef struct View3DShadow {
|
||||
struct View3DShadow *next, *prev;
|
||||
GPULamp *lamp;
|
||||
} View3DShadow;
|
||||
|
||||
static void gpu_render_lamp_update(Scene *scene, View3D *v3d, Object *ob, Object *par, float obmat[][4], ListBase *shadows)
|
||||
{
|
||||
GPULamp *lamp;
|
||||
View3DShadow *shadow;
|
||||
|
||||
lamp = GPU_lamp_from_blender(scene, ob, par);
|
||||
|
||||
if(lamp) {
|
||||
GPU_lamp_update(lamp, ob->lay, obmat);
|
||||
|
||||
if((ob->lay & v3d->lay) && GPU_lamp_has_shadow_buffer(lamp)) {
|
||||
shadow= MEM_callocN(sizeof(View3DShadow), "View3DShadow");
|
||||
shadow->lamp = lamp;
|
||||
BLI_addtail(shadows, shadow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
|
||||
{
|
||||
ListBase shadows;
|
||||
View3DShadow *shadow;
|
||||
Scene *sce;
|
||||
Base *base;
|
||||
Object *ob;
|
||||
|
||||
shadows.first= shadows.last= NULL;
|
||||
|
||||
/* update lamp transform and gather shadow lamps */
|
||||
for(SETLOOPER(scene, base)) {
|
||||
ob= base->object;
|
||||
|
||||
if(ob->type == OB_LAMP)
|
||||
gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, &shadows);
|
||||
|
||||
if (ob->transflag & OB_DUPLI) {
|
||||
DupliObject *dob;
|
||||
ListBase *lb = object_duplilist(scene, ob);
|
||||
|
||||
for(dob=lb->first; dob; dob=dob->next)
|
||||
if(dob->ob->type==OB_LAMP)
|
||||
gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, &shadows);
|
||||
|
||||
free_object_duplilist(lb);
|
||||
}
|
||||
}
|
||||
|
||||
/* render shadows after updating all lamps, nested object_duplilist
|
||||
* don't work correct since it's replacing object matrices */
|
||||
for(shadow=shadows.first; shadow; shadow=shadow->next) {
|
||||
/* this needs to be done better .. */
|
||||
float viewmat[4][4], winmat[4][4];
|
||||
int drawtype, lay, winsize, flag2;
|
||||
|
||||
drawtype= v3d->drawtype;
|
||||
lay= v3d->lay;
|
||||
flag2= v3d->flag2 & V3D_SOLID_TEX;
|
||||
|
||||
v3d->drawtype = OB_SOLID;
|
||||
v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp);
|
||||
v3d->flag2 &= ~V3D_SOLID_TEX;
|
||||
|
||||
GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat);
|
||||
// XXX drawview3d_render(v3d, viewmat, winsize, winsize, winmat, 1);
|
||||
GPU_lamp_shadow_buffer_unbind(shadow->lamp);
|
||||
|
||||
v3d->drawtype= drawtype;
|
||||
v3d->lay= lay;
|
||||
v3d->flag2 |= flag2;
|
||||
}
|
||||
|
||||
BLI_freelistN(&shadows);
|
||||
}
|
||||
|
||||
|
||||
void drawview3dspace(const bContext *C, ARegion *ar, View3D *v3d)
|
||||
{
|
||||
@@ -1228,8 +1584,8 @@ void drawview3dspace(const bContext *C, ARegion *ar, View3D *v3d)
|
||||
}
|
||||
|
||||
/* shadow buffers, before we setup matrices */
|
||||
// if(draw_glsl_material(NULL, v3d->drawtype))
|
||||
// gpu_update_lamps_shadows(scene, v3d);
|
||||
if(draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
|
||||
gpu_update_lamps_shadows(scene, v3d);
|
||||
|
||||
setwinmatrixview3d(CTX_wm_window(C), v3d, ar->winx, ar->winy, NULL); /* 0= no pick rect */
|
||||
setviewmatrixview3d(v3d); /* note: calls where_is_object for camera... */
|
||||
@@ -1319,10 +1675,10 @@ void drawview3dspace(const bContext *C, ARegion *ar, View3D *v3d)
|
||||
if(v3d->lay & base->lay) {
|
||||
|
||||
UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
|
||||
// XXX draw_object(base, DRAW_CONSTCOLOR|DRAW_SCENESET);
|
||||
draw_object(C, scene, ar, v3d, base, DRAW_CONSTCOLOR|DRAW_SCENESET);
|
||||
|
||||
if(base->object->transflag & OB_DUPLI) {
|
||||
// XXX draw_dupli_objects_color(v3d, base, TH_WIRE);
|
||||
draw_dupli_objects_color(C, scene, ar, v3d, base, TH_WIRE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1336,10 +1692,11 @@ void drawview3dspace(const bContext *C, ARegion *ar, View3D *v3d)
|
||||
|
||||
/* dupli drawing */
|
||||
if(base->object->transflag & OB_DUPLI) {
|
||||
// XXX draw_dupli_objects(v3d, base);
|
||||
draw_dupli_objects(C, scene, ar, v3d, base);
|
||||
}
|
||||
if((base->flag & SELECT)==0) {
|
||||
// XXX if(base->object!=G.obedit) draw_object(base, 0);
|
||||
if(base->object!=G.obedit)
|
||||
draw_object(C, scene, ar, v3d, base, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1352,14 +1709,14 @@ void drawview3dspace(const bContext *C, ARegion *ar, View3D *v3d)
|
||||
/* draw selected and editmode */
|
||||
for(base= scene->base.first; base; base= base->next) {
|
||||
if(v3d->lay & base->lay) {
|
||||
// if (base->object==G.obedit || ( base->flag & SELECT) )
|
||||
// XXX draw_object(base, 0);
|
||||
if (base->object==G.obedit || ( base->flag & SELECT) )
|
||||
draw_object(C, scene, ar, v3d, base, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(!retopo && sculptparticle && !(obact && (obact->dtx & OB_DRAWXRAY))) {
|
||||
if(G.f & G_SCULPTMODE)
|
||||
draw_sculpt_depths(scene, v3d);
|
||||
draw_sculpt_depths(C, scene, ar, v3d);
|
||||
view3d_update_depths(ar, v3d);
|
||||
}
|
||||
|
||||
@@ -1375,12 +1732,12 @@ void drawview3dspace(const bContext *C, ARegion *ar, View3D *v3d)
|
||||
// if(scene->radio) RAD_drawall(v3d->drawtype>=OB_SOLID);
|
||||
|
||||
/* Transp and X-ray afterdraw stuff */
|
||||
// view3d_draw_transp(v3d);
|
||||
// view3d_draw_xray(v3d, 1); // clears zbuffer if it is used!
|
||||
view3d_draw_transp(C, scene, ar, v3d);
|
||||
view3d_draw_xray(C, scene, ar, v3d, 1); // clears zbuffer if it is used!
|
||||
|
||||
if(!retopo && sculptparticle && (obact && (OBACT->dtx & OB_DRAWXRAY))) {
|
||||
if(G.f & G_SCULPTMODE)
|
||||
draw_sculpt_depths(scene, v3d);
|
||||
draw_sculpt_depths(C, scene, ar, v3d);
|
||||
view3d_update_depths(ar, v3d);
|
||||
}
|
||||
|
||||
|
||||
1086
source/blender/editors/space_view3d/view3d_edit.c
Normal file
1086
source/blender/editors/space_view3d/view3d_edit.c
Normal file
@@ -0,0 +1,1086 @@
|
||||
/**
|
||||
* $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) 2008 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "DNA_action_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_lamp_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_rand.h"
|
||||
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "RE_pipeline.h" // make_stars
|
||||
|
||||
#include "BIF_gl.h"
|
||||
#include "BIF_retopo.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#include "PIL_time.h" /* smoothview */
|
||||
|
||||
#include "view3d_intern.h" // own include
|
||||
|
||||
/* ********************** view3d_edit: view manipulations ********************* */
|
||||
|
||||
#define TRACKBALLSIZE (1.1)
|
||||
|
||||
/* the central math in this function was copied from trackball.cpp, sample code from the
|
||||
Developers Toolbox series by SGI. */
|
||||
|
||||
/* trackball: better one than a full spherical solution */
|
||||
|
||||
void calctrackballvecfirst(rcti *area, short *mval, float *vec)
|
||||
{
|
||||
float x, y, radius, d, z, t;
|
||||
|
||||
radius= TRACKBALLSIZE;
|
||||
|
||||
/* normalize x and y */
|
||||
x= (area->xmax + area->xmin)/2 -mval[0];
|
||||
x/= (float)((area->xmax - area->xmin)/2);
|
||||
y= (area->ymax + area->ymin)/2 -mval[1];
|
||||
y/= (float)((area->ymax - area->ymin)/2);
|
||||
|
||||
d = sqrt(x*x + y*y);
|
||||
if (d < radius*M_SQRT1_2) /* Inside sphere */
|
||||
z = sqrt(radius*radius - d*d);
|
||||
else
|
||||
{ /* On hyperbola */
|
||||
t = radius / M_SQRT2;
|
||||
z = t*t / d;
|
||||
}
|
||||
|
||||
vec[0]= x;
|
||||
vec[1]= y;
|
||||
vec[2]= -z; /* yah yah! */
|
||||
|
||||
if( fabs(vec[2])>fabs(vec[1]) && fabs(vec[2])>fabs(vec[0]) ) {
|
||||
vec[0]= 0.0;
|
||||
vec[1]= 0.0;
|
||||
if(vec[2]>0.0) vec[2]= 1.0; else vec[2]= -1.0;
|
||||
}
|
||||
else if( fabs(vec[1])>fabs(vec[0]) && fabs(vec[1])>fabs(vec[2]) ) {
|
||||
vec[0]= 0.0;
|
||||
vec[2]= 0.0;
|
||||
if(vec[1]>0.0) vec[1]= 1.0; else vec[1]= -1.0;
|
||||
}
|
||||
else {
|
||||
vec[1]= 0.0;
|
||||
vec[2]= 0.0;
|
||||
if(vec[0]>0.0) vec[0]= 1.0; else vec[0]= -1.0;
|
||||
}
|
||||
}
|
||||
|
||||
void calctrackballvec(rcti *area, short *mval, float *vec)
|
||||
{
|
||||
float x, y, radius, d, z, t;
|
||||
|
||||
radius= TRACKBALLSIZE;
|
||||
|
||||
/* x en y normalizeren */
|
||||
x= (area->xmax + area->xmin)/2 -mval[0];
|
||||
x/= (float)((area->xmax - area->xmin)/4);
|
||||
y= (area->ymax + area->ymin)/2 -mval[1];
|
||||
y/= (float)((area->ymax - area->ymin)/2);
|
||||
|
||||
d = sqrt(x*x + y*y);
|
||||
if (d < radius*M_SQRT1_2) /* Inside sphere */
|
||||
z = sqrt(radius*radius - d*d);
|
||||
else
|
||||
{ /* On hyperbola */
|
||||
t = radius / M_SQRT2;
|
||||
z = t*t / d;
|
||||
}
|
||||
|
||||
vec[0]= x;
|
||||
vec[1]= y;
|
||||
vec[2]= -z; /* yah yah! */
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ndof scaling will be moved to user setting.
|
||||
// In the mean time this is just a place holder.
|
||||
|
||||
// Note: scaling in the plugin and ghostwinlay.c
|
||||
// should be removed. With driver default setting,
|
||||
// each axis returns approx. +-200 max deflection.
|
||||
|
||||
// The values I selected are based on the older
|
||||
// polling i/f. With event i/f, the sensistivity
|
||||
// can be increased for improved response from
|
||||
// small deflections of the device input.
|
||||
|
||||
|
||||
// lukep notes : i disagree on the range.
|
||||
// the normal 3Dconnection driver give +/-400
|
||||
// on defaut range in other applications
|
||||
// and up to +/- 1000 if set to maximum
|
||||
// because i remove the scaling by delta,
|
||||
// which was a bad idea as it depend of the system
|
||||
// speed and os, i changed the scaling values, but
|
||||
// those are still not ok
|
||||
|
||||
|
||||
float ndof_axis_scale[6] = {
|
||||
+0.01, // Tx
|
||||
+0.01, // Tz
|
||||
+0.01, // Ty
|
||||
+0.0015, // Rx
|
||||
+0.0015, // Rz
|
||||
+0.0015 // Ry
|
||||
};
|
||||
|
||||
void filterNDOFvalues(float *sbval)
|
||||
{
|
||||
int i=0;
|
||||
float max = 0.0;
|
||||
|
||||
for (i =0; i<6;i++)
|
||||
if (fabs(sbval[i]) > max)
|
||||
max = fabs(sbval[i]);
|
||||
for (i =0; i<6;i++)
|
||||
if (fabs(sbval[i]) != max )
|
||||
sbval[i]=0.0;
|
||||
}
|
||||
|
||||
// statics for controlling v3d->dist corrections.
|
||||
// viewmoveNDOF zeros and adjusts v3d->ofs.
|
||||
// viewmove restores based on dz_flag state.
|
||||
|
||||
int dz_flag = 0;
|
||||
float m_dist;
|
||||
|
||||
void viewmoveNDOFfly(ARegion *ar, View3D *v3d, int mode)
|
||||
{
|
||||
int i;
|
||||
float phi;
|
||||
float dval[7];
|
||||
// static fval[6] for low pass filter; device input vector is dval[6]
|
||||
static float fval[6];
|
||||
float tvec[3],rvec[3];
|
||||
float q1[4];
|
||||
float mat[3][3];
|
||||
float upvec[3];
|
||||
|
||||
|
||||
/*----------------------------------------------------
|
||||
* sometimes this routine is called from headerbuttons
|
||||
* viewmove needs to refresh the screen
|
||||
*/
|
||||
// XXX areawinset(ar->win);
|
||||
|
||||
|
||||
// fetch the current state of the ndof device
|
||||
// XXX getndof(dval);
|
||||
|
||||
if (v3d->ndoffilter)
|
||||
filterNDOFvalues(fval);
|
||||
|
||||
// Scale input values
|
||||
|
||||
// if(dval[6] == 0) return; // guard against divide by zero
|
||||
|
||||
for(i=0;i<6;i++) {
|
||||
|
||||
// user scaling
|
||||
dval[i] = dval[i] * ndof_axis_scale[i];
|
||||
}
|
||||
|
||||
|
||||
// low pass filter with zero crossing reset
|
||||
|
||||
for(i=0;i<6;i++) {
|
||||
if((dval[i] * fval[i]) >= 0)
|
||||
dval[i] = (fval[i] * 15 + dval[i]) / 16;
|
||||
else
|
||||
fval[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
// force perspective mode. This is a hack and is
|
||||
// incomplete. It doesn't actually effect the view
|
||||
// until the first draw and doesn't update the menu
|
||||
// to reflect persp mode.
|
||||
|
||||
v3d->persp = V3D_PERSP;
|
||||
|
||||
|
||||
// Correct the distance jump if v3d->dist != 0
|
||||
|
||||
// This is due to a side effect of the original
|
||||
// mouse view rotation code. The rotation point is
|
||||
// set a distance in front of the viewport to
|
||||
// make rotating with the mouse look better.
|
||||
// The distance effect is written at a low level
|
||||
// in the view management instead of the mouse
|
||||
// view function. This means that all other view
|
||||
// movement devices must subtract this from their
|
||||
// view transformations.
|
||||
|
||||
if(v3d->dist != 0.0) {
|
||||
dz_flag = 1;
|
||||
m_dist = v3d->dist;
|
||||
upvec[0] = upvec[1] = 0;
|
||||
upvec[2] = v3d->dist;
|
||||
Mat3CpyMat4(mat, v3d->viewinv);
|
||||
Mat3MulVecfl(mat, upvec);
|
||||
VecSubf(v3d->ofs, v3d->ofs, upvec);
|
||||
v3d->dist = 0.0;
|
||||
}
|
||||
|
||||
|
||||
// Apply rotation
|
||||
// Rotations feel relatively faster than translations only in fly mode, so
|
||||
// we have no choice but to fix that here (not in the plugins)
|
||||
rvec[0] = -0.5 * dval[3];
|
||||
rvec[1] = -0.5 * dval[4];
|
||||
rvec[2] = -0.5 * dval[5];
|
||||
|
||||
// rotate device x and y by view z
|
||||
|
||||
Mat3CpyMat4(mat, v3d->viewinv);
|
||||
mat[2][2] = 0.0f;
|
||||
Mat3MulVecfl(mat, rvec);
|
||||
|
||||
// rotate the view
|
||||
|
||||
phi = Normalize(rvec);
|
||||
if(phi != 0) {
|
||||
VecRotToQuat(rvec,phi,q1);
|
||||
QuatMul(v3d->viewquat, v3d->viewquat, q1);
|
||||
}
|
||||
|
||||
|
||||
// Apply translation
|
||||
|
||||
tvec[0] = dval[0];
|
||||
tvec[1] = dval[1];
|
||||
tvec[2] = -dval[2];
|
||||
|
||||
// the next three lines rotate the x and y translation coordinates
|
||||
// by the current z axis angle
|
||||
|
||||
Mat3CpyMat4(mat, v3d->viewinv);
|
||||
mat[2][2] = 0.0f;
|
||||
Mat3MulVecfl(mat, tvec);
|
||||
|
||||
// translate the view
|
||||
|
||||
VecSubf(v3d->ofs, v3d->ofs, tvec);
|
||||
|
||||
|
||||
/*----------------------------------------------------
|
||||
* refresh the screen XXX
|
||||
*/
|
||||
|
||||
// update render preview window
|
||||
|
||||
// XXX BIF_view3d_previewrender_signal(ar, PR_DBASE|PR_DISPRECT);
|
||||
}
|
||||
|
||||
/* Zooms in on a border drawn by the user */
|
||||
static int view_autodist(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mouse_worldloc[3] ) //, float *autodist )
|
||||
{
|
||||
rcti rect;
|
||||
/* ZBuffer depth vars */
|
||||
bglMats mats;
|
||||
float depth, depth_close= MAXFLOAT;
|
||||
int had_depth = 0;
|
||||
double cent[2], p[3];
|
||||
int xs, ys;
|
||||
|
||||
// XXX getmouseco_areawin(mval);
|
||||
|
||||
// XXX persp(PERSP_VIEW);
|
||||
|
||||
rect.xmax = mval[0] + 4;
|
||||
rect.ymax = mval[1] + 4;
|
||||
|
||||
rect.xmin = mval[0] - 4;
|
||||
rect.ymin = mval[1] - 4;
|
||||
|
||||
/* Get Z Depths, needed for perspective, nice for ortho */
|
||||
bgl_get_mats(&mats);
|
||||
draw_depth(C, scene, ar, v3d, NULL);
|
||||
|
||||
/* force updating */
|
||||
if (v3d->depths) {
|
||||
had_depth = 1;
|
||||
v3d->depths->damaged = 1;
|
||||
}
|
||||
|
||||
view3d_update_depths(ar, v3d);
|
||||
|
||||
/* Constrain rect to depth bounds */
|
||||
if (rect.xmin < 0) rect.xmin = 0;
|
||||
if (rect.ymin < 0) rect.ymin = 0;
|
||||
if (rect.xmax >= v3d->depths->w) rect.xmax = v3d->depths->w-1;
|
||||
if (rect.ymax >= v3d->depths->h) rect.ymax = v3d->depths->h-1;
|
||||
|
||||
/* Find the closest Z pixel */
|
||||
for (xs=rect.xmin; xs < rect.xmax; xs++) {
|
||||
for (ys=rect.ymin; ys < rect.ymax; ys++) {
|
||||
depth= v3d->depths->depths[ys*v3d->depths->w+xs];
|
||||
if(depth < v3d->depths->depth_range[1] && depth > v3d->depths->depth_range[0]) {
|
||||
if (depth_close > depth) {
|
||||
depth_close = depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (depth_close==MAXFLOAT)
|
||||
return 0;
|
||||
|
||||
if (had_depth==0) {
|
||||
MEM_freeN(v3d->depths->depths);
|
||||
v3d->depths->depths = NULL;
|
||||
}
|
||||
v3d->depths->damaged = 1;
|
||||
|
||||
cent[0] = (double)mval[0];
|
||||
cent[1] = (double)mval[1];
|
||||
|
||||
if (!gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2]))
|
||||
return 0;
|
||||
|
||||
mouse_worldloc[0] = (float)p[0];
|
||||
mouse_worldloc[1] = (float)p[1];
|
||||
mouse_worldloc[2] = (float)p[2];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void view_zoom_mouseloc(ARegion *ar, View3D *v3d, float dfac, short *mouseloc)
|
||||
{
|
||||
if(U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
|
||||
short vb[2];
|
||||
float dvec[3];
|
||||
float tvec[3];
|
||||
float tpos[3];
|
||||
float new_dist;
|
||||
|
||||
/* find the current window width and height */
|
||||
vb[0] = ar->winx;
|
||||
vb[1] = ar->winy;
|
||||
|
||||
tpos[0] = -v3d->ofs[0];
|
||||
tpos[1] = -v3d->ofs[1];
|
||||
tpos[2] = -v3d->ofs[2];
|
||||
|
||||
/* Project cursor position into 3D space */
|
||||
initgrabz(v3d, tpos[0], tpos[1], tpos[2]);
|
||||
window_to_3d(ar, v3d, dvec, mouseloc[0]-vb[0]/2, mouseloc[1]-vb[1]/2);
|
||||
|
||||
/* Calculate view target position for dolly */
|
||||
tvec[0] = -(tpos[0] + dvec[0]);
|
||||
tvec[1] = -(tpos[1] + dvec[1]);
|
||||
tvec[2] = -(tpos[2] + dvec[2]);
|
||||
|
||||
/* Offset to target position and dolly */
|
||||
new_dist = v3d->dist * dfac;
|
||||
|
||||
VECCOPY(v3d->ofs, tvec);
|
||||
v3d->dist = new_dist;
|
||||
|
||||
/* Calculate final offset */
|
||||
dvec[0] = tvec[0] + dvec[0] * dfac;
|
||||
dvec[1] = tvec[1] + dvec[1] * dfac;
|
||||
dvec[2] = tvec[2] + dvec[2] * dfac;
|
||||
|
||||
VECCOPY(v3d->ofs, dvec);
|
||||
} else {
|
||||
v3d->dist *= dfac;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define COS45 0.70710678118654746
|
||||
#define SIN45 COS45
|
||||
|
||||
void viewmove(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d, int mode)
|
||||
{
|
||||
static float lastofs[3] = {0,0,0};
|
||||
Object *ob = OBACT;
|
||||
float firstvec[3], newvec[3], dvec[3];
|
||||
float reverse, oldquat[4], q1[4], si, phi, dist0;
|
||||
float ofs[3], obofs[3]= {0.0f, 0.0f, 0.0f};
|
||||
int firsttime=1;
|
||||
short mvalball[2], mval[2], mvalo[2], mval_area[2], mvali[2];
|
||||
short use_sel = 0;
|
||||
short preview3d_event= 1;
|
||||
|
||||
// locals for dist correction
|
||||
float mat[3][3];
|
||||
float upvec[3];
|
||||
|
||||
/* 3D window may not be defined */
|
||||
if( !v3d ) {
|
||||
fprintf( stderr, "v3d == NULL in viewmove()\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// dist correction from other movement devices
|
||||
if((dz_flag)||v3d->dist==0) {
|
||||
dz_flag = 0;
|
||||
v3d->dist = m_dist;
|
||||
upvec[0] = upvec[1] = 0;
|
||||
upvec[2] = v3d->dist;
|
||||
Mat3CpyMat4(mat, v3d->viewinv);
|
||||
Mat3MulVecfl(mat, upvec);
|
||||
VecAddf(v3d->ofs, v3d->ofs, upvec);
|
||||
}
|
||||
|
||||
/* sometimes this routine is called from headerbuttons */
|
||||
|
||||
// XXX areawinset(ar->win);
|
||||
|
||||
QUATCOPY(oldquat, v3d->viewquat);
|
||||
|
||||
// XXX getmouseco_areawin(mval_area); /* for zoom to mouse loc */
|
||||
// XXX getmouseco_sc(mvali); /* work with screen coordinates because of trackball function */
|
||||
mvalball[0]= mvalo[0] = mvali[0]; /* needed for turntable to work */
|
||||
mvalball[1]= mvalo[1] = mvali[1];
|
||||
dist0= v3d->dist;
|
||||
|
||||
calctrackballvec(&ar->winrct, mvalo, firstvec);
|
||||
|
||||
/* cumultime(0); */
|
||||
|
||||
if(!G.obedit && (G.f & G_SCULPTMODE) && ob && v3d->pivot_last) {
|
||||
use_sel= 1;
|
||||
VecCopyf(ofs, v3d->ofs);
|
||||
|
||||
// XXX VecCopyf(obofs, sculpt_data()->pivot);
|
||||
Mat4MulVecfl(ob->obmat, obofs);
|
||||
obofs[0]= -obofs[0];
|
||||
obofs[1]= -obofs[1];
|
||||
obofs[2]= -obofs[2];
|
||||
}
|
||||
else if (U.uiflag & USER_ORBIT_SELECTION) {
|
||||
use_sel = 1;
|
||||
|
||||
VECCOPY(ofs, v3d->ofs);
|
||||
|
||||
/* If there's no selection, lastofs is unmodified and last value since static */
|
||||
// XXX calculateTransformCenter(V3D_CENTROID, lastofs);
|
||||
|
||||
VECCOPY(obofs, lastofs);
|
||||
VecMulf(obofs, -1.0f);
|
||||
}
|
||||
else if (U.uiflag & USER_ORBIT_ZBUF) {
|
||||
if ((use_sel= view_autodist(C, scene, ar, v3d, mval, obofs))) {
|
||||
if (v3d->persp==V3D_PERSP) {
|
||||
float my_origin[3]; /* original v3d->ofs */
|
||||
float my_pivot[3]; /* view */
|
||||
|
||||
VECCOPY(my_origin, v3d->ofs);
|
||||
VecMulf(my_origin, -1.0f); /* ofs is flipped */
|
||||
|
||||
/* Set the dist value to be the distance from this 3d point */
|
||||
/* this means youll always be able to zoom into it and panning wont go bad when dist was zero */
|
||||
|
||||
/* remove dist value */
|
||||
upvec[0] = upvec[1] = 0;
|
||||
upvec[2] = v3d->dist;
|
||||
Mat3CpyMat4(mat, v3d->viewinv);
|
||||
Mat3MulVecfl(mat, upvec);
|
||||
VecSubf(my_pivot, v3d->ofs, upvec);
|
||||
VecMulf(my_pivot, -1.0f); /* ofs is flipped */
|
||||
|
||||
/* find a new ofs value that is allong the view axis (rather then the mouse location) */
|
||||
lambda_cp_line_ex(obofs, my_pivot, my_origin, dvec);
|
||||
dist0 = v3d->dist = VecLenf(my_pivot, dvec);
|
||||
|
||||
VecMulf(dvec, -1.0f);
|
||||
VECCOPY(v3d->ofs, dvec);
|
||||
}
|
||||
VecMulf(obofs, -1.0f);
|
||||
VECCOPY(ofs, v3d->ofs);
|
||||
} else {
|
||||
ofs[0] = ofs[1] = ofs[2] = 0.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
ofs[0] = ofs[1] = ofs[2] = 0.0f;
|
||||
|
||||
initgrabz(v3d, -v3d->ofs[0], -v3d->ofs[1], -v3d->ofs[2]);
|
||||
|
||||
reverse= 1.0f;
|
||||
if (v3d->persmat[2][1] < 0.0f)
|
||||
reverse= -1.0f;
|
||||
|
||||
while(TRUE) {
|
||||
// XXX getmouseco_sc(mval);
|
||||
|
||||
if( (mode==2 && U.viewzoom==USER_ZOOM_CONT) || /* continues zoom always update */
|
||||
mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) { /* mouse moved, so update */
|
||||
|
||||
if(firsttime) {
|
||||
|
||||
firsttime= 0;
|
||||
/* are we translating, rotating or zooming? */
|
||||
if(mode==0) {
|
||||
// XXX if(v3d->view!=0) scrarea_queue_headredraw(ar); /*for button */
|
||||
}
|
||||
if(v3d->persp==V3D_CAMOB && mode!=1 && v3d->camera) {
|
||||
v3d->persp= V3D_PERSP;
|
||||
// XXX scrarea_do_windraw(ar);
|
||||
// XXX scrarea_queue_headredraw(ar);
|
||||
}
|
||||
}
|
||||
|
||||
if(mode==0) { /* view rotate */
|
||||
v3d->view= 0; /* need to reset everytime because of view snapping */
|
||||
|
||||
if (U.uiflag & USER_AUTOPERSP) v3d->persp= V3D_PERSP;
|
||||
|
||||
if (U.flag & USER_TRACKBALL) mvalball[0]= mval[0];
|
||||
mvalball[1]= mval[1];
|
||||
|
||||
calctrackballvec(&ar->winrct, mvalball, newvec);
|
||||
|
||||
VecSubf(dvec, newvec, firstvec);
|
||||
|
||||
si= sqrt(dvec[0]*dvec[0]+ dvec[1]*dvec[1]+ dvec[2]*dvec[2]);
|
||||
si/= (2.0*TRACKBALLSIZE);
|
||||
|
||||
if (U.flag & USER_TRACKBALL) {
|
||||
Crossf(q1+1, firstvec, newvec);
|
||||
|
||||
Normalize(q1+1);
|
||||
|
||||
/* Allow for rotation beyond the interval
|
||||
* [-pi, pi] */
|
||||
while (si > 1.0)
|
||||
si -= 2.0;
|
||||
|
||||
/* This relation is used instead of
|
||||
* phi = asin(si) so that the angle
|
||||
* of rotation is linearly proportional
|
||||
* to the distance that the mouse is
|
||||
* dragged. */
|
||||
phi = si * M_PI / 2.0;
|
||||
|
||||
si= sin(phi);
|
||||
q1[0]= cos(phi);
|
||||
q1[1]*= si;
|
||||
q1[2]*= si;
|
||||
q1[3]*= si;
|
||||
QuatMul(v3d->viewquat, q1, oldquat);
|
||||
|
||||
if (use_sel) {
|
||||
/* compute the post multiplication quat, to rotate the offset correctly */
|
||||
QUATCOPY(q1, oldquat);
|
||||
QuatConj(q1);
|
||||
QuatMul(q1, q1, v3d->viewquat);
|
||||
|
||||
QuatConj(q1); /* conj == inv for unit quat */
|
||||
VECCOPY(v3d->ofs, ofs);
|
||||
VecSubf(v3d->ofs, v3d->ofs, obofs);
|
||||
QuatMulVecf(q1, v3d->ofs);
|
||||
VecAddf(v3d->ofs, v3d->ofs, obofs);
|
||||
}
|
||||
} else {
|
||||
/* New turntable view code by John Aughey */
|
||||
|
||||
float m[3][3];
|
||||
float m_inv[3][3];
|
||||
float xvec[3] = {1,0,0};
|
||||
/* Sensitivity will control how fast the viewport rotates. 0.0035 was
|
||||
obtained experimentally by looking at viewport rotation sensitivities
|
||||
on other modeling programs. */
|
||||
/* Perhaps this should be a configurable user parameter. */
|
||||
const float sensitivity = 0.0035;
|
||||
|
||||
/* Get the 3x3 matrix and its inverse from the quaternion */
|
||||
QuatToMat3(v3d->viewquat, m);
|
||||
Mat3Inv(m_inv,m);
|
||||
|
||||
/* Determine the direction of the x vector (for rotating up and down) */
|
||||
/* This can likely be compuated directly from the quaternion. */
|
||||
Mat3MulVecfl(m_inv,xvec);
|
||||
|
||||
/* Perform the up/down rotation */
|
||||
phi = sensitivity * -(mval[1] - mvalo[1]);
|
||||
si = sin(phi);
|
||||
q1[0] = cos(phi);
|
||||
q1[1] = si * xvec[0];
|
||||
q1[2] = si * xvec[1];
|
||||
q1[3] = si * xvec[2];
|
||||
QuatMul(v3d->viewquat, v3d->viewquat, q1);
|
||||
|
||||
if (use_sel) {
|
||||
QuatConj(q1); /* conj == inv for unit quat */
|
||||
VecSubf(v3d->ofs, v3d->ofs, obofs);
|
||||
QuatMulVecf(q1, v3d->ofs);
|
||||
VecAddf(v3d->ofs, v3d->ofs, obofs);
|
||||
}
|
||||
|
||||
/* Perform the orbital rotation */
|
||||
phi = sensitivity * reverse * (mval[0] - mvalo[0]);
|
||||
q1[0] = cos(phi);
|
||||
q1[1] = q1[2] = 0.0;
|
||||
q1[3] = sin(phi);
|
||||
QuatMul(v3d->viewquat, v3d->viewquat, q1);
|
||||
|
||||
if (use_sel) {
|
||||
QuatConj(q1);
|
||||
VecSubf(v3d->ofs, v3d->ofs, obofs);
|
||||
QuatMulVecf(q1, v3d->ofs);
|
||||
VecAddf(v3d->ofs, v3d->ofs, obofs);
|
||||
}
|
||||
}
|
||||
|
||||
/* check for view snap */
|
||||
if (G.qual==LR_CTRLKEY){
|
||||
int i;
|
||||
float viewmat[3][3];
|
||||
|
||||
static const float thres = 0.93f; //cos(20 deg);
|
||||
|
||||
static float snapquats[39][6] = {
|
||||
/*{q0, q1, q3, q4, view, oposite_direction}*/
|
||||
{COS45, -SIN45, 0.0, 0.0, 1, 0}, //front
|
||||
{0.0, 0.0, -SIN45, -SIN45, 1, 1}, //back
|
||||
{1.0, 0.0, 0.0, 0.0, 7, 0}, //top
|
||||
{0.0, -1.0, 0.0, 0.0, 7, 1}, //bottom
|
||||
{0.5, -0.5, -0.5, -0.5, 3, 0}, //left
|
||||
{0.5, -0.5, 0.5, 0.5, 3, 1}, //right
|
||||
|
||||
/* some more 45 deg snaps */
|
||||
{0.65328145027160645, -0.65328145027160645, 0.27059805393218994, 0.27059805393218994, 0, 0},
|
||||
{0.92387950420379639, 0.0, 0.0, 0.38268342614173889, 0, 0},
|
||||
{0.0, -0.92387950420379639, 0.38268342614173889, 0.0, 0, 0},
|
||||
{0.35355335474014282, -0.85355335474014282, 0.35355338454246521, 0.14644660055637360, 0, 0},
|
||||
{0.85355335474014282, -0.35355335474014282, 0.14644660055637360, 0.35355338454246521, 0, 0},
|
||||
{0.49999994039535522, -0.49999994039535522, 0.49999997019767761, 0.49999997019767761, 0, 0},
|
||||
{0.27059802412986755, -0.65328145027160645, 0.65328145027160645, 0.27059802412986755, 0, 0},
|
||||
{0.65328145027160645, -0.27059802412986755, 0.27059802412986755, 0.65328145027160645, 0, 0},
|
||||
{0.27059799432754517, -0.27059799432754517, 0.65328139066696167, 0.65328139066696167, 0, 0},
|
||||
{0.38268336653709412, 0.0, 0.0, 0.92387944459915161, 0, 0},
|
||||
{0.0, -0.38268336653709412, 0.92387944459915161, 0.0, 0, 0},
|
||||
{0.14644658565521240, -0.35355335474014282, 0.85355335474014282, 0.35355335474014282, 0, 0},
|
||||
{0.35355335474014282, -0.14644658565521240, 0.35355335474014282, 0.85355335474014282, 0, 0},
|
||||
{0.0, 0.0, 0.92387944459915161, 0.38268336653709412, 0, 0},
|
||||
{-0.0, 0.0, 0.38268336653709412, 0.92387944459915161, 0, 0},
|
||||
{-0.27059802412986755, 0.27059802412986755, 0.65328133106231689, 0.65328133106231689, 0, 0},
|
||||
{-0.38268339633941650, 0.0, 0.0, 0.92387938499450684, 0, 0},
|
||||
{0.0, 0.38268339633941650, 0.92387938499450684, 0.0, 0, 0},
|
||||
{-0.14644658565521240, 0.35355338454246521, 0.85355329513549805, 0.35355332493782043, 0, 0},
|
||||
{-0.35355338454246521, 0.14644658565521240, 0.35355332493782043, 0.85355329513549805, 0, 0},
|
||||
{-0.49999991059303284, 0.49999991059303284, 0.49999985098838806, 0.49999985098838806, 0, 0},
|
||||
{-0.27059799432754517, 0.65328145027160645, 0.65328139066696167, 0.27059799432754517, 0, 0},
|
||||
{-0.65328145027160645, 0.27059799432754517, 0.27059799432754517, 0.65328139066696167, 0, 0},
|
||||
{-0.65328133106231689, 0.65328133106231689, 0.27059793472290039, 0.27059793472290039, 0, 0},
|
||||
{-0.92387932538986206, 0.0, 0.0, 0.38268333673477173, 0, 0},
|
||||
{0.0, 0.92387932538986206, 0.38268333673477173, 0.0, 0, 0},
|
||||
{-0.35355329513549805, 0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0, 0},
|
||||
{-0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0.35355329513549805, 0, 0},
|
||||
{-0.38268330693244934, 0.92387938499450684, 0.0, 0.0, 0, 0},
|
||||
{-0.92387938499450684, 0.38268330693244934, 0.0, 0.0, 0, 0},
|
||||
{-COS45, 0.0, 0.0, SIN45, 0, 0},
|
||||
{COS45, 0.0, 0.0, SIN45, 0, 0},
|
||||
{0.0, 0.0, 0.0, 1.0, 0, 0}
|
||||
};
|
||||
|
||||
QuatToMat3(v3d->viewquat, viewmat);
|
||||
|
||||
for (i = 0 ; i < 39; i++){
|
||||
float snapmat[3][3];
|
||||
float view = (int)snapquats[i][4];
|
||||
float oposite_dir = (int)snapquats[i][5];
|
||||
|
||||
QuatToMat3(snapquats[i], snapmat);
|
||||
|
||||
if ((Inpf(snapmat[0], viewmat[0]) > thres) &&
|
||||
(Inpf(snapmat[1], viewmat[1]) > thres) &&
|
||||
(Inpf(snapmat[2], viewmat[2]) > thres)){
|
||||
|
||||
QUATCOPY(v3d->viewquat, snapquats[i]);
|
||||
|
||||
v3d->view = view;
|
||||
if (view){
|
||||
if (oposite_dir){
|
||||
v3d->flag2 |= V3D_OPP_DIRECTION_NAME;
|
||||
}else{
|
||||
v3d->flag2 &= ~V3D_OPP_DIRECTION_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(mode==1) { /* translate */
|
||||
if(v3d->persp==V3D_CAMOB) {
|
||||
float max= (float)MAX2(ar->winx, ar->winy);
|
||||
|
||||
v3d->camdx += (mvalo[0]-mval[0])/(max);
|
||||
v3d->camdy += (mvalo[1]-mval[1])/(max);
|
||||
CLAMP(v3d->camdx, -1.0f, 1.0f);
|
||||
CLAMP(v3d->camdy, -1.0f, 1.0f);
|
||||
preview3d_event= 0;
|
||||
}
|
||||
else {
|
||||
window_to_3d(ar, v3d, dvec, mval[0]-mvalo[0], mval[1]-mvalo[1]);
|
||||
VecAddf(v3d->ofs, v3d->ofs, dvec);
|
||||
}
|
||||
}
|
||||
else if(mode==2) {
|
||||
float zfac=1.0;
|
||||
|
||||
/* use initial value (do not use mvalo (that is used to detect mouse moviments)) */
|
||||
mvalo[0] = mvali[0];
|
||||
mvalo[1] = mvali[1];
|
||||
|
||||
if(U.viewzoom==USER_ZOOM_CONT) {
|
||||
// oldstyle zoom
|
||||
zfac = 1.0+(float)(mvalo[0]-mval[0]+mvalo[1]-mval[1])/1000.0;
|
||||
}
|
||||
else if(U.viewzoom==USER_ZOOM_SCALE) {
|
||||
int ctr[2], len1, len2;
|
||||
// method which zooms based on how far you move the mouse
|
||||
|
||||
ctr[0] = (ar->winrct.xmax + ar->winrct.xmin)/2;
|
||||
ctr[1] = (ar->winrct.ymax + ar->winrct.ymin)/2;
|
||||
|
||||
len1 = (int)sqrt((ctr[0] - mval[0])*(ctr[0] - mval[0]) + (ctr[1] - mval[1])*(ctr[1] - mval[1])) + 5;
|
||||
len2 = (int)sqrt((ctr[0] - mvalo[0])*(ctr[0] - mvalo[0]) + (ctr[1] - mvalo[1])*(ctr[1] - mvalo[1])) + 5;
|
||||
|
||||
zfac = dist0 * ((float)len2/len1) / v3d->dist;
|
||||
}
|
||||
else { /* USER_ZOOM_DOLLY */
|
||||
float len1 = (ar->winrct.ymax - mval[1]) + 5;
|
||||
float len2 = (ar->winrct.ymax - mvalo[1]) + 5;
|
||||
zfac = dist0 * (2.0*((len2/len1)-1.0) + 1.0) / v3d->dist;
|
||||
}
|
||||
|
||||
if(zfac != 1.0 && zfac*v3d->dist > 0.001*v3d->grid &&
|
||||
zfac*v3d->dist < 10.0*v3d->far)
|
||||
view_zoom_mouseloc(ar, v3d, zfac, mval_area);
|
||||
|
||||
|
||||
if ((U.uiflag & USER_ORBIT_ZBUF) && (U.viewzoom==USER_ZOOM_CONT) && (v3d->persp==V3D_PERSP)) {
|
||||
/* Secret apricot feature, translate the view when in continues mode */
|
||||
upvec[0] = upvec[1] = 0;
|
||||
upvec[2] = (dist0 - v3d->dist) * v3d->grid;
|
||||
v3d->dist = dist0;
|
||||
Mat3CpyMat4(mat, v3d->viewinv);
|
||||
Mat3MulVecfl(mat, upvec);
|
||||
VecAddf(v3d->ofs, v3d->ofs, upvec);
|
||||
} else {
|
||||
/* these limits are in toets.c too */
|
||||
if(v3d->dist<0.001*v3d->grid) v3d->dist= 0.001*v3d->grid;
|
||||
if(v3d->dist>10.0*v3d->far) v3d->dist=10.0*v3d->far;
|
||||
}
|
||||
|
||||
if(v3d->persp==V3D_ORTHO || v3d->persp==V3D_CAMOB) preview3d_event= 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
mvalo[0]= mval[0];
|
||||
mvalo[1]= mval[1];
|
||||
|
||||
// XXX if(G.f & G_PLAYANIM) inner_play_anim_loop(0, 0);
|
||||
|
||||
/* If in retopo paint mode, update lines */
|
||||
if(retopo_mesh_paint_check() && v3d->retopo_view_data) {
|
||||
v3d->retopo_view_data->queue_matrix_update= 1;
|
||||
retopo_paint_view_update(v3d);
|
||||
}
|
||||
|
||||
// XXX scrarea_do_windraw(ar);
|
||||
// XXX screen_swapbuffers();
|
||||
}
|
||||
else {
|
||||
// short val;
|
||||
// unsigned short event;
|
||||
/* we need to empty the queue... when you do this very long it overflows */
|
||||
// XX while(qtest()) event= extern_qread(&val);
|
||||
|
||||
// XXX BIF_wait_for_statechange();
|
||||
}
|
||||
|
||||
/* this in the end, otherwise get_mbut does not work on a PC... */
|
||||
// XXX if( !(get_mbut() & (L_MOUSE|M_MOUSE))) break;
|
||||
}
|
||||
|
||||
if(v3d->depths) v3d->depths->damaged= 1;
|
||||
// XXX retopo_queue_updates(v3d);
|
||||
// XXX allqueue(REDRAWVIEW3D, 0);
|
||||
|
||||
// XXX if(preview3d_event)
|
||||
// BIF_view3d_previewrender_signal(ar, PR_DBASE|PR_DISPRECT);
|
||||
// else
|
||||
// BIF_view3d_previewrender_signal(ar, PR_PROJECTED);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void viewmoveNDOF(Scene *scene, View3D *v3d, int mode)
|
||||
{
|
||||
float fval[7];
|
||||
float dvec[3];
|
||||
float sbadjust = 1.0f;
|
||||
float len;
|
||||
short use_sel = 0;
|
||||
Object *ob = OBACT;
|
||||
float m[3][3];
|
||||
float m_inv[3][3];
|
||||
float xvec[3] = {1,0,0};
|
||||
float yvec[3] = {0,-1,0};
|
||||
float zvec[3] = {0,0,1};
|
||||
float phi, si;
|
||||
float q1[4];
|
||||
float obofs[3];
|
||||
float reverse;
|
||||
//float diff[4];
|
||||
float d, curareaX, curareaY;
|
||||
float mat[3][3];
|
||||
float upvec[3];
|
||||
|
||||
/* Sensitivity will control how fast the view rotates. The value was
|
||||
* obtained experimentally by tweaking until the author didn't get dizzy watching.
|
||||
* Perhaps this should be a configurable user parameter.
|
||||
*/
|
||||
float psens = 0.005f * (float) U.ndof_pan; /* pan sensitivity */
|
||||
float rsens = 0.005f * (float) U.ndof_rotate; /* rotate sensitivity */
|
||||
float zsens = 0.3f; /* zoom sensitivity */
|
||||
|
||||
const float minZoom = -30.0f;
|
||||
const float maxZoom = 300.0f;
|
||||
|
||||
//reset view type
|
||||
v3d->view = 0;
|
||||
//printf("passing here \n");
|
||||
//
|
||||
if (G.obedit==NULL && ob && !(ob->flag & OB_POSEMODE)) {
|
||||
use_sel = 1;
|
||||
}
|
||||
|
||||
if((dz_flag)||v3d->dist==0) {
|
||||
dz_flag = 0;
|
||||
v3d->dist = m_dist;
|
||||
upvec[0] = upvec[1] = 0;
|
||||
upvec[2] = v3d->dist;
|
||||
Mat3CpyMat4(mat, v3d->viewinv);
|
||||
Mat3MulVecfl(mat, upvec);
|
||||
VecAddf(v3d->ofs, v3d->ofs, upvec);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------
|
||||
* sometimes this routine is called from headerbuttons
|
||||
* viewmove needs to refresh the screen
|
||||
*/
|
||||
// XXX areawinset(curarea->win);
|
||||
|
||||
/*----------------------------------------------------
|
||||
* record how much time has passed. clamp at 10 Hz
|
||||
* pretend the previous frame occured at the clamped time
|
||||
*/
|
||||
// now = PIL_check_seconds_timer();
|
||||
// frametime = (now - prevTime);
|
||||
// if (frametime > 0.1f){ /* if more than 1/10s */
|
||||
// frametime = 1.0f/60.0; /* clamp at 1/60s so no jumps when starting to move */
|
||||
// }
|
||||
// prevTime = now;
|
||||
// sbadjust *= 60 * frametime; /* normalize ndof device adjustments to 100Hz for framerate independence */
|
||||
|
||||
/* fetch the current state of the ndof device & enforce dominant mode if selected */
|
||||
// XXX getndof(fval);
|
||||
if (v3d->ndoffilter)
|
||||
filterNDOFvalues(fval);
|
||||
|
||||
|
||||
// put scaling back here, was previously in ghostwinlay
|
||||
fval[0] = fval[0] * (1.0f/600.0f);
|
||||
fval[1] = fval[1] * (1.0f/600.0f);
|
||||
fval[2] = fval[2] * (1.0f/1100.0f);
|
||||
fval[3] = fval[3] * 0.00005f;
|
||||
fval[4] =-fval[4] * 0.00005f;
|
||||
fval[5] = fval[5] * 0.00005f;
|
||||
fval[6] = fval[6] / 1000000.0f;
|
||||
|
||||
// scale more if not in perspective mode
|
||||
if (v3d->persp == V3D_ORTHO) {
|
||||
fval[0] = fval[0] * 0.05f;
|
||||
fval[1] = fval[1] * 0.05f;
|
||||
fval[2] = fval[2] * 0.05f;
|
||||
fval[3] = fval[3] * 0.9f;
|
||||
fval[4] = fval[4] * 0.9f;
|
||||
fval[5] = fval[5] * 0.9f;
|
||||
zsens *= 8;
|
||||
}
|
||||
|
||||
|
||||
/* set object offset */
|
||||
if (ob) {
|
||||
obofs[0] = -ob->obmat[3][0];
|
||||
obofs[1] = -ob->obmat[3][1];
|
||||
obofs[2] = -ob->obmat[3][2];
|
||||
}
|
||||
else {
|
||||
VECCOPY(obofs, v3d->ofs);
|
||||
}
|
||||
|
||||
/* calc an adjustment based on distance from camera
|
||||
disabled per patch 14402 */
|
||||
d = 1.0f;
|
||||
|
||||
/* if (ob) {
|
||||
VecSubf(diff, obofs, v3d->ofs);
|
||||
d = VecLength(diff);
|
||||
}
|
||||
*/
|
||||
|
||||
reverse = (v3d->persmat[2][1] < 0.0f) ? -1.0f : 1.0f;
|
||||
|
||||
/*----------------------------------------------------
|
||||
* ndof device pan
|
||||
*/
|
||||
psens *= 1.0f + d;
|
||||
curareaX = sbadjust * psens * fval[0];
|
||||
curareaY = sbadjust * psens * fval[1];
|
||||
dvec[0] = curareaX * v3d->persinv[0][0] + curareaY * v3d->persinv[1][0];
|
||||
dvec[1] = curareaX * v3d->persinv[0][1] + curareaY * v3d->persinv[1][1];
|
||||
dvec[2] = curareaX * v3d->persinv[0][2] + curareaY * v3d->persinv[1][2];
|
||||
VecAddf(v3d->ofs, v3d->ofs, dvec);
|
||||
|
||||
/*----------------------------------------------------
|
||||
* ndof device dolly
|
||||
*/
|
||||
len = zsens * sbadjust * fval[2];
|
||||
|
||||
if (v3d->persp==V3D_CAMOB) {
|
||||
if(v3d->persp==V3D_CAMOB) { /* This is stupid, please fix - TODO */
|
||||
v3d->camzoom+= 10.0f * -len;
|
||||
}
|
||||
if (v3d->camzoom < minZoom) v3d->camzoom = minZoom;
|
||||
else if (v3d->camzoom > maxZoom) v3d->camzoom = maxZoom;
|
||||
}
|
||||
else if ((v3d->dist> 0.001*v3d->grid) && (v3d->dist<10.0*v3d->far)) {
|
||||
v3d->dist*=(1.0 + len);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------
|
||||
* ndof device turntable
|
||||
* derived from the turntable code in viewmove
|
||||
*/
|
||||
|
||||
/* Get the 3x3 matrix and its inverse from the quaternion */
|
||||
QuatToMat3(v3d->viewquat, m);
|
||||
Mat3Inv(m_inv,m);
|
||||
|
||||
/* Determine the direction of the x vector (for rotating up and down) */
|
||||
/* This can likely be compuated directly from the quaternion. */
|
||||
Mat3MulVecfl(m_inv,xvec);
|
||||
Mat3MulVecfl(m_inv,yvec);
|
||||
Mat3MulVecfl(m_inv,zvec);
|
||||
|
||||
/* Perform the up/down rotation */
|
||||
phi = sbadjust * rsens * /*0.5f * */ fval[3]; /* spin vertically half as fast as horizontally */
|
||||
si = sin(phi);
|
||||
q1[0] = cos(phi);
|
||||
q1[1] = si * xvec[0];
|
||||
q1[2] = si * xvec[1];
|
||||
q1[3] = si * xvec[2];
|
||||
QuatMul(v3d->viewquat, v3d->viewquat, q1);
|
||||
|
||||
if (use_sel) {
|
||||
QuatConj(q1); /* conj == inv for unit quat */
|
||||
VecSubf(v3d->ofs, v3d->ofs, obofs);
|
||||
QuatMulVecf(q1, v3d->ofs);
|
||||
VecAddf(v3d->ofs, v3d->ofs, obofs);
|
||||
}
|
||||
|
||||
/* Perform the orbital rotation */
|
||||
/* Perform the orbital rotation
|
||||
If the seen Up axis is parallel to the zoom axis, rotation should be
|
||||
achieved with a pure Roll motion (no Spin) on the device. When you start
|
||||
to tilt, moving from Top to Side view, Spinning will increasingly become
|
||||
more relevant while the Roll component will decrease. When a full
|
||||
Side view is reached, rotations around the world's Up axis are achieved
|
||||
with a pure Spin-only motion. In other words the control of the spinning
|
||||
around the world's Up axis should move from the device's Spin axis to the
|
||||
device's Roll axis depending on the orientation of the world's Up axis
|
||||
relative to the screen. */
|
||||
//phi = sbadjust * rsens * reverse * fval[4]; /* spin the knob, y axis */
|
||||
phi = sbadjust * rsens * (yvec[2] * fval[4] + zvec[2] * fval[5]);
|
||||
q1[0] = cos(phi);
|
||||
q1[1] = q1[2] = 0.0;
|
||||
q1[3] = sin(phi);
|
||||
QuatMul(v3d->viewquat, v3d->viewquat, q1);
|
||||
|
||||
if (use_sel) {
|
||||
QuatConj(q1);
|
||||
VecSubf(v3d->ofs, v3d->ofs, obofs);
|
||||
QuatMulVecf(q1, v3d->ofs);
|
||||
VecAddf(v3d->ofs, v3d->ofs, obofs);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------
|
||||
* refresh the screen
|
||||
*/
|
||||
// XXX scrarea_do_windraw(curarea);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
|
||||
@@ -30,6 +30,11 @@
|
||||
|
||||
/* internal exports only */
|
||||
|
||||
struct wmWindow;
|
||||
struct BoundBox;
|
||||
struct Object;
|
||||
struct DerivedMesh;
|
||||
|
||||
typedef struct ViewDepths {
|
||||
unsigned short w, h;
|
||||
float *depths;
|
||||
@@ -43,34 +48,75 @@ typedef struct ViewDepths {
|
||||
#define DRAW_CONSTCOLOR 2
|
||||
#define DRAW_SCENESET 4
|
||||
|
||||
#define V3D_XRAY 1
|
||||
#define V3D_TRANSP 2
|
||||
|
||||
/* project short */
|
||||
#define IS_CLIPPED 12000
|
||||
|
||||
/* view3d_header.c */
|
||||
void view3d_header_buttons(const bContext *C, ARegion *ar);
|
||||
|
||||
/* drawobject.c */
|
||||
void draw_object(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag);
|
||||
int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt);
|
||||
|
||||
/* drawmesh.c */
|
||||
void draw_mesh_textured(Scene *scene, View3D *v3d, Object *ob, struct DerivedMesh *dm, int faceselect);
|
||||
|
||||
/* view3d_draw.c */
|
||||
void drawview3dspace(const bContext *C, ARegion *ar, View3D *v3d);
|
||||
void draw_depth(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d, int (* func)(void *));
|
||||
int view3d_test_clipping(View3D *v3d, float *vec);
|
||||
void view3d_clr_clipping(void);
|
||||
void view3d_set_clipping(View3D *v3d);
|
||||
void add_view3d_after(View3D *v3d, Base *base, int type, int flag);
|
||||
void make_axis_color(char *col, char *col2, char axis);
|
||||
|
||||
void circf(float x, float y, float rad);
|
||||
void circ(float x, float y, float rad);
|
||||
void view3d_update_depths(ARegion *ar, View3D *v3d);
|
||||
|
||||
/* view3d_view.c */
|
||||
float *give_cursor(Scene *scene, View3D *v3d);
|
||||
void viewline(ARegion *ar, View3D *v3d, short mval[2], float ray_start[3], float ray_end[3]);
|
||||
void viewray(ARegion *ar, View3D *v3d, short mval[2], float ray_start[3], float ray_normal[3]);
|
||||
|
||||
void initgrabz(View3D *v3d, float x, float y, float z);
|
||||
void window_to_3d(ARegion *ar, View3D *v3d, float *vec, short mx, short my);
|
||||
int boundbox_clip(View3D *v3d, float obmat[][4], struct BoundBox *bb);
|
||||
|
||||
void view3d_project_short_clip(ARegion *ar, View3D *v3d, float *vec, short *adr, float projmat[4][4], float wmat[4][4]);
|
||||
void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr, float mat[4][4]);
|
||||
void view3d_project_float(ARegion *a, float *vec, float *adr, float mat[4][4]);
|
||||
void view3d_get_object_project_mat(View3D *v3d, struct Object *ob, float pmat[4][4], float vmat[4][4]);
|
||||
void view3d_project_float(ARegion *ar, float *vec, float *adr, float mat[4][4]);
|
||||
|
||||
void project_short(ARegion *ar, View3D *v3d, float *vec, short *adr);
|
||||
void project_int(ARegion *ar, View3D *v3d, float *vec, int *adr);
|
||||
void project_int_noclip(ARegion *ar, View3D *v3d, float *vec, int *adr);
|
||||
void project_short_noclip(ARegion *ar, View3D *v3d, float *vec, short *adr);
|
||||
void project_float(ARegion *ar, View3D *v3d, float *vec, float *adr);
|
||||
void project_float_noclip(ARegion *ar, View3D *v3d, float *vec, float *adr);
|
||||
|
||||
int get_view3d_viewplane(View3D *v3d, int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize);
|
||||
void view_settings_from_ob(Object *ob, float *ofs, float *quat, float *dist, float *lens);
|
||||
void obmat_to_viewmat(View3D *v3d, Object *ob, short smooth);
|
||||
|
||||
short view3d_opengl_select(bContext *C, Scene *scene, ARegion *ar, View3D *v3d, unsigned int *buffer, unsigned int bufsize, rcti *input);
|
||||
void initlocalview(Scene *scene, ARegion *ar, View3D *v3d);
|
||||
void restore_localviewdata(View3D *vd);
|
||||
void endlocalview(Scene *scene, ScrArea *sa);
|
||||
|
||||
void setwinmatrixview3d(wmWindow *win, View3D *v3d, int winx, int winy, rctf *rect); /* rect: for picking */
|
||||
void centerview(ARegion *ar, View3D *v3d);
|
||||
void view3d_home(View3D *v3d, ARegion *ar, int center);
|
||||
|
||||
void view3d_align_axis_to_vector(View3D *v3d, int axisidx, float vec[3]);
|
||||
|
||||
void smooth_view(View3D *v3d, float *ofs, float *quat, float *dist, float *lens);
|
||||
void smooth_view_to_camera(View3D *v3d);
|
||||
|
||||
void setwinmatrixview3d(struct wmWindow *win, View3D *v3d, int winx, int winy, rctf *rect); /* rect: for picking */
|
||||
void setviewmatrixview3d(View3D *v3d);
|
||||
|
||||
#endif /* ED_VIEW3D_INTERN_H */
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <float.h>
|
||||
|
||||
#include "DNA_action_types.h"
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_lamp_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
@@ -48,10 +49,12 @@
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_rand.h"
|
||||
|
||||
#include "BKE_anim.h"
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_utildefines.h"
|
||||
@@ -72,6 +75,7 @@
|
||||
|
||||
#include "view3d_intern.h" // own include
|
||||
|
||||
#define BL_NEAR_CLIP 0.001
|
||||
|
||||
float *give_cursor(Scene *scene, View3D *v3d)
|
||||
{
|
||||
@@ -79,6 +83,49 @@ float *give_cursor(Scene *scene, View3D *v3d)
|
||||
else return scene->cursor;
|
||||
}
|
||||
|
||||
/* create intersection coordinates in view Z direction at mouse coordinates */
|
||||
void viewline(ARegion *ar, View3D *v3d, short mval[2], float ray_start[3], float ray_end[3])
|
||||
{
|
||||
float vec[4];
|
||||
|
||||
if(v3d->persp != V3D_ORTHO){
|
||||
vec[0]= 2.0f * mval[0] / ar->winx - 1;
|
||||
vec[1]= 2.0f * mval[1] / ar->winy - 1;
|
||||
vec[2]= -1.0f;
|
||||
vec[3]= 1.0f;
|
||||
|
||||
Mat4MulVec4fl(v3d->persinv, vec);
|
||||
VecMulf(vec, 1.0f / vec[3]);
|
||||
|
||||
VECCOPY(ray_start, v3d->viewinv[3]);
|
||||
VECSUB(vec, vec, ray_start);
|
||||
Normalize(vec);
|
||||
|
||||
VECADDFAC(ray_start, v3d->viewinv[3], vec, v3d->near);
|
||||
VECADDFAC(ray_end, v3d->viewinv[3], vec, v3d->far);
|
||||
}
|
||||
else {
|
||||
vec[0] = 2.0f * mval[0] / ar->winx - 1;
|
||||
vec[1] = 2.0f * mval[1] / ar->winy - 1;
|
||||
vec[2] = 0.0f;
|
||||
vec[3] = 1.0f;
|
||||
|
||||
Mat4MulVec4fl(v3d->persinv, vec);
|
||||
|
||||
VECADDFAC(ray_start, vec, v3d->viewinv[2], 1000.0f);
|
||||
VECADDFAC(ray_end, vec, v3d->viewinv[2], -1000.0f);
|
||||
}
|
||||
}
|
||||
|
||||
/* create intersection ray in view Z direction at mouse coordinates */
|
||||
void viewray(ARegion *ar, View3D *v3d, short mval[2], float ray_start[3], float ray_normal[3])
|
||||
{
|
||||
float ray_end[3];
|
||||
|
||||
viewline(ar, v3d, mval, ray_start, ray_end);
|
||||
VecSubf(ray_normal, ray_end, ray_start);
|
||||
Normalize(ray_normal);
|
||||
}
|
||||
|
||||
|
||||
void initgrabz(View3D *v3d, float x, float y, float z)
|
||||
@@ -110,6 +157,75 @@ void window_to_3d(ARegion *ar, View3D *v3d, float *vec, short mx, short my)
|
||||
vec[2]= (v3d->persinv[0][2]*dx + v3d->persinv[1][2]*dy);
|
||||
}
|
||||
|
||||
void view3d_get_object_project_mat(View3D *v3d, Object *ob, float pmat[4][4], float vmat[4][4])
|
||||
{
|
||||
Mat4MulMat4(vmat, ob->obmat, v3d->viewmat);
|
||||
Mat4MulMat4(pmat, vmat, v3d->winmat);
|
||||
Mat4CpyMat4(vmat, ob->obmat);
|
||||
}
|
||||
|
||||
/* projectmat brings it to window coords, wmat to rotated world space */
|
||||
void view3d_project_short_clip(ARegion *ar, View3D *v3d, float *vec, short *adr, float projmat[4][4], float wmat[4][4])
|
||||
{
|
||||
float fx, fy, vec4[4];
|
||||
|
||||
adr[0]= IS_CLIPPED;
|
||||
|
||||
/* clipplanes in eye space */
|
||||
if(v3d->flag & V3D_CLIPPING) {
|
||||
VECCOPY(vec4, vec);
|
||||
Mat4MulVecfl(wmat, vec4);
|
||||
if(view3d_test_clipping(v3d, vec4))
|
||||
return;
|
||||
}
|
||||
|
||||
VECCOPY(vec4, vec);
|
||||
vec4[3]= 1.0;
|
||||
|
||||
Mat4MulVec4fl(projmat, vec4);
|
||||
|
||||
/* clipplanes in window space */
|
||||
if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */
|
||||
fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
|
||||
|
||||
if( fx>0 && fx<ar->winx) {
|
||||
|
||||
fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
|
||||
|
||||
if(fy>0.0 && fy< (float)ar->winy) {
|
||||
adr[0]= (short)floor(fx);
|
||||
adr[1]= (short)floor(fy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr, float mat[4][4])
|
||||
{
|
||||
float fx, fy, vec4[4];
|
||||
|
||||
adr[0]= IS_CLIPPED;
|
||||
|
||||
VECCOPY(vec4, vec);
|
||||
vec4[3]= 1.0;
|
||||
|
||||
Mat4MulVec4fl(mat, vec4);
|
||||
|
||||
if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */
|
||||
fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
|
||||
|
||||
if( fx>-32700 && fx<32700) {
|
||||
|
||||
fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
|
||||
|
||||
if(fy>-32700.0 && fy<32700.0) {
|
||||
adr[0]= (short)floor(fx);
|
||||
adr[1]= (short)floor(fy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void view3d_project_float(ARegion *ar, float *vec, float *adr, float mat[4][4])
|
||||
{
|
||||
float vec4[4];
|
||||
@@ -128,8 +244,40 @@ void view3d_project_float(ARegion *ar, float *vec, float *adr, float mat[4][4])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define BL_NEAR_CLIP 0.001
|
||||
int boundbox_clip(View3D *v3d, float obmat[][4], BoundBox *bb)
|
||||
{
|
||||
/* return 1: draw */
|
||||
|
||||
float mat[4][4];
|
||||
float vec[4], min, max;
|
||||
int a, flag= -1, fl;
|
||||
|
||||
if(bb==NULL) return 1;
|
||||
if(bb->flag & OB_BB_DISABLED) return 1;
|
||||
|
||||
Mat4MulMat4(mat, obmat, v3d->persmat);
|
||||
|
||||
for(a=0; a<8; a++) {
|
||||
VECCOPY(vec, bb->vec[a]);
|
||||
vec[3]= 1.0;
|
||||
Mat4MulVec4fl(mat, vec);
|
||||
max= vec[3];
|
||||
min= -vec[3];
|
||||
|
||||
fl= 0;
|
||||
if(vec[0] < min) fl+= 1;
|
||||
if(vec[0] > max) fl+= 2;
|
||||
if(vec[1] < min) fl+= 4;
|
||||
if(vec[1] > max) fl+= 8;
|
||||
if(vec[2] < min) fl+= 16;
|
||||
if(vec[2] > max) fl+= 32;
|
||||
|
||||
flag &= fl;
|
||||
if(flag==0) return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void project_short(ARegion *ar, View3D *v3d, float *vec, short *adr) /* clips */
|
||||
{
|
||||
@@ -427,125 +575,9 @@ void setwinmatrixview3d(wmWindow *win, View3D *v3d, int winx, int winy, rctf *re
|
||||
}
|
||||
|
||||
|
||||
/* SMOOTHVIEW */
|
||||
void smooth_view(View3D *v3d, float *ofs, float *quat, float *dist, float *lens)
|
||||
{
|
||||
/* View Animation enabled */
|
||||
if (U.smooth_viewtx) {
|
||||
int i;
|
||||
char changed = 0;
|
||||
float step = 0.0, step_inv;
|
||||
float orig_dist;
|
||||
float orig_lens;
|
||||
float orig_quat[4];
|
||||
float orig_ofs[3];
|
||||
|
||||
double time_allowed, time_current, time_start;
|
||||
|
||||
/* if there is no difference, return */
|
||||
changed = 0; /* zero means no difference */
|
||||
if (dist) {
|
||||
if ((*dist) != v3d->dist)
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
if (lens) {
|
||||
if ((*lens) != v3d->lens)
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
if (!changed && ofs) {
|
||||
if ((ofs[0]!=v3d->ofs[0]) ||
|
||||
(ofs[1]!=v3d->ofs[1]) ||
|
||||
(ofs[2]!=v3d->ofs[2]) )
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
if (!changed && quat ) {
|
||||
if ((quat[0]!=v3d->viewquat[0]) ||
|
||||
(quat[1]!=v3d->viewquat[1]) ||
|
||||
(quat[2]!=v3d->viewquat[2]) ||
|
||||
(quat[3]!=v3d->viewquat[3]) )
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
/* The new view is different from the old one
|
||||
* so animate the view */
|
||||
if (changed) {
|
||||
|
||||
/* store original values */
|
||||
VECCOPY(orig_ofs, v3d->ofs);
|
||||
QUATCOPY(orig_quat, v3d->viewquat);
|
||||
orig_dist = v3d->dist;
|
||||
orig_lens = v3d->lens;
|
||||
|
||||
time_allowed= (float)U.smooth_viewtx / 1000.0;
|
||||
time_current = time_start = PIL_check_seconds_timer();
|
||||
|
||||
/* if this is view rotation only
|
||||
* we can decrease the time allowed by
|
||||
* the angle between quats
|
||||
* this means small rotations wont lag */
|
||||
if (quat && !ofs && !dist) {
|
||||
float vec1[3], vec2[3];
|
||||
VECCOPY(vec1, quat);
|
||||
VECCOPY(vec2, v3d->viewquat);
|
||||
Normalize(vec1);
|
||||
Normalize(vec2);
|
||||
/* scale the time allowed by the rotation */
|
||||
time_allowed *= NormalizedVecAngle2(vec1, vec2)/(M_PI/2);
|
||||
}
|
||||
|
||||
while (time_start + time_allowed > time_current) {
|
||||
|
||||
step = (float)((time_current-time_start) / time_allowed);
|
||||
|
||||
/* ease in/out */
|
||||
if (step < 0.5) step = (float)pow(step*2, 2)/2;
|
||||
else step = (float)1-(pow(2*(1-step),2)/2);
|
||||
|
||||
step_inv = 1-step;
|
||||
|
||||
if (ofs)
|
||||
for (i=0; i<3; i++)
|
||||
v3d->ofs[i] = ofs[i]*step + orig_ofs[i]*step_inv;
|
||||
|
||||
|
||||
if (quat)
|
||||
QuatInterpol(v3d->viewquat, orig_quat, quat, step);
|
||||
|
||||
if (dist)
|
||||
v3d->dist = ((*dist)*step) + (orig_dist*step_inv);
|
||||
|
||||
if (lens)
|
||||
v3d->lens = ((*lens)*step) + (orig_lens*step_inv);
|
||||
|
||||
/*redraw the view*/
|
||||
// scrarea_do_windraw(ar);
|
||||
// screen_swapbuffers();
|
||||
|
||||
time_current= PIL_check_seconds_timer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* set these values even if animation is enabled because flaot
|
||||
* error will make then not quite accurate */
|
||||
if (ofs)
|
||||
VECCOPY(v3d->ofs, ofs);
|
||||
if (quat)
|
||||
QUATCOPY(v3d->viewquat, quat);
|
||||
if (dist)
|
||||
v3d->dist = *dist;
|
||||
if (lens)
|
||||
v3d->lens = *lens;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Gets the lens and clipping values from a camera of lamp type object */
|
||||
void object_view_settings(Object *ob, float *lens, float *clipsta, float *clipend)
|
||||
static void object_view_settings(Object *ob, float *lens, float *clipsta, float *clipend)
|
||||
{
|
||||
if (!ob) return;
|
||||
|
||||
@@ -712,3 +744,674 @@ void setcameratoview3d(View3D *v3d)
|
||||
/*}*/
|
||||
v3d->viewquat[0]= -v3d->viewquat[0];
|
||||
}
|
||||
|
||||
|
||||
/* IGLuint-> GLuint*/
|
||||
/* Warning: be sure to account for a negative return value
|
||||
* This is an error, "Too many objects in select buffer"
|
||||
* and no action should be taken (can crash blender) if this happens
|
||||
*/
|
||||
short view3d_opengl_select(bContext *C, Scene *scene, ARegion *ar, View3D *v3d, unsigned int *buffer, unsigned int bufsize, rcti *input)
|
||||
{
|
||||
rctf rect;
|
||||
short code, hits;
|
||||
|
||||
G.f |= G_PICKSEL;
|
||||
|
||||
/* case not a border select */
|
||||
if(input->xmin==input->xmax) {
|
||||
rect.xmin= input->xmin-12; // seems to be default value for bones only now
|
||||
rect.xmax= input->xmin+12;
|
||||
rect.ymin= input->ymin-12;
|
||||
rect.ymax= input->xmin+12;
|
||||
}
|
||||
else {
|
||||
rect.xmin= input->xmin;
|
||||
rect.xmax= input->xmax;
|
||||
rect.ymin= input->ymin;
|
||||
rect.ymax= input->ymax;
|
||||
}
|
||||
|
||||
/* get rid of overlay button matrix XXX ?*/
|
||||
setwinmatrixview3d(CTX_wm_window(C), v3d, ar->winx, ar->winy, &rect);
|
||||
Mat4MulMat4(v3d->persmat, v3d->viewmat, v3d->winmat);
|
||||
|
||||
if(v3d->drawtype > OB_WIRE) {
|
||||
v3d->zbuf= TRUE;
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
if(v3d->flag & V3D_CLIPPING)
|
||||
view3d_set_clipping(v3d);
|
||||
|
||||
glSelectBuffer( bufsize, (GLuint *)buffer);
|
||||
glRenderMode(GL_SELECT);
|
||||
glInitNames(); /* these two calls whatfor? It doesnt work otherwise */
|
||||
glPushName(-1);
|
||||
code= 1;
|
||||
|
||||
if(G.obedit && G.obedit->type==OB_MBALL) {
|
||||
draw_object(C, scene, ar, v3d, BASACT, DRAW_PICKING|DRAW_CONSTCOLOR);
|
||||
}
|
||||
else if ((G.obedit && G.obedit->type==OB_ARMATURE)) {
|
||||
draw_object(C, scene, ar, v3d, BASACT, DRAW_PICKING|DRAW_CONSTCOLOR);
|
||||
}
|
||||
else {
|
||||
Base *base;
|
||||
|
||||
v3d->xray= TRUE; // otherwise it postpones drawing
|
||||
for(base= scene->base.first; base; base= base->next) {
|
||||
if(base->lay & v3d->lay) {
|
||||
|
||||
if (base->object->restrictflag & OB_RESTRICT_SELECT)
|
||||
base->selcol= 0;
|
||||
else {
|
||||
base->selcol= code;
|
||||
glLoadName(code);
|
||||
draw_object(C, scene, ar, v3d, base, DRAW_PICKING|DRAW_CONSTCOLOR);
|
||||
|
||||
/* we draw group-duplicators for selection too */
|
||||
if((base->object->transflag & OB_DUPLI) && base->object->dup_group) {
|
||||
ListBase *lb;
|
||||
DupliObject *dob;
|
||||
Base tbase;
|
||||
|
||||
tbase.flag= OB_FROMDUPLI;
|
||||
lb= object_duplilist(scene, base->object);
|
||||
|
||||
for(dob= lb->first; dob; dob= dob->next) {
|
||||
tbase.object= dob->ob;
|
||||
Mat4CpyMat4(dob->ob->obmat, dob->mat);
|
||||
|
||||
draw_object(C, scene, ar, v3d, &tbase, DRAW_PICKING|DRAW_CONSTCOLOR);
|
||||
|
||||
Mat4CpyMat4(dob->ob->obmat, dob->omat);
|
||||
}
|
||||
free_object_duplilist(lb);
|
||||
}
|
||||
code++;
|
||||
}
|
||||
}
|
||||
}
|
||||
v3d->xray= FALSE; // restore
|
||||
}
|
||||
|
||||
glPopName(); /* see above (pushname) */
|
||||
hits= glRenderMode(GL_RENDER);
|
||||
|
||||
G.f &= ~G_PICKSEL;
|
||||
setwinmatrixview3d(CTX_wm_window(C), v3d, ar->winx, ar->winy, NULL);
|
||||
Mat4MulMat4(v3d->persmat, v3d->viewmat, v3d->winmat);
|
||||
|
||||
if(v3d->drawtype > OB_WIRE) {
|
||||
v3d->zbuf= 0;
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
// XXX persp(PERSP_WIN);
|
||||
|
||||
if(v3d->flag & V3D_CLIPPING)
|
||||
view3d_clr_clipping();
|
||||
|
||||
if(hits<0) printf("Too many objects in select buffer\n"); // XXX make error message
|
||||
|
||||
return hits;
|
||||
}
|
||||
|
||||
// XXX solve: localview on region level? no.... layers are area, so all regions in area have to be set
|
||||
static unsigned int free_localbit(void)
|
||||
{
|
||||
unsigned int lay;
|
||||
ScrArea *sa;
|
||||
bScreen *sc;
|
||||
|
||||
lay= 0;
|
||||
|
||||
/* sometimes we loose a localview: when an area is closed */
|
||||
/* check all areas: which localviews are in use? */
|
||||
for(sc= G.main->screen.first; sc; sc= sc->id.next) {
|
||||
for(sa= sc->areabase.first; sa; sa= sa->next) {
|
||||
SpaceLink *sl= sa->spacedata.first;
|
||||
for(; sl; sl= sl->next) {
|
||||
if(sl->spacetype==SPACE_VIEW3D) {
|
||||
View3D *v3d= (View3D*) sl;
|
||||
lay |= v3d->lay;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( (lay & 0x01000000)==0) return 0x01000000;
|
||||
if( (lay & 0x02000000)==0) return 0x02000000;
|
||||
if( (lay & 0x04000000)==0) return 0x04000000;
|
||||
if( (lay & 0x08000000)==0) return 0x08000000;
|
||||
if( (lay & 0x10000000)==0) return 0x10000000;
|
||||
if( (lay & 0x20000000)==0) return 0x20000000;
|
||||
if( (lay & 0x40000000)==0) return 0x40000000;
|
||||
if( (lay & 0x80000000)==0) return 0x80000000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void initlocalview(Scene *scene, ARegion *ar, View3D *v3d)
|
||||
{
|
||||
Base *base;
|
||||
float size = 0.0, min[3], max[3], afm[3];
|
||||
unsigned int locallay;
|
||||
int ok=0;
|
||||
|
||||
if(v3d->localvd) return;
|
||||
|
||||
INIT_MINMAX(min, max);
|
||||
|
||||
locallay= free_localbit();
|
||||
|
||||
if(locallay==0) {
|
||||
printf("Sorry, no more than 8 localviews\n"); // XXX error
|
||||
ok= 0;
|
||||
}
|
||||
else {
|
||||
if(G.obedit) {
|
||||
minmax_object(G.obedit, min, max);
|
||||
|
||||
ok= 1;
|
||||
|
||||
BASACT->lay |= locallay;
|
||||
G.obedit->lay= BASACT->lay;
|
||||
}
|
||||
else {
|
||||
base= FIRSTBASE;
|
||||
while(base) {
|
||||
if TESTBASE(base) {
|
||||
minmax_object(base->object, min, max);
|
||||
base->lay |= locallay;
|
||||
base->object->lay= base->lay;
|
||||
ok= 1;
|
||||
}
|
||||
base= base->next;
|
||||
}
|
||||
}
|
||||
|
||||
afm[0]= (max[0]-min[0]);
|
||||
afm[1]= (max[1]-min[1]);
|
||||
afm[2]= (max[2]-min[2]);
|
||||
size= 0.7*MAX3(afm[0], afm[1], afm[2]);
|
||||
if(size<=0.01) size= 0.01;
|
||||
}
|
||||
|
||||
if(ok) {
|
||||
v3d->localvd= MEM_mallocN(sizeof(View3D), "localview");
|
||||
memcpy(v3d->localvd, v3d, sizeof(View3D));
|
||||
|
||||
v3d->ofs[0]= -(min[0]+max[0])/2.0;
|
||||
v3d->ofs[1]= -(min[1]+max[1])/2.0;
|
||||
v3d->ofs[2]= -(min[2]+max[2])/2.0;
|
||||
|
||||
v3d->dist= size;
|
||||
|
||||
// correction for window aspect ratio
|
||||
if(ar->winy>2 && ar->winx>2) {
|
||||
size= (float)ar->winx/(float)ar->winy;
|
||||
if(size<1.0) size= 1.0/size;
|
||||
v3d->dist*= size;
|
||||
}
|
||||
|
||||
if (v3d->persp==V3D_CAMOB) v3d->persp= V3D_PERSP;
|
||||
if (v3d->near> 0.1) v3d->near= 0.1;
|
||||
|
||||
v3d->cursor[0]= -v3d->ofs[0];
|
||||
v3d->cursor[1]= -v3d->ofs[1];
|
||||
v3d->cursor[2]= -v3d->ofs[2];
|
||||
|
||||
v3d->lay= locallay;
|
||||
|
||||
// XXX countall();
|
||||
// XXX scrarea_queue_winredraw(curarea);
|
||||
}
|
||||
else {
|
||||
/* clear flags */
|
||||
base= FIRSTBASE;
|
||||
while(base) {
|
||||
if( base->lay & locallay ) {
|
||||
base->lay-= locallay;
|
||||
if(base->lay==0) base->lay= v3d->layact;
|
||||
if(base->object != G.obedit) base->flag |= SELECT;
|
||||
base->object->lay= base->lay;
|
||||
}
|
||||
base= base->next;
|
||||
}
|
||||
// XXX scrarea_queue_headredraw(curarea);
|
||||
|
||||
v3d->localview= 0;
|
||||
}
|
||||
// XXX BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT);
|
||||
}
|
||||
|
||||
void centerview(ARegion *ar, View3D *v3d) /* like a localview without local! */
|
||||
{
|
||||
Object *ob= OBACT;
|
||||
float size, min[3], max[3], afm[3];
|
||||
int ok=0;
|
||||
|
||||
/* SMOOTHVIEW */
|
||||
float new_ofs[3];
|
||||
float new_dist;
|
||||
|
||||
INIT_MINMAX(min, max);
|
||||
|
||||
if (G.f & G_WEIGHTPAINT) {
|
||||
/* hardcoded exception, we look for the one selected armature */
|
||||
/* this is weak code this way, we should make a generic active/selection callback interface once... */
|
||||
Base *base;
|
||||
for(base=FIRSTBASE; base; base= base->next) {
|
||||
if(TESTBASELIB(base)) {
|
||||
if(base->object->type==OB_ARMATURE)
|
||||
if(base->object->flag & OB_POSEMODE)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(base)
|
||||
ob= base->object;
|
||||
}
|
||||
|
||||
|
||||
if(G.obedit) {
|
||||
// XXX ok = minmax_verts(min, max); /* only selected */
|
||||
}
|
||||
else if(ob && (ob->flag & OB_POSEMODE)) {
|
||||
if(ob->pose) {
|
||||
bArmature *arm= ob->data;
|
||||
bPoseChannel *pchan;
|
||||
float vec[3];
|
||||
|
||||
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
|
||||
if(pchan->bone->flag & BONE_SELECTED) {
|
||||
if(pchan->bone->layer & arm->layer) {
|
||||
ok= 1;
|
||||
VECCOPY(vec, pchan->pose_head);
|
||||
Mat4MulVecfl(ob->obmat, vec);
|
||||
DO_MINMAX(vec, min, max);
|
||||
VECCOPY(vec, pchan->pose_tail);
|
||||
Mat4MulVecfl(ob->obmat, vec);
|
||||
DO_MINMAX(vec, min, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (FACESEL_PAINT_TEST) {
|
||||
// XXX ok= minmax_tface(min, max);
|
||||
}
|
||||
else if (G.f & G_PARTICLEEDIT) {
|
||||
// XXX ok= PE_minmax(min, max);
|
||||
}
|
||||
else {
|
||||
Base *base= FIRSTBASE;
|
||||
while(base) {
|
||||
if TESTBASE(base) {
|
||||
minmax_object(base->object, min, max);
|
||||
/* account for duplis */
|
||||
minmax_object_duplis(base->object, min, max);
|
||||
|
||||
ok= 1;
|
||||
}
|
||||
base= base->next;
|
||||
}
|
||||
}
|
||||
|
||||
if(ok==0) return;
|
||||
|
||||
afm[0]= (max[0]-min[0]);
|
||||
afm[1]= (max[1]-min[1]);
|
||||
afm[2]= (max[2]-min[2]);
|
||||
size= 0.7f*MAX3(afm[0], afm[1], afm[2]);
|
||||
|
||||
if(size <= v3d->near*1.5f) size= v3d->near*1.5f;
|
||||
|
||||
new_ofs[0]= -(min[0]+max[0])/2.0f;
|
||||
new_ofs[1]= -(min[1]+max[1])/2.0f;
|
||||
new_ofs[2]= -(min[2]+max[2])/2.0f;
|
||||
|
||||
new_dist = size;
|
||||
|
||||
/* correction for window aspect ratio */
|
||||
if(ar->winy>2 && ar->winx>2) {
|
||||
size= (float)ar->winx/(float)ar->winy;
|
||||
if(size<1.0f) size= 1.0f/size;
|
||||
new_dist*= size;
|
||||
}
|
||||
|
||||
v3d->cursor[0]= -new_ofs[0];
|
||||
v3d->cursor[1]= -new_ofs[1];
|
||||
v3d->cursor[2]= -new_ofs[2];
|
||||
|
||||
if (v3d->persp==V3D_CAMOB && v3d->camera) {
|
||||
float orig_lens= v3d->lens;
|
||||
|
||||
v3d->persp=V3D_PERSP;
|
||||
v3d->dist= 0.0f;
|
||||
view_settings_from_ob(v3d->camera, v3d->ofs, NULL, NULL, &v3d->lens);
|
||||
smooth_view(v3d, new_ofs, NULL, &new_dist, &orig_lens);
|
||||
} else {
|
||||
if(v3d->persp==V3D_CAMOB)
|
||||
v3d->persp= V3D_PERSP;
|
||||
|
||||
smooth_view(v3d, new_ofs, NULL, &new_dist, NULL);
|
||||
}
|
||||
// XXX scrarea_queue_winredraw(curarea);
|
||||
// XXX BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void restore_localviewdata(View3D *vd)
|
||||
{
|
||||
if(vd->localvd==0) return;
|
||||
|
||||
VECCOPY(vd->ofs, vd->localvd->ofs);
|
||||
vd->dist= vd->localvd->dist;
|
||||
vd->persp= vd->localvd->persp;
|
||||
vd->view= vd->localvd->view;
|
||||
vd->near= vd->localvd->near;
|
||||
vd->far= vd->localvd->far;
|
||||
vd->lay= vd->localvd->lay;
|
||||
vd->layact= vd->localvd->layact;
|
||||
vd->drawtype= vd->localvd->drawtype;
|
||||
vd->camera= vd->localvd->camera;
|
||||
QUATCOPY(vd->viewquat, vd->localvd->viewquat);
|
||||
|
||||
}
|
||||
|
||||
void endlocalview(Scene *scene, ScrArea *sa)
|
||||
{
|
||||
View3D *v3d;
|
||||
struct Base *base;
|
||||
unsigned int locallay;
|
||||
|
||||
if(sa->spacetype!=SPACE_VIEW3D) return;
|
||||
v3d= sa->spacedata.first;
|
||||
|
||||
if(v3d->localvd) {
|
||||
|
||||
locallay= v3d->lay & 0xFF000000;
|
||||
|
||||
restore_localviewdata(v3d);
|
||||
|
||||
MEM_freeN(v3d->localvd);
|
||||
v3d->localvd= 0;
|
||||
v3d->localview= 0;
|
||||
|
||||
/* for when in other window the layers have changed */
|
||||
if(v3d->scenelock) v3d->lay= scene->lay;
|
||||
|
||||
base= FIRSTBASE;
|
||||
while(base) {
|
||||
if( base->lay & locallay ) {
|
||||
base->lay-= locallay;
|
||||
if(base->lay==0) base->lay= v3d->layact;
|
||||
if(base->object != G.obedit) {
|
||||
base->flag |= SELECT;
|
||||
base->object->flag |= SELECT;
|
||||
}
|
||||
base->object->lay= base->lay;
|
||||
}
|
||||
base= base->next;
|
||||
}
|
||||
|
||||
// XXX countall();
|
||||
// XXX allqueue(REDRAWVIEW3D, 0); /* because of select */
|
||||
// XXX allqueue(REDRAWOOPS, 0); /* because of select */
|
||||
// XXX BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT);
|
||||
}
|
||||
}
|
||||
|
||||
void view3d_home(View3D *v3d, ARegion *ar, int center)
|
||||
{
|
||||
Base *base;
|
||||
float size, min[3], max[3], afm[3];
|
||||
int ok= 1, onedone=0;
|
||||
|
||||
if(center) {
|
||||
min[0]= min[1]= min[2]= 0.0f;
|
||||
max[0]= max[1]= max[2]= 0.0f;
|
||||
}
|
||||
else {
|
||||
INIT_MINMAX(min, max);
|
||||
}
|
||||
|
||||
for(base= FIRSTBASE; base; base= base->next) {
|
||||
if(base->lay & v3d->lay) {
|
||||
onedone= 1;
|
||||
minmax_object(base->object, min, max);
|
||||
}
|
||||
}
|
||||
if(!onedone) return;
|
||||
|
||||
afm[0]= (max[0]-min[0]);
|
||||
afm[1]= (max[1]-min[1]);
|
||||
afm[2]= (max[2]-min[2]);
|
||||
size= 0.7f*MAX3(afm[0], afm[1], afm[2]);
|
||||
if(size==0.0) ok= 0;
|
||||
|
||||
if(ok) {
|
||||
float new_dist;
|
||||
float new_ofs[3];
|
||||
|
||||
new_dist = size;
|
||||
new_ofs[0]= -(min[0]+max[0])/2.0f;
|
||||
new_ofs[1]= -(min[1]+max[1])/2.0f;
|
||||
new_ofs[2]= -(min[2]+max[2])/2.0f;
|
||||
|
||||
// correction for window aspect ratio
|
||||
if(ar->winy>2 && ar->winx>2) {
|
||||
size= (float)ar->winx/(float)ar->winy;
|
||||
if(size<1.0) size= 1.0f/size;
|
||||
new_dist*= size;
|
||||
}
|
||||
|
||||
if (v3d->persp==V3D_CAMOB && v3d->camera) {
|
||||
/* switch out of camera view */
|
||||
float orig_lens= v3d->lens;
|
||||
|
||||
v3d->persp= V3D_PERSP;
|
||||
v3d->dist= 0.0;
|
||||
view_settings_from_ob(v3d->camera, v3d->ofs, NULL, NULL, &v3d->lens);
|
||||
smooth_view(v3d, new_ofs, NULL, &new_dist, &orig_lens);
|
||||
|
||||
} else {
|
||||
if(v3d->persp==V3D_CAMOB) v3d->persp= V3D_PERSP;
|
||||
smooth_view(v3d, new_ofs, NULL, &new_dist, NULL);
|
||||
}
|
||||
// XXX scrarea_queue_winredraw(curarea);
|
||||
}
|
||||
// XXX BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT);
|
||||
|
||||
}
|
||||
|
||||
void view3d_align_axis_to_vector(View3D *v3d, int axisidx, float vec[3])
|
||||
{
|
||||
float alignaxis[3] = {0.0, 0.0, 0.0};
|
||||
float norm[3], axis[3], angle, new_quat[4];
|
||||
|
||||
if(axisidx > 0) alignaxis[axisidx-1]= 1.0;
|
||||
else alignaxis[-axisidx-1]= -1.0;
|
||||
|
||||
VECCOPY(norm, vec);
|
||||
Normalize(norm);
|
||||
|
||||
angle= (float)acos(Inpf(alignaxis, norm));
|
||||
Crossf(axis, alignaxis, norm);
|
||||
VecRotToQuat(axis, -angle, new_quat);
|
||||
|
||||
v3d->view= 0;
|
||||
|
||||
if (v3d->persp==V3D_CAMOB && v3d->camera) {
|
||||
/* switch out of camera view */
|
||||
float orig_ofs[3];
|
||||
float orig_dist= v3d->dist;
|
||||
float orig_lens= v3d->lens;
|
||||
|
||||
VECCOPY(orig_ofs, v3d->ofs);
|
||||
v3d->persp= V3D_PERSP;
|
||||
v3d->dist= 0.0;
|
||||
view_settings_from_ob(v3d->camera, v3d->ofs, NULL, NULL, &v3d->lens);
|
||||
smooth_view(v3d, orig_ofs, new_quat, &orig_dist, &orig_lens);
|
||||
} else {
|
||||
if (v3d->persp==V3D_CAMOB) v3d->persp= V3D_PERSP; /* switch out of camera mode */
|
||||
smooth_view(v3d, NULL, new_quat, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* SMOOTHVIEW */
|
||||
void smooth_view(View3D *v3d, float *ofs, float *quat, float *dist, float *lens)
|
||||
{
|
||||
/* View Animation enabled */
|
||||
if (U.smooth_viewtx) {
|
||||
int i;
|
||||
char changed = 0;
|
||||
float step = 0.0, step_inv;
|
||||
float orig_dist;
|
||||
float orig_lens;
|
||||
float orig_quat[4];
|
||||
float orig_ofs[3];
|
||||
|
||||
double time_allowed, time_current, time_start;
|
||||
|
||||
/* if there is no difference, return */
|
||||
changed = 0; /* zero means no difference */
|
||||
if (dist) {
|
||||
if ((*dist) != v3d->dist)
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
if (lens) {
|
||||
if ((*lens) != v3d->lens)
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
if (!changed && ofs) {
|
||||
if ((ofs[0]!=v3d->ofs[0]) ||
|
||||
(ofs[1]!=v3d->ofs[1]) ||
|
||||
(ofs[2]!=v3d->ofs[2]) )
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
if (!changed && quat ) {
|
||||
if ((quat[0]!=v3d->viewquat[0]) ||
|
||||
(quat[1]!=v3d->viewquat[1]) ||
|
||||
(quat[2]!=v3d->viewquat[2]) ||
|
||||
(quat[3]!=v3d->viewquat[3]) )
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
/* The new view is different from the old one
|
||||
* so animate the view */
|
||||
if (changed) {
|
||||
|
||||
/* store original values */
|
||||
VECCOPY(orig_ofs, v3d->ofs);
|
||||
QUATCOPY(orig_quat, v3d->viewquat);
|
||||
orig_dist = v3d->dist;
|
||||
orig_lens = v3d->lens;
|
||||
|
||||
time_allowed= (float)U.smooth_viewtx / 1000.0;
|
||||
time_current = time_start = PIL_check_seconds_timer();
|
||||
|
||||
/* if this is view rotation only
|
||||
* we can decrease the time allowed by
|
||||
* the angle between quats
|
||||
* this means small rotations wont lag */
|
||||
if (quat && !ofs && !dist) {
|
||||
float vec1[3], vec2[3];
|
||||
VECCOPY(vec1, quat);
|
||||
VECCOPY(vec2, v3d->viewquat);
|
||||
Normalize(vec1);
|
||||
Normalize(vec2);
|
||||
/* scale the time allowed by the rotation */
|
||||
time_allowed *= NormalizedVecAngle2(vec1, vec2)/(M_PI/2);
|
||||
}
|
||||
|
||||
while (time_start + time_allowed > time_current) {
|
||||
|
||||
step = (float)((time_current-time_start) / time_allowed);
|
||||
|
||||
/* ease in/out */
|
||||
if (step < 0.5) step = (float)pow(step*2, 2)/2;
|
||||
else step = (float)1-(pow(2*(1-step),2)/2);
|
||||
|
||||
step_inv = 1-step;
|
||||
|
||||
if (ofs)
|
||||
for (i=0; i<3; i++)
|
||||
v3d->ofs[i] = ofs[i]*step + orig_ofs[i]*step_inv;
|
||||
|
||||
|
||||
if (quat)
|
||||
QuatInterpol(v3d->viewquat, orig_quat, quat, step);
|
||||
|
||||
if (dist)
|
||||
v3d->dist = ((*dist)*step) + (orig_dist*step_inv);
|
||||
|
||||
if (lens)
|
||||
v3d->lens = ((*lens)*step) + (orig_lens*step_inv);
|
||||
|
||||
/*redraw the view*/
|
||||
// scrarea_do_windraw(ar);
|
||||
// screen_swapbuffers();
|
||||
|
||||
time_current= PIL_check_seconds_timer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* set these values even if animation is enabled because flaot
|
||||
* error will make then not quite accurate */
|
||||
if (ofs)
|
||||
VECCOPY(v3d->ofs, ofs);
|
||||
if (quat)
|
||||
QUATCOPY(v3d->viewquat, quat);
|
||||
if (dist)
|
||||
v3d->dist = *dist;
|
||||
if (lens)
|
||||
v3d->lens = *lens;
|
||||
|
||||
}
|
||||
|
||||
/* For use with smooth view
|
||||
*
|
||||
* the current view is unchanged, blend between the current view and the
|
||||
* camera view
|
||||
* */
|
||||
void smooth_view_to_camera(View3D *v3d)
|
||||
{
|
||||
if (!U.smooth_viewtx || !v3d->camera || v3d->persp != V3D_CAMOB) {
|
||||
return;
|
||||
} else {
|
||||
Object *ob = v3d->camera;
|
||||
|
||||
float orig_ofs[3];
|
||||
float orig_dist=v3d->dist;
|
||||
float orig_lens=v3d->lens;
|
||||
float new_dist=0.0;
|
||||
float new_lens=35.0;
|
||||
float new_quat[4];
|
||||
float new_ofs[3];
|
||||
|
||||
VECCOPY(orig_ofs, v3d->ofs);
|
||||
|
||||
view_settings_from_ob(ob, new_ofs, new_quat, NULL, &new_lens);
|
||||
|
||||
v3d->persp= V3D_PERSP;
|
||||
smooth_view(v3d, new_ofs, new_quat, &new_dist, &new_lens);
|
||||
VECCOPY(v3d->ofs, orig_ofs);
|
||||
v3d->lens= orig_lens;
|
||||
v3d->dist = orig_dist; /* restore the dist */
|
||||
|
||||
v3d->camera = ob;
|
||||
v3d->persp= V3D_CAMOB;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ sources = env.Glob('intern/*.c')
|
||||
incs = '. ../editors/include ../python ../makesdna ../blenlib ../blenkernel'
|
||||
incs += ' ../nodes ../imbuf ../blenloader ../render/extern/include'
|
||||
incs += ' ../ftfont ../radiosity/extern/include ../../kernel/gen_system'
|
||||
incs += ' ../makesrna'
|
||||
incs += ' ../makesrna ../gpu'
|
||||
|
||||
incs += ' #/intern/guardedalloc #/intern/memutil #/intern/ghost #/intern/bmfont'
|
||||
incs += ' #/intern/elbeem #/extern/glew/include'
|
||||
|
||||
@@ -138,6 +138,8 @@ void wmFrustum (wmWindow *win, float x1, float x2, float y1, float y2, float
|
||||
void wmOrtho (wmWindow *win, float x1, float x2, float y1, float y2, float n, float f);
|
||||
void wmOrtho2 (wmWindow *win, float x1, float x2, float y1, float y2);
|
||||
|
||||
/* utilities */
|
||||
void WM_set_framebuffer_index_color(int index);
|
||||
|
||||
#endif /* WM_API_H */
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ CPPFLAGS += -I../../blenkernel
|
||||
CPPFLAGS += -I../../nodes
|
||||
CPPFLAGS += -I../../imbuf
|
||||
CPPFLAGS += -I../../blenloader
|
||||
CPPFLAGS += -I../../gpu
|
||||
CPPFLAGS += -I../../render/extern/include
|
||||
CPPFLAGS += -I../../ftfont
|
||||
CPPFLAGS += -I../../radiosity/extern/include
|
||||
|
||||
@@ -69,8 +69,6 @@
|
||||
|
||||
#include "SYS_System.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
|
||||
#include "RNA_define.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
@@ -84,6 +82,12 @@
|
||||
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
|
||||
#include "GPU_extensions.h"
|
||||
#include "GPU_draw.h"
|
||||
|
||||
|
||||
static void initbuttons(void)
|
||||
{
|
||||
UI_init();
|
||||
@@ -135,7 +139,9 @@ void WM_init(bContext *C)
|
||||
|
||||
// XXX UI_filelist_init_icons();
|
||||
|
||||
// init_gl_stuff(); /* drawview.c, after homefile */
|
||||
GPU_state_init();
|
||||
GPU_extensions_init();
|
||||
|
||||
read_Blog();
|
||||
BLI_strncpy(G.lib, G.sce, FILE_MAX);
|
||||
}
|
||||
|
||||
@@ -445,7 +445,7 @@ static unsigned int index_to_framebuffer(int index)
|
||||
|
||||
#endif
|
||||
|
||||
void set_framebuffer_index_color(int index)
|
||||
void WM_set_framebuffer_index_color(int index)
|
||||
{
|
||||
cpack(index_to_framebuffer(index));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user