mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-12-11 21:31:30 +00:00
773eda1929
to work under GIMP 1.2.x -- at taniwha's urging, I am checking this into CVS. You need libgtk+ v1.2, libgtkglarea v5, libgimp v1.2 (or thereabouts) to get this to work.
423 lines
9.3 KiB
C
423 lines
9.3 KiB
C
/* Texture Paint
|
|
* Plug-in for the GIMP
|
|
*
|
|
* Copyright (C) 1998 Uwe Maurer <uwe_maurer@t-online.de>
|
|
*
|
|
* Based on GiMd2Viewer-0.1 (Quake2 model viewer) by
|
|
* Copyright (C) 1998 Lionel ULMER <bbrox@mygale.org>
|
|
* Copyright (C) 1997-1998 Janne Löf <jlof@student.oulu.fi>
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
|
|
#include "texturepaint.h"
|
|
|
|
|
|
void begingl(GtkWidget *glarea)
|
|
{
|
|
if (!gtk_gl_area_begingl(GTK_GL_AREA(glarea)))
|
|
{
|
|
gimp_message("gtk_gl_area_begingl failed()!");
|
|
gtk_main_quit();
|
|
}
|
|
}
|
|
|
|
void endgl(GtkWidget *glarea)
|
|
{
|
|
gtk_gl_area_endgl(GTK_GL_AREA(glarea));
|
|
}
|
|
|
|
gint expose(GtkWidget *widget, GdkEventExpose *event, gpointer data)
|
|
{
|
|
model_draw((ModelInfo*)data);
|
|
return TRUE;
|
|
}
|
|
|
|
gint resize(GtkWidget *widget, GdkEventConfigure *event,gpointer data)
|
|
{
|
|
if (!GTK_WIDGET_REALIZED(widget))
|
|
return TRUE;
|
|
|
|
begingl(widget);
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
gluPerspective(45.0,
|
|
(float) widget->allocation.width / widget->allocation.height,
|
|
0.1, 200.0);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glViewport(0, 0, widget->allocation.width, widget->allocation.height);
|
|
|
|
model_draw((ModelInfo *)data);
|
|
|
|
endgl(widget);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void BindTexture(ModelInfo *mdl,char *texdata,int w,int h)
|
|
{
|
|
|
|
DEBUG("%s %i",mdl->name,mdl->tex_image);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, mdl->texture);
|
|
set_parameter(mdl);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, 3, w, h, 0,
|
|
GL_RGB, GL_UNSIGNED_BYTE, texdata);
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
|
|
glBindTexture(GL_TEXTURE_2D,mdl->texture);
|
|
}
|
|
|
|
|
|
gint button_press_event(GtkWidget *widget, GdkEventButton *event,gpointer data)
|
|
{
|
|
ModelInfo *mdl;
|
|
|
|
mdl=(ModelInfo *)data;
|
|
|
|
if (event->type==GDK_2BUTTON_PRESS)
|
|
{
|
|
if (event->button==1)
|
|
on_paint_clicked(NULL,mdl);
|
|
else if (event->button==3)
|
|
on_generate_clicked(NULL,mdl);
|
|
|
|
}
|
|
|
|
if (event->button == 1)
|
|
{
|
|
mdl->M1_beginx = event->x;
|
|
mdl->M1_beginy = event->y;
|
|
trackball(mdl->lastquat,0,0,0,0);
|
|
} else if (event->button == 2)
|
|
{
|
|
mdl->M2_beginx = event->x;
|
|
mdl->M2_beginy = event->y;
|
|
} else if (event->button == 3)
|
|
{
|
|
mdl->M3_beginy = event->y;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
gint motion_notify_event(GtkWidget *widget, GdkEventMotion *event,
|
|
gpointer data)
|
|
{
|
|
int x, y;
|
|
int width,height;
|
|
GdkModifierType state;
|
|
ModelInfo *mdl;
|
|
|
|
|
|
mdl=(ModelInfo *)data;
|
|
|
|
width=widget->allocation.width;
|
|
height=widget->allocation.height;
|
|
|
|
if (event->is_hint)
|
|
{
|
|
gdk_window_get_pointer(event->window, &x, &y, &state);
|
|
} else
|
|
{
|
|
x=event->x;
|
|
y=event->y;
|
|
state = event->state;
|
|
}
|
|
|
|
if ((state & (GDK_BUTTON1_MASK|GDK_BUTTON2_MASK|GDK_BUTTON3_MASK))==0)
|
|
return TRUE;
|
|
|
|
|
|
if (state & GDK_BUTTON1_MASK)
|
|
{
|
|
trackball(mdl->lastquat,
|
|
(2.0 * mdl->M1_beginx - width) / width,
|
|
(height- 2.0 * mdl->M1_beginy) / height,
|
|
(2.0 * x - width) / width,
|
|
(height- 2.0 * y) / height);
|
|
mdl->M1_beginx = x;
|
|
mdl->M1_beginy = y;
|
|
add_quats(mdl->lastquat,mdl->curquat,mdl->curquat);
|
|
} else if (state & GDK_BUTTON2_MASK)
|
|
{
|
|
mdl->obj_Xpos += (mdl->obj_Zpos / -width) * (x - mdl->M2_beginx);
|
|
mdl->obj_Ypos -= (mdl->obj_Zpos / -height) * (y - mdl->M2_beginy);
|
|
|
|
mdl->M2_beginx = x;
|
|
mdl->M2_beginy = y;
|
|
|
|
} else if (state & GDK_BUTTON3_MASK)
|
|
{
|
|
mdl->obj_Zpos += (mdl->obj_Zpos / -height) * (y - mdl->M3_beginy);
|
|
mdl->M3_beginy = y;
|
|
}
|
|
|
|
model_draw(mdl);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void initgl(ModelInfo *mdl)
|
|
{
|
|
static int first_initgl=1;
|
|
GtkWidget *widget;
|
|
GLint data[4];
|
|
|
|
widget=mdl->glarea;
|
|
|
|
if (first_initgl)
|
|
{
|
|
glGetIntegerv(GL_MAX_TEXTURE_SIZE,data);
|
|
max_tex_size=data[0];
|
|
|
|
glGetIntegerv(GL_RED_BITS,data);
|
|
red_bits=data[0];
|
|
glGetIntegerv(GL_GREEN_BITS,data);
|
|
green_bits=data[0];
|
|
glGetIntegerv(GL_BLUE_BITS,data);
|
|
blue_bits=data[0];
|
|
|
|
red_shift = 8-red_bits;
|
|
green_shift = 8-green_bits;
|
|
blue_shift = 8-blue_bits;
|
|
|
|
first_initgl=0;
|
|
}
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
gluPerspective(45.0,
|
|
(float) widget->allocation.width / widget->allocation.height,
|
|
0.1, 200.0);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glEnable(GL_CULL_FACE);
|
|
glCullFace(GL_FRONT);
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glDisable(GL_DITHER);
|
|
glShadeModel(GL_FLAT);
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glGenTextures(1,&mdl->texture);
|
|
|
|
get_texture(mdl);
|
|
|
|
glViewport(0, 0, widget->allocation.width, widget->allocation.height);
|
|
}
|
|
|
|
|
|
void on_center_clicked(GtkButton *button, gpointer data)
|
|
{
|
|
ModelInfo *mdl;
|
|
|
|
if (data)
|
|
mdl=(ModelInfo *)data;
|
|
else
|
|
mdl=dialog->mdl;
|
|
|
|
if (mdl)
|
|
{
|
|
mdl->obj_Xpos = 0.0;
|
|
mdl->obj_Ypos = 0.0;
|
|
mdl->obj_Zpos = -2.0;
|
|
trackball(mdl->curquat,0,0,0,0);
|
|
trackball(mdl->lastquat,0,0,0,0);
|
|
model_draw(mdl);
|
|
}
|
|
}
|
|
|
|
void model_new(char *name,Model *model)
|
|
{
|
|
int attrList[]=
|
|
{ GDK_GL_RGBA, GDK_GL_DOUBLEBUFFER, GDK_GL_DEPTH_SIZE, 1, GDK_GL_NONE};
|
|
|
|
GtkWidget *glarea;
|
|
ModelInfo *mdl_info;
|
|
char str[256];
|
|
|
|
mdl_info=g_malloc(sizeof(ModelInfo));
|
|
memset(mdl_info,0,sizeof(ModelInfo));
|
|
|
|
mdl_info->name=strdup(name);
|
|
mdl_info->model=model;
|
|
|
|
mdl_info->tex_image=-1;
|
|
mdl_info->paint_image=-1;
|
|
mdl_info->idle=-1;
|
|
|
|
trackball(mdl_info->curquat,0,0,0,0);
|
|
trackball(mdl_info->lastquat,0,0,0,0);
|
|
|
|
mdl_info->obj_Zpos=-2;
|
|
|
|
mdl_info->first=0;
|
|
mdl_info->last=mdl_info->model->numframes-1;
|
|
mdl_info->frame=0;
|
|
mdl_info->timer=g_timer_new();
|
|
|
|
|
|
mdl_info->glwindow=create_glwindow();
|
|
|
|
strcpy(str,"3D Window - ");
|
|
strncat(str,name,200);
|
|
gtk_window_set_title(GTK_WINDOW(mdl_info->glwindow),str);
|
|
gtk_object_set_data(GTK_OBJECT(mdl_info->glwindow),MODEL_KEY,mdl_info);
|
|
|
|
glarea = gtk_gl_area_new(attrList);
|
|
mdl_info->glarea=glarea;
|
|
|
|
if (glarea == NULL) {
|
|
g_print("Can't create GtkGLArea widget\n");
|
|
gtk_exit(1);
|
|
}
|
|
gtk_widget_set_usize(glarea, 200, 200); /* Minimum size */
|
|
gtk_widget_set_events(glarea,
|
|
GDK_EXPOSURE_MASK |
|
|
GDK_BUTTON_PRESS_MASK |
|
|
GDK_BUTTON_RELEASE_MASK |
|
|
GDK_POINTER_MOTION_MASK |
|
|
GDK_POINTER_MOTION_HINT_MASK);
|
|
|
|
gtk_signal_connect(GTK_OBJECT(glarea), "expose_event",
|
|
GTK_SIGNAL_FUNC(expose), mdl_info);
|
|
|
|
/* when widgets size changes we want to change glViewport size to match it */
|
|
gtk_signal_connect(GTK_OBJECT(glarea), "configure_event",
|
|
GTK_SIGNAL_FUNC(resize), mdl_info);
|
|
/* virtual trackball */
|
|
gtk_signal_connect(GTK_OBJECT(glarea), "motion_notify_event",
|
|
GTK_SIGNAL_FUNC(motion_notify_event), mdl_info);
|
|
gtk_signal_connect(GTK_OBJECT(glarea), "button_press_event",
|
|
GTK_SIGNAL_FUNC(button_press_event), mdl_info);
|
|
|
|
gtk_container_add(GTK_CONTAINER(mdl_info->glwindow), glarea);
|
|
gtk_widget_show(mdl_info->glwindow);
|
|
gtk_widget_show(glarea);
|
|
gtk_widget_realize(glarea);
|
|
|
|
dialog->models_list=g_list_append(dialog->models_list,mdl_info);
|
|
|
|
update_models_menu(mdl_info);
|
|
}
|
|
|
|
void add_anim_button(GtkWidget *container,int num,char **pix)
|
|
{
|
|
GtkStyle *style;
|
|
GdkBitmap *mask;
|
|
GdkPixmap *gdkpix;
|
|
GtkWidget *gtkpix,*button;
|
|
|
|
button=gtk_button_new();
|
|
gtk_container_add(GTK_CONTAINER(container),button);
|
|
gtk_widget_realize(button);
|
|
style = gtk_widget_get_style(button);
|
|
gdkpix = gdk_pixmap_create_from_xpm_d(button->window,
|
|
&mask,
|
|
&style->bg[GTK_STATE_NORMAL],
|
|
pix);
|
|
gtkpix = gtk_pixmap_new(gdkpix, mask);
|
|
gtk_widget_show(gtkpix);
|
|
gtk_container_add(GTK_CONTAINER(button),gtkpix);
|
|
gtk_signal_connect(GTK_OBJECT(button),"clicked",
|
|
GTK_SIGNAL_FUNC(on_anim_clicked),GINT_TO_POINTER(num));
|
|
gtk_widget_show(button);
|
|
}
|
|
|
|
|
|
void display_model(ModelInfo *mdl,int mode)
|
|
{
|
|
GLfloat m[4][4];
|
|
int nextframe;
|
|
int frame;
|
|
float interp;
|
|
|
|
DEBUG("%s",mdl->name);
|
|
|
|
|
|
if (!GTK_WIDGET_REALIZED(mdl->glarea)) return;
|
|
|
|
if (mdl->model==NULL) return;
|
|
|
|
begingl(mdl->glarea);
|
|
|
|
if (!mdl->init)
|
|
{
|
|
initgl(mdl);
|
|
mdl->init = 1;
|
|
}
|
|
|
|
if (mode==DRAW_NORMAL)
|
|
{
|
|
glClearColor(.3,.4,.6,0);
|
|
}
|
|
else
|
|
{
|
|
glClearColor(0,0,0,0);
|
|
}
|
|
|
|
if (mode==DRAW_WHITE) glDisable(GL_TEXTURE_2D);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
|
|
glLoadIdentity();
|
|
glTranslatef(mdl->obj_Xpos,mdl->obj_Ypos,mdl->obj_Zpos);
|
|
build_rotmatrix(m,mdl->curquat);
|
|
glMultMatrixf(&m[0][0]);
|
|
glRotatef(-90,1,0,0);
|
|
|
|
if (mode==DRAW_COORD_S)
|
|
{
|
|
glEnable(GL_TEXTURE_2D);
|
|
glBindTexture(GL_TEXTURE_2D,mdl->texture_s);
|
|
}
|
|
else if (mode==DRAW_COORD_T)
|
|
{
|
|
glEnable(GL_TEXTURE_2D);
|
|
glBindTexture(GL_TEXTURE_2D,mdl->texture_t);
|
|
}
|
|
|
|
|
|
if (mdl->last>mdl->first)
|
|
{
|
|
frame=(int)mdl->frame;
|
|
nextframe=(int)mdl->frame+1;
|
|
if (nextframe>=mdl->model->numframes) nextframe=frame;
|
|
}
|
|
else
|
|
{
|
|
nextframe=(int)mdl->frame;
|
|
frame=(int)mdl->frame-1;
|
|
if (frame<0) frame=0;
|
|
}
|
|
|
|
interp=mdl->frame-floor(mdl->frame);
|
|
|
|
mdl->model->draw(mdl->model,frame,nextframe,interp);
|
|
|
|
if (mode!=DRAW_NORMAL)
|
|
{
|
|
glEnable(GL_TEXTURE_2D);
|
|
glBindTexture(GL_TEXTURE_2D,mdl->texture);
|
|
}
|
|
|
|
endgl(mdl->glarea);
|
|
gtk_gl_area_swapbuffers(GTK_GL_AREA(mdl->glarea));
|
|
}
|
|
|