diff --git a/plug-ins/MapObject/.cvsignore b/plug-ins/MapObject/.cvsignore new file mode 100644 index 0000000000..535a9457a5 --- /dev/null +++ b/plug-ins/MapObject/.cvsignore @@ -0,0 +1,6 @@ +Makefile.in +Makefile +.deps +_libs +.libs +MapObject diff --git a/plug-ins/MapObject/CHANGES b/plug-ins/MapObject/CHANGES new file mode 100644 index 0000000000..0afb49c296 --- /dev/null +++ b/plug-ins/MapObject/CHANGES @@ -0,0 +1,16 @@ + +Changes (post 0.31): +==================== + +-> 0.31 Merged MapPlane and MapSphere. Added support for non-interactive + execution (for script-fu). +-> 0.32 Fixed a bug in the bilinear interpolation function. Added "tile" option. + Added some icons to the material page to illustrate the effects of the + parameters. I'm not sure they help much. +-> 0.40 Some source/algorithm cleanups, fixed gtk+ object refcounting bugs. Some + changes to compile with gtk+ 0.99.4. +-> 1.00 First non-beta release. Replaced GckNotebook with GtkNotebook, fixed a few + annoying bugs. Better support for partial transparency (only filtered + transparency now, perhaps additive later). Compiles without warnings with + -Wall and -ansi. + diff --git a/plug-ins/MapObject/Makefile.am b/plug-ins/MapObject/Makefile.am new file mode 100644 index 0000000000..d233970729 --- /dev/null +++ b/plug-ins/MapObject/Makefile.am @@ -0,0 +1,41 @@ +## Process this file with automake to produce Makefile.in + +pluginlibdir = $(gimpplugindir)/plug-ins + +pluginlib_PROGRAMS = MapObject + +MapObject_SOURCES = \ + amb1.xpm amb2.xpm arcball.c arcball.h diffint1.xpm diffint2.xpm diffref1.xpm diffref2.xpm high1.xpm high2.xpm mapobject_apply.c mapobject_apply.h mapobject_image.c mapobject_image.h mapobject_main.c mapobject_main.h mapobject_pixmaps.h mapobject_preview.c mapobject_preview.h mapobject_shade.c mapobject_shade.h mapobject_ui.c mapobject_ui.h specref1.xpm specref2.xpm + +INCLUDES = \ +# -I$(top_srcdir) \ + -I$(top_srcdir)/libgck \ + -I$(includedir) \ + $(X_CFLAGS) + +LDADD = \ +# $(top_builddir)/libgimp/libgimpui.la \ +# $(top_builddir)/libgimp/libgimp.la \ + $(top_builddir)/libgck/gck/libgck.la \ + $(X_LIBS) \ + -lc + +DEPS = \ +# $(top_builddir)/libgimp/libgimpui.la \ +# $(top_builddir)/libgimp/libgimp.la \ + $(top_builddir)/libgck/gck/libgck.la + +MapObject_DEPENDENCIES = $(DEPS) + +.PHONY: files + +files: + @files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \ + echo $$p; \ + done + @for subdir in $(SUBDIRS); do \ + files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \ + for file in $$files; do \ + echo $$subdir/$$file; \ + done; \ + done diff --git a/plug-ins/MapObject/README b/plug-ins/MapObject/README new file mode 100644 index 0000000000..753551a344 --- /dev/null +++ b/plug-ins/MapObject/README @@ -0,0 +1,58 @@ + +MapObject 1.00 -- image filter plug-in for The GIMP program +=========================================================== + +Copyright (C) 1996-98 Tom Bech +Copyright (C) 1996-98 Federico Mena Quintero + +You can reach the author(s) via E-mail: +tomb@gimp.org (Tom) or quartic@gimp.org (Federico). + +The GIMP was developed by Peter Mattis and Spencer Kimball. +You can contact them at gimp@xcf.berkeley.edu. + +There's more GIMP stuff on our home pages: +http://www.ii.uib.no/~tomb/gimp.html (Tom's page) +http://www.nuclecu.unam.mx/~federico/gimp/index.html (Quartic's page) + +Legal stuff +=========== + +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 (see "COPYING" file); if not, write to the Free Software Foundation, +Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +In other words, you can't sue us for whatever happens while using this ;) + +Compiling +========= + +To compile you'll need The GIMP 0.99.20 and GTK+ 0.99.7 or later. +You'll also need GCK 1.00 (http://www.ii.uib.no/~tomb/gck.html) + +1) Edit the Makefile to reflect your system setup. + +2) Type "make" and then "make install" + +You should now be ready to run. "make install" puts the executable "map_object" +in the standard plug-in directory. + +Documentation +============= + +Ahem.. right.. ;) ..I'll get around to it eventually. + +Please send me a mail if you find any bugs. + +Have fun, + +Tom diff --git a/plug-ins/MapObject/TODO b/plug-ins/MapObject/TODO new file mode 100644 index 0000000000..97544f1afb --- /dev/null +++ b/plug-ins/MapObject/TODO @@ -0,0 +1,18 @@ + +The MapObject plug-in "todo"-list: +================================= + +* Interactive positioning of directional light +* Rotation by mouse (doesn't work correctly yet and is disabled). +* Faster mapping code +* Multiple light-sources +* More objects - at least cube and cylinder. +* Presets (including save/load) +* Gray-scale/channels support +* Documentation +* Autoconf/automake stuff? + +If there's anything you would like to add, feel free +to send me any suggestions for new stuff or improvements. + +Tom diff --git a/plug-ins/MapObject/amb1.xpm b/plug-ins/MapObject/amb1.xpm new file mode 100644 index 0000000000..d9fb4a1b4e --- /dev/null +++ b/plug-ins/MapObject/amb1.xpm @@ -0,0 +1,88 @@ +/* XPM */ +char * amb1_xpm[] = { +"32 32 53 1", +" c None", +". c #861786178617", +"X c #861782078617", +"o c #69A66DB669A6", +"O c #8E388E388E38", +"+ c #B6DAB2CAB6DA", +"@ c #BEFBBAEABEFB", +"# c #AEBAAEBAAEBA", +"$ c #9E799E799E79", +"% c #8E388A288E38", +"& c #618565956185", +"* c #30C234D330C2", +"= c #A699A699A699", +"- c #CF3CCF3CCF3C", +"; c #D75CD34CD75C", +": c #C71BC30BC71B", +"> c #DF7DDF7DDF7D", +", c #D75CD75CD75C", +"< c #CF3CCB2BCF3C", +"1 c #AEBAAAAAAEBA", +"2 c #965896589658", +"3 c #79E779E779E7", +"4 c #514455555144", +"5 c #18611C711861", +"6 c #E79DE38DE79D", +"7 c #E79DE79DE79D", +"8 c #DF7DDB6CDF7D", +"9 c #BEFBBEFBBEFB", +"0 c #9E799A699E79", +"q c #79E77DF779E7", +"w c #618561856185", +"e c #38E338E338E3", +"r c #000004100000", +"t c #EFBEEFBEEFBE", +"y c #FFFFFBEEFFFF", +"u c #410341034103", +"i c #08200C300820", +"p c #FFFFFFFFFFFF", +"a c #B6DAB6DAB6DA", +"s c #965892489658", +"d c #104014511040", +"f c #71C675D671C6", +"g c #596559655965", +"h c #104010401040", +"j c #000000000000", +"k c #514451445144", +"l c #30C230C230C2", +"z c #59655D755965", +"x c #410345144103", +"c c #208124922081", +"v c #49244D344924", +"b c #208120812081", +"n c #082008200820", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" .Xo ", +" O+@@#$%&* ", +" =-;;-:+$.&* ", +" =;>>>,<@12345 ", +" O->6778-9#0qwer ", +" +;>7tyt-910X&ui ", +" @;>7ypy-a=sqwud ", +" .@-,8ty6:#$Ofgehj ", +" X#:<---:+=2Xoklij ", +" o$+@99a#=2.fzxcrj ", +" %$1#1=$2.f&v*dj ", +" &.200sOXf&kebrj ", +" *&3qXqfozvecnjj ", +" *4w&wgkx*bnjj ", +" 5euuelcdrjj ", +" ridhirjjj ", +" jjj ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/plug-ins/MapObject/amb2.xpm b/plug-ins/MapObject/amb2.xpm new file mode 100644 index 0000000000..c9cc0eda5c --- /dev/null +++ b/plug-ins/MapObject/amb2.xpm @@ -0,0 +1,58 @@ +/* XPM */ +char * amb2_xpm[] = { +"32 32 23 1", +" c None", +". c #CF3CCF3CCF3C", +"X c #CF3CCB2BCF3C", +"o c #C71BC30BC71B", +"O c #D75CD75CD75C", +"+ c #DF7DDB6CDF7D", +"@ c #C71BC71BC71B", +"# c #AEBAAEBAAEBA", +"$ c #DF7DDF7DDF7D", +"% c #E79DE38DE79D", +"& c #D75CD34CD75C", +"* c #E79DE79DE79D", +"= c #AEBAAAAAAEBA", +"- c #EFBEEBADEFBE", +"; c #BEFBBEFBBEFB", +": c #A699A289A699", +"> c #F7DEF3CEF7DE", +", c #F7DEF7DEF7DE", +"< c #B6DAB2CAB6DA", +"1 c #FFFFFFFFFFFF", +"2 c #FFFFFBEEFFFF", +"3 c #B6DAB6DAB6DA", +"4 c #BEFBBAEABEFB", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ..X ", +" oO+++O.@# ", +" X$%%$$+O&X# ", +" X%%*%%$$+&.@= ", +" o$%**-*%$+O.@;: ", +" O%**>,,%$+O.Xo< ", +" +%%-,12*+O&.Xo3 ", +" .+$%*,2,%+O&.@;3< ", +" .+$$%%*%+O&.X@;3< ", +" XO+$$$++OO&.@o43< ", +" .O+++OO&&.Xo;3< ", +" @&&OO&&..X@;43# ", +" #X.....X@o;43<: ", +" #@@XX@@o;43<: ", +" =;oo;;433<: ", +" :<3333<#: ", +" <<< ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/plug-ins/MapObject/arcball.c b/plug-ins/MapObject/arcball.c new file mode 100644 index 0000000000..362d6b8177 --- /dev/null +++ b/plug-ins/MapObject/arcball.c @@ -0,0 +1,457 @@ +/************************************/ +/* ArcBall.c (c) Ken Shoemake, 1993 */ +/* Modified by Tom Bech, 1996 */ +/************************************/ + +#include +#include +#include +#include "arcball.h" + +/* Gloval variables */ +/* ================ */ + +HVect center; +double radius; +Quat qNow, qDown, qDrag; +HVect vNow, vDown, vFrom, vTo, vrFrom, vrTo; +HMatrix mNow, mDown; +unsigned int showResult, dragging; +ConstraintSet sets[NSets]; +int setSizes[NSets]; +AxisSet axisSet; +int axisIndex; + +HMatrix mId = {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}}; +double otherAxis[][4] = {{-0.48, 0.80, 0.36, 1}}; +Quat qOne = {0, 0, 0, 1}; + +/* Externally visible methods */ +/* ========================== */ + +void ArcBall_Init(); +void ArcBall_Place(HVect Center, double Radius); +void ArcBall_UseSet(AxisSet axis_Set); +void ArcBall_Update(void); +void ArcBall_Value(HMatrix m_Now); +void ArcBall_Values(double *alpha,double *beta,double *gamma); +void ArcBall_BeginDrag(void); +void ArcBall_EndDrag(void); +void ArcBall_Mouse(HVect v_Now); +void ArcBall_CopyMat(HMatrix inm,HMatrix outm); + +/* Internal methods */ +/* ================ */ + +HMatrix *Qt_ToMatrix(Quat q,HMatrix out); +Quat Qt_Conj(Quat q); +Quat Qt_Mul(Quat qL, Quat qR); +Quat Qt_FromBallPoints(HVect from, HVect to); +void Qt_ToBallPoints(Quat q, HVect *arcFrom, HVect *arcTo); + +HVect V3_(double x, double y, double z); +double V3_Norm(HVect v); +HVect V3_Unit(HVect v); +HVect V3_Scale(HVect v, double s); +HVect V3_Negate(HVect v); +HVect V3_Add(HVect v1, HVect v2); +HVect V3_Sub(HVect v1, HVect v2); +double V3_Dot(HVect v1, HVect v2); +HVect V3_Cross(HVect v1, HVect v2); +HVect V3_Bisect(HVect v0, HVect v1); + +HVect MouseOnSphere(HVect mouse, HVect ballCenter, double ballRadius); +HVect ConstrainToAxis(HVect loose, HVect axis); +int NearestConstraintAxis(HVect loose, HVect *axes, int nAxes); + +/* Establish reasonable initial values for controller. */ +/* =================================================== */ + +void ArcBall_Init(void) +{ + int i; + + center = qOne; + radius = 1.0; + vDown = vNow = qOne; + qDown = qNow = qOne; + for (i=15; i>=0; i--) ((double *)mNow)[i] = ((double *)mDown)[i] = ((double *)mId)[i]; + + showResult = dragging = FALSE; + axisSet = NoAxes; + sets[CameraAxes] = mId[X]; + setSizes[CameraAxes] = 3; + sets[BodyAxes] = mDown[X]; + setSizes[BodyAxes] = 3; + sets[OtherAxes] = otherAxis[X]; + setSizes[OtherAxes] = 1; +} + +/* Set the center and size of the controller. */ +/* ========================================== */ + +void ArcBall_Place(HVect Center, double Radius) +{ + center = Center; + radius = Radius; +} + +/* Incorporate new mouse position. */ +/* =============================== */ + +void ArcBall_Mouse(HVect v_Now) +{ + vNow = v_Now; +} + +/* Choose a constraint set, or none. */ +/* ================================= */ + +void ArcBall_UseSet(AxisSet axis_Set) +{ + if (!dragging) axisSet = axis_Set; +} + + +/* Using vDown, vNow, dragging, and axisSet, compute rotation etc. */ +/* =============================================================== */ + +void ArcBall_Update(void) +{ + int setSize = setSizes[axisSet]; + HVect *set = (HVect *)(sets[axisSet]); + + vFrom = MouseOnSphere(vDown, center, radius); + vTo = MouseOnSphere(vNow, center, radius); + if (dragging) + { + if (axisSet!=NoAxes) + { + vFrom = ConstrainToAxis(vFrom, set[axisIndex]); + vTo = ConstrainToAxis(vTo, set[axisIndex]); + } + qDrag = Qt_FromBallPoints(vFrom, vTo); + qNow = Qt_Mul(qDrag, qDown); + } + else + { + if (axisSet!=NoAxes) axisIndex = NearestConstraintAxis(vTo, set, setSize); + } + Qt_ToBallPoints(qDown, &vrFrom, &vrTo); + Qt_ToMatrix(Qt_Conj(qNow), mNow); /* Gives transpose for GL. */ +} + +/* Return rotation matrix defined by controller use. */ +/* ================================================= */ + +void ArcBall_Value(HMatrix m_Now) +{ + ArcBall_CopyMat(mNow,m_Now); +} + +/* Extract rotation angles from matrix */ +/* =================================== */ + +void ArcBall_Values(double *alpha,double *beta,double *gamma) +{ + if ((*beta=asin(-mNow[0][2]))!=0.0) + { + *gamma=atan2(mNow[1][2],mNow[2][2]); + *alpha=atan2(mNow[0][1],mNow[0][0]); + } + else + { + *gamma=atan2(mNow[1][0],mNow[1][1]); + *alpha=0.0; + } +} + +/* Begin drag sequence. */ +/* ==================== */ + +void ArcBall_BeginDrag(void) +{ + dragging = TRUE; + vDown = vNow; +} + +/* Stop drag sequence. */ +/* =================== */ + +void ArcBall_EndDrag(void) +{ + dragging = FALSE; + qDown = qNow; + + ArcBall_CopyMat(mNow,mDown); +} + +/*===================*/ +/***** BallAux.c *****/ +/*===================*/ + +/* Return quaternion product qL * qR. Note: order is important! */ +/* To combine rotations, use the product Mul(qSecond, qFirst), */ +/* which gives the effect of rotating by qFirst then qSecond. */ +/* ============================================================= */ + +Quat Qt_Mul(Quat qL, Quat qR) +{ + Quat qq; + qq.w = qL.w*qR.w - qL.x*qR.x - qL.y*qR.y - qL.z*qR.z; + qq.x = qL.w*qR.x + qL.x*qR.w + qL.y*qR.z - qL.z*qR.y; + qq.y = qL.w*qR.y + qL.y*qR.w + qL.z*qR.x - qL.x*qR.z; + qq.z = qL.w*qR.z + qL.z*qR.w + qL.x*qR.y - qL.y*qR.x; + return (qq); +} + +/* Construct rotation matrix from (possibly non-unit) quaternion. */ +/* Assumes matrix is used to multiply column vector on the left: */ +/* vnew = mat vold. Works correctly for right-handed coordinate */ +/* system and right-handed rotations. */ +/* ============================================================== */ + +HMatrix *Qt_ToMatrix(Quat q, HMatrix out) +{ + double Nq = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w; + double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0; + double xs = q.x*s, ys = q.y*s, zs = q.z*s; + double wx = q.w*xs, wy = q.w*ys, wz = q.w*zs; + double xx = q.x*xs, xy = q.x*ys, xz = q.x*zs; + double yy = q.y*ys, yz = q.y*zs, zz = q.z*zs; + out[X][X] = 1.0 - (yy + zz); out[Y][X] = xy + wz; out[Z][X] = xz - wy; + out[X][Y] = xy - wz; out[Y][Y] = 1.0 - (xx + zz); out[Z][Y] = yz + wx; + out[X][Z] = xz + wy; out[Y][Z] = yz - wx; out[Z][Z] = 1.0 - (xx + yy); + out[X][W] = out[Y][W] = out[Z][W] = out[W][X] = out[W][Y] = out[W][Z] = 0.0; + out[W][W] = 1.0; + return ((HMatrix *)&out); +} + +/* Return conjugate of quaternion. */ +/* =============================== */ + +Quat Qt_Conj(Quat q) +{ + Quat qq; + qq.x = -q.x; qq.y = -q.y; qq.z = -q.z; qq.w = q.w; + return (qq); +} + +/* Return vector formed from components */ +/* ==================================== */ + +HVect V3_(double x, double y, double z) +{ + HVect v; + v.x = x; v.y = y; v.z = z; v.w = 0; + return (v); +} + +/* Return norm of v, defined as sum of squares of components */ +/* ========================================================= */ + +double V3_Norm(HVect v) +{ + return ( v.x*v.x + v.y*v.y + v.z*v.z ); +} + +/* Return unit magnitude vector in direction of v */ +/* ============================================== */ + +HVect V3_Unit(HVect v) +{ + static HVect u = {0, 0, 0, 0}; + double vlen = sqrt(V3_Norm(v)); + + if (vlen != 0.0) u.x = v.x/vlen; u.y = v.y/vlen; u.z = v.z/vlen; + return (u); +} + +/* Return version of v scaled by s */ +/* =============================== */ + +HVect V3_Scale(HVect v, double s) +{ + HVect u; + u.x = s*v.x; u.y = s*v.y; u.z = s*v.z; u.w = v.w; + return (u); +} + +/* Return negative of v */ +/* ==================== */ + +HVect V3_Negate(HVect v) +{ + static HVect u = {0, 0, 0, 0}; + u.x = -v.x; u.y = -v.y; u.z = -v.z; + return (u); +} + +/* Return sum of v1 and v2 */ +/* ======================= */ + +HVect V3_Add(HVect v1, HVect v2) +{ + static HVect v = {0, 0, 0, 0}; + v.x = v1.x+v2.x; v.y = v1.y+v2.y; v.z = v1.z+v2.z; + return (v); +} + +/* Return difference of v1 minus v2 */ +/* ================================ */ + +HVect V3_Sub(HVect v1, HVect v2) +{ + static HVect v = {0, 0, 0, 0}; + v.x = v1.x-v2.x; v.y = v1.y-v2.y; v.z = v1.z-v2.z; + return (v); +} + +/* Halve arc between unit vectors v0 and v1. */ +/* ========================================= */ + +HVect V3_Bisect(HVect v0, HVect v1) +{ + HVect v = {0, 0, 0, 0}; + double Nv; + + v = V3_Add(v0, v1); + Nv = V3_Norm(v); + if (Nv < 1.0e-5) v = V3_(0, 0, 1); + else v = V3_Scale(v, 1/sqrt(Nv)); + return (v); +} + +/* Return dot product of v1 and v2 */ +/* =============================== */ + +double V3_Dot(HVect v1, HVect v2) +{ + return (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); +} + + +/* Return cross product, v1 x v2 */ +/* ============================= */ + +HVect V3_Cross(HVect v1, HVect v2) +{ + static HVect v = {0, 0, 0, 0}; + v.x = v1.y*v2.z-v1.z*v2.y; + v.y = v1.z*v2.x-v1.x*v2.z; + v.z = v1.x*v2.y-v1.y*v2.x; + return (v); +} + +void ArcBall_CopyMat(HMatrix inm,HMatrix outm) +{ + int x=0,y=0; + + for (x=0;x<4;x++) + { + for (y=0;y<4;y++) + { + outm[y][x]=inm[y][x]; + } + } +} + +/*=====================================================*/ +/**** BallMath.c - Essential routines for ArcBall. ****/ +/*=====================================================*/ + +/* Convert window coordinates to sphere coordinates. */ +/* ================================================= */ + +HVect MouseOnSphere(HVect mouse, HVect ballCenter, double ballRadius) +{ + HVect ballMouse; + register double mag; + + ballMouse.x = (mouse.x - ballCenter.x) / ballRadius; + ballMouse.y = (mouse.y - ballCenter.y) / ballRadius; + mag = ballMouse.x*ballMouse.x + ballMouse.y*ballMouse.y; + if (mag > 1.0) + { + register double scale = 1.0/sqrt(mag); + ballMouse.x *= scale; ballMouse.y *= scale; + ballMouse.z = 0.0; + } + else ballMouse.z = sqrt(1 - mag); + ballMouse.w = 0.0; + return (ballMouse); +} + +/* Construct a unit quaternion from two points on unit sphere */ +/* ========================================================== */ + +Quat Qt_FromBallPoints(HVect from, HVect to) +{ + Quat qu; + qu.x = from.y*to.z - from.z*to.y; + qu.y = from.z*to.x - from.x*to.z; + qu.z = from.x*to.y - from.y*to.x; + qu.w = from.x*to.x + from.y*to.y + from.z*to.z; + return (qu); +} + +/* Convert a unit quaternion to two points on unit sphere */ +/* ====================================================== */ + +void Qt_ToBallPoints(Quat q, HVect *arcFrom, HVect *arcTo) +{ + double s; + + s = sqrt(q.x*q.x + q.y*q.y); + if (s == 0.0) *arcFrom = V3_(0.0, 1.0, 0.0); + else *arcFrom = V3_(-q.y/s, q.x/s, 0.0); + arcTo->x = q.w*arcFrom->x - q.z*arcFrom->y; + arcTo->y = q.w*arcFrom->y + q.z*arcFrom->x; + arcTo->z = q.x*arcFrom->y - q.y*arcFrom->x; + if (q.w < 0.0) *arcFrom = V3_(-arcFrom->x, -arcFrom->y, 0.0); +} + +/* Force sphere point to be perpendicular to axis. */ +/* =============================================== */ + +HVect ConstrainToAxis(HVect loose, HVect axis) +{ + HVect onPlane; + register double norm; + + onPlane = V3_Sub(loose, V3_Scale(axis, V3_Dot(axis, loose))); + norm = V3_Norm(onPlane); + if (norm > 0.0) + { + if (onPlane.z < 0.0) onPlane = V3_Negate(onPlane); + return ( V3_Scale(onPlane, 1/sqrt(norm)) ); + } + /* else drop through */ + /* ================= */ + + if (axis.z == 1) onPlane = V3_(1.0, 0.0, 0.0); + else onPlane = V3_Unit(V3_(-axis.y, axis.x, 0.0)); + return (onPlane); +} + +/* Find the index of nearest arc of axis set. */ +/* ========================================== */ + +int NearestConstraintAxis(HVect loose, HVect *axes, int nAxes) +{ + HVect onPlane; + register double max, dot; + register int i, nearest; + max = -1; nearest = 0; + + for (i=0; imax) + { + max = dot; nearest = i; + } + } + return (nearest); +} diff --git a/plug-ins/MapObject/arcball.h b/plug-ins/MapObject/arcball.h new file mode 100644 index 0000000000..c622a51721 --- /dev/null +++ b/plug-ins/MapObject/arcball.h @@ -0,0 +1,25 @@ +#ifndef ARCBALLH +#define ARCBALLH + +typedef struct {double x, y, z, w;} Quat; +enum QuatPart {X, Y, Z, W, QuatLen}; +typedef Quat HVect; +typedef double HMatrix[QuatLen][QuatLen]; + +typedef enum AxisSet{NoAxes, CameraAxes, BodyAxes, OtherAxes, NSets} AxisSet; +typedef double *ConstraintSet; + +extern Quat qOne; + +extern void ArcBall_Init(); +extern void ArcBall_Place(HVect Center, double Radius); +extern void ArcBall_UseSet(AxisSet axis_Set); +extern void ArcBall_Update(void); +extern void ArcBall_Value(HMatrix m_Now); +extern void ArcBall_Values(double *alpha,double *beta,double *gamma); +extern void ArcBall_BeginDrag(void); +extern void ArcBall_EndDrag(void); +extern void ArcBall_Mouse(HVect v_Now); +extern void ArcBall_CopyMat(HMatrix inm,HMatrix outm); + +#endif diff --git a/plug-ins/MapObject/diffint1.xpm b/plug-ins/MapObject/diffint1.xpm new file mode 100644 index 0000000000..323af173c3 --- /dev/null +++ b/plug-ins/MapObject/diffint1.xpm @@ -0,0 +1,44 @@ +/* XPM */ +char * diffint1_xpm[] = { +"32 32 9 1", +" c None", +". c #514455555144", +"X c #514451445144", +"o c #49244D344924", +"O c #596559655965", +"+ c #492449244924", +"@ c #410345144103", +"# c #59655D755965", +"$ c #618561856185", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ..X ", +" o.OO...X+ ", +" XOOOOOO..X+ ", +" XOOOOOOO...X+ ", +" oOOOOOOOOO..Xo@ ", +" .OOO###OO...XX+ ", +" OOOO#$#OO...XXo ", +" .OOOO###OO...XXoo ", +" ..OOOOOOO...XXooo ", +" X.OOOOOO....XXooo ", +" ...O......XXooo ", +" X........XXXoo+ ", +" +X.....XXXXooo@ ", +" +XXXXXXXoooo@ ", +" +oXXXooooo@ ", +" @+ooooo+@ ", +" ooo ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/plug-ins/MapObject/diffint2.xpm b/plug-ins/MapObject/diffint2.xpm new file mode 100644 index 0000000000..289db9eab9 --- /dev/null +++ b/plug-ins/MapObject/diffint2.xpm @@ -0,0 +1,80 @@ +/* XPM */ +char * diffint2_xpm[] = { +"32 32 45 1", +" c None", +". c #A699A699A699", +"X c #A699A289A699", +"o c #965896589658", +"O c #BEFBBEFBBEFB", +"+ c #CF3CCB2BCF3C", +"@ c #C71BC71BC71B", +"# c #C71BC30BC71B", +"$ c #B6DAB6DAB6DA", +"% c #8E388E388E38", +"& c #69A669A669A6", +"* c #D75CD75CD75C", +"= c #DF7DDB6CDF7D", +"- c #CF3CCF3CCF3C", +"; c #965892489658", +": c #DF7DDF7DDF7D", +"> c #E79DE38DE79D", +", c #D75CD34CD75C", +"< c #AEBAAEBAAEBA", +"1 c #9E799E799E79", +"2 c #861786178617", +"3 c #596559655965", +"4 c #E79DE79DE79D", +"5 c #B6DAB2CAB6DA", +"6 c #71C671C671C6", +"7 c #492449244924", +"8 c #F7DEF3CEF7DE", +"9 c #F7DEF7DEF7DE", +"0 c #71C675D671C6", +"q c #514455555144", +"w c #FFFFFFFFFFFF", +"e c #FFFFFBEEFFFF", +"r c #BEFBBAEABEFB", +"t c #EFBEEBADEFBE", +"y c #AEBAAAAAAEBA", +"u c #9E799A699E79", +"i c #8E388A288E38", +"p c #49244D344924", +"a c #861782078617", +"s c #69A66DB669A6", +"d c #79E779E779E7", +"f c #618565956185", +"g c #514451445144", +"h c #618561856185", +"j c #410345144103", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" .Xo ", +" .O+@#$.%& ", +" $*==*-#$.;& ", +" $=:>:=,+O<123 ", +" .*:444:*+O5X%67 ", +" O=>4898*+O5X%0q ", +" +=:49we=@r<1%03 ", +" .@*=:8et-#$yui03p ", +" X#-,**=-#r c #A699A289A699", +", c #618565956185", +"< c #AEBAAEBAAEBA", +"1 c #861786178617", +"2 c #492449244924", +"3 c #8E388E388E38", +"4 c #596559655965", +"5 c #CF3CCB2BCF3C", +"6 c #618561856185", +"7 c #DF7DDB6CDF7D", +"8 c #C71BC30BC71B", +"9 c #AEBAAAAAAEBA", +"0 c #8E388A288E38", +"q c #49244D344924", +"w c #9E799E799E79", +"e c #79E77DF779E7", +"r c #965892489658", +"t c #71C671C671C6", +"y c #514451445144", +"u c #9E799A699E79", +"i c #861782078617", +"p c #69A66DB669A6", +"a c #514455555144", +"s c #410345144103", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" .Xo ", +" .O+@@#$%& ", +" *=====@-$%& ", +" *=======+;:>, ", +" .========+*X<12 ", +" O========+*X%34 ", +" +========O;5<36 ", +" .@=======@#78906q ", +" X@======@O;Xowe4q ", +" o#@====@O*$89rtyq ", +" $-+++O#;$:%ui6q ", +" %$;**;7X8%w0py2 ", +" &%:XX58o9u0taqs ", +" &><%<9wripaqs ", +" ,1330et6yqs ", +" 24664yq2s ", +" qqq ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/plug-ins/MapObject/high1.xpm b/plug-ins/MapObject/high1.xpm new file mode 100644 index 0000000000..b542308d05 --- /dev/null +++ b/plug-ins/MapObject/high1.xpm @@ -0,0 +1,75 @@ +/* XPM */ +char * high1_xpm[] = { +"32 32 40 1", +" c None", +". c #D75CD34CD75C", +"X c #CF3CCF3CCF3C", +"o c #BEFBBAEABEFB", +"O c #F7DEF3CEF7DE", +"+ c #F7DEF7DEF7DE", +"@ c #FFFFFBEEFFFF", +"# c #EFBEEBADEFBE", +"$ c #D75CD75CD75C", +"% c #B6DAB2CAB6DA", +"& c #79E779E779E7", +"* c #E79DE79DE79D", +"= c #FFFFFFFFFFFF", +"- c #EFBEEFBEEFBE", +"; c #E79DE38DE79D", +": c #C71BC71BC71B", +"> c #A699A289A699", +", c #618565956185", +"< c #AEBAAEBAAEBA", +"1 c #861786178617", +"2 c #492449244924", +"3 c #8E388E388E38", +"4 c #596559655965", +"5 c #CF3CCB2BCF3C", +"6 c #618561856185", +"7 c #DF7DDB6CDF7D", +"8 c #C71BC30BC71B", +"9 c #AEBAAAAAAEBA", +"0 c #8E388A288E38", +"q c #49244D344924", +"w c #9E799E799E79", +"e c #79E77DF779E7", +"r c #965892489658", +"t c #71C671C671C6", +"y c #514451445144", +"u c #9E799A699E79", +"i c #861782078617", +"p c #69A66DB669A6", +"a c #514455555144", +"s c #410345144103", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" .Xo ", +" .O+@@#$%& ", +" *=====@-$%& ", +" *=======+;:>, ", +" .========+*X<12 ", +" O========+*X%34 ", +" +========O;5<36 ", +" .@=======@#78906q ", +" X@======@O;Xowe4q ", +" o#@====@O*$89rtyq ", +" $-+++O#;$:%ui6q ", +" %$;**;7X8%w0py2 ", +" &%:XX58o9u0taqs ", +" &><%<9wripaqs ", +" ,1330et6yqs ", +" 24664yq2s ", +" qqq ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/plug-ins/MapObject/high2.xpm b/plug-ins/MapObject/high2.xpm new file mode 100644 index 0000000000..49447a19fe --- /dev/null +++ b/plug-ins/MapObject/high2.xpm @@ -0,0 +1,78 @@ +/* XPM */ +char * high2_xpm[] = { +"32 32 43 1", +" c None", +". c #A699A699A699", +"X c #A699A289A699", +"o c #965896589658", +"O c #BEFBBEFBBEFB", +"+ c #CF3CCB2BCF3C", +"@ c #C71BC71BC71B", +"# c #C71BC30BC71B", +"$ c #B6DAB6DAB6DA", +"% c #8E388E388E38", +"& c #69A669A669A6", +"* c #D75CD75CD75C", +"= c #DF7DDB6CDF7D", +"- c #CF3CCF3CCF3C", +"; c #965892489658", +": c #DF7DDF7DDF7D", +"> c #E79DE38DE79D", +", c #D75CD34CD75C", +"< c #AEBAAEBAAEBA", +"1 c #9E799E799E79", +"2 c #861786178617", +"3 c #596559655965", +"4 c #E79DE79DE79D", +"5 c #B6DAB2CAB6DA", +"6 c #71C671C671C6", +"7 c #492449244924", +"8 c #F7DEF7DEF7DE", +"9 c #71C675D671C6", +"0 c #514455555144", +"q c #FFFFFFFFFFFF", +"w c #BEFBBAEABEFB", +"e c #F7DEF3CEF7DE", +"r c #AEBAAAAAAEBA", +"t c #9E799A699E79", +"y c #8E388A288E38", +"u c #49244D344924", +"i c #861782078617", +"p c #69A66DB669A6", +"a c #79E779E779E7", +"s c #618565956185", +"d c #514451445144", +"f c #618561856185", +"g c #410345144103", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" .Xo ", +" .O+@#$.%& ", +" $*==*-#$.;& ", +" $=:>:=,+O<123 ", +" .*:>4>=*+O5X%67 ", +" O=>4>8:,+O5X%90 ", +" +=:>8qq-@w<1%93 ", +" .@*==:e=+#$rty93u ", +" X#-,*,*-#wbpp!=4)) + { + /* Create a new image */ + /* ================== */ + + new_image_id=gimp_image_new(width,height,RGB); + + if (mapvals.transparent_background==TRUE) + { + /* Add a layer with an alpha channel */ + /* ================================= */ + + new_layer_id=gimp_layer_new(new_image_id,"Background",width,height,RGBA_IMAGE,100.0,NORMAL_MODE); + } + else + { + /* Create a "normal" layer */ + /* ======================= */ + + new_layer_id=gimp_layer_new(new_image_id,"Background",width,height,RGB_IMAGE,100.0,NORMAL_MODE); + } + + gimp_image_add_layer(new_image_id,new_layer_id,0); + output_drawable=gimp_drawable_get(new_layer_id); + } + + gimp_pixel_rgn_init (&dest_region, output_drawable, 0, 0, width, height, TRUE, TRUE); + + if (mapvals.maptype==MAP_PLANE) + gimp_progress_init("Map to object (plane)"); + else + gimp_progress_init("Map to object (sphere)"); + + if (mapvals.antialiasing==FALSE) + { + for (ycount=0;ycountid, TRUE); + gimp_drawable_update (output_drawable->id, 0, 0, width,height); + + if (new_image_id!=-1) + { + gimp_display_new(new_image_id); + gimp_displays_flush(); + gimp_drawable_detach (output_drawable); + } +} + diff --git a/plug-ins/MapObject/mapobject_apply.h b/plug-ins/MapObject/mapobject_apply.h new file mode 100644 index 0000000000..681e3d3a8b --- /dev/null +++ b/plug-ins/MapObject/mapobject_apply.h @@ -0,0 +1,20 @@ +#ifndef MAPOBJECTAPPLYH +#define MAPOBJECTAPPLYH + +#include +#include +#include +#include +#include +#include +#include + +#include "mapobject_main.h" +#include "mapobject_image.h" + + +extern gdouble imat[4][4]; +extern void init_compute(void); +extern void compute_image(void); + +#endif diff --git a/plug-ins/MapObject/mapobject_image.c b/plug-ins/MapObject/mapobject_image.c new file mode 100644 index 0000000000..2dae75ac00 --- /dev/null +++ b/plug-ins/MapObject/mapobject_image.c @@ -0,0 +1,202 @@ +/*********************************************************/ +/* Image manipulation routines. Calls mapobject_shade.c */ +/* functions to compute the shading of the image at each */ +/* pixel. These routines are used by the functions in */ +/* mapobject_preview.c and mapobject_apply.c */ +/*********************************************************/ + +#include "mapobject_image.h" + +GDrawable *input_drawable,*output_drawable; +GPixelRgn source_region,dest_region; + +guchar *preview_rgb_data = NULL; +GdkImage *image = NULL; + +glong maxcounter,old_depth,max_depth; +gint imgtype,width,height,in_channels,out_channels; +GckRGB background; +gdouble oldtreshold; + +gint border_x1,border_y1,border_x2,border_y2; + +/******************/ +/* Implementation */ +/******************/ + +GckRGB peek(gint x,gint y) +{ + static guchar data[4]; + GckRGB color; + + gimp_pixel_rgn_get_pixel(&source_region,data,x,y); + + color.r=(gdouble)(data[0])/255.0; + color.g=(gdouble)(data[1])/255.0; + color.b=(gdouble)(data[2])/255.0; + + if (input_drawable->bpp==4) + { + if (in_channels==4) + color.a=(gdouble)(data[3])/255.0; + else + color.a=1.0; + } + else + color.a=1.0; + + return(color); +} + +void poke(gint x,gint y,GckRGB *color) +{ + static guchar data[4]; + + data[0]=(guchar)(color->r*255.0); + data[1]=(guchar)(color->g*255.0); + data[2]=(guchar)(color->b*255.0); + data[3]=(guchar)(color->a*255.0); + + gimp_pixel_rgn_set_pixel(&dest_region,data,x,y); +} + +gint checkbounds(gint x,gint y) +{ + if (x=border_x2 || y>=border_y2) + return(FALSE); + else + return(TRUE); +} + +GckVector3 int_to_pos(gint x,gint y) +{ + GckVector3 pos; + + pos.x=(gdouble)x/(gdouble)width; + pos.y=(gdouble)y/(gdouble)height; + pos.z=0.0; + + return(pos); +} + +void pos_to_int(gdouble x,gdouble y,gint *scr_x,gint *scr_y) +{ + *scr_x=(gint)((x*(gdouble)width)); + *scr_y=(gint)((y*(gdouble)height)); +} + +/**********************************************/ +/* Compute the image color at pos (u,v) using */ +/* Quartics bilinear interpolation stuff. */ +/**********************************************/ + +GckRGB get_image_color(gdouble u,gdouble v,gint *inside) +{ + gint x1, y1, x2, y2; + GckRGB p[4]; + + pos_to_int(u,v,&x1,&y1); + + if (mapvals.tiled==TRUE) + { + *inside=TRUE; + if (x1 < 0) x1 = (width-1) - (-x1 % width); + else x1 = x1 % width; + + if (y1 < 0) y1 = (height-1) - (-y1 % height); + else y1 = y1 % height; + + x2 = (x1 + 1) % width; + y2 = (y1 + 1) % height; + + p[0] = peek(x1, y1); + p[1] = peek(x2, y1); + p[2] = peek(x1, y2); + p[3] = peek(x2, y2); + return(gck_bilinear_rgba(u * width, v * height, p)); + } + + if (checkbounds(x1,y1)==FALSE) + { + *inside=FALSE; + return(background); + } + + x2 = (x1 + 1); + y2 = (y1 + 1); + + if (checkbounds(x2,y2)==FALSE) + { + *inside=TRUE; + return(peek(x1,y1)); + } + + *inside=TRUE; + p[0] = peek(x1, y1); + p[1] = peek(x2, y1); + p[2] = peek(x1, y2); + p[3] = peek(x2, y2); + return(gck_bilinear_rgba(u * width, v * height, p)); +} + +/****************************************/ +/* Allocate memory for temporary images */ +/****************************************/ + +gint image_setup(GDrawable *drawable,gint interactive) +{ + glong numbytes; + + /* Set the tile cache size */ + /* ======================= */ + + gimp_tile_cache_ntiles((drawable->width + gimp_tile_width() - 1) / + gimp_tile_width()); + + /* Get some useful info on the input drawable */ + /* ========================================== */ + + input_drawable=drawable; + output_drawable=drawable; + + gimp_drawable_mask_bounds (drawable->id, &border_x1, &border_y1, &border_x2, &border_y2); + + width=input_drawable->width; + height=input_drawable->height; + + gimp_pixel_rgn_init (&source_region, input_drawable, 0, 0, width, height, FALSE, FALSE); + + maxcounter=(glong)width*(glong)height; + + /* Assume at least RGB */ + /* =================== */ + + in_channels=3; + if (gimp_drawable_has_alpha(input_drawable->id)==TRUE) + in_channels++; + + if (interactive==TRUE) + { + /* Allocate memory for temp. images */ + /* ================================ */ + + numbytes=PREVIEW_HEIGHT*PREVIEW_WIDTH*3; + + image=gdk_image_new(GDK_IMAGE_FASTEST,appwin->visinfo->visual,PREVIEW_WIDTH,PREVIEW_HEIGHT); + if (image==NULL) + return(FALSE); + + preview_rgb_data=(guchar *)malloc((size_t)numbytes); + if (preview_rgb_data==NULL) + return(FALSE); + memset(preview_rgb_data,0,numbytes); + + /* Convert from raw RGB to GdkImage */ + /* ================================ */ + + gck_rgb_to_gdkimage(appwin->visinfo,preview_rgb_data,image,PREVIEW_WIDTH,PREVIEW_HEIGHT); + } + + return(TRUE); +} + diff --git a/plug-ins/MapObject/mapobject_image.h b/plug-ins/MapObject/mapobject_image.h new file mode 100644 index 0000000000..33be0345b4 --- /dev/null +++ b/plug-ins/MapObject/mapobject_image.h @@ -0,0 +1,48 @@ +#ifndef MAPOBJECTIMAGEH +#define MAPOBJECTIMAGEH + +#include +#include +#include +#include +#include +#include +#include + +#include "mapobject_main.h" +#include "mapobject_preview.h" +#include "mapobject_shade.h" +#include "mapobject_ui.h" + +/* Externally visible variables */ +/* ============================ */ + +extern GDrawable *input_drawable,*output_drawable; +extern GPixelRgn source_region,dest_region; + +extern guchar *preview_rgb_data; +extern GdkImage *image; + +extern glong maxcounter,old_depth,max_depth; +extern gint imgtype,width,height,in_channels,out_channels; +extern GckRGB background; +extern gdouble oldtreshold; + +extern gint border_x1,border_y1,border_x2,border_y2; + +extern GTile *current_in_tile, *current_out_tile; + +/* Externally visible functions */ +/* ============================ */ + +extern gint image_setup (GDrawable *drawable,gint interactive); +extern glong in_xy_to_index (gint x,gint y); +extern glong out_xy_to_index (gint x,gint y); +extern gint checkbounds (gint x,gint y); +extern GckRGB peek (gint x,gint y); +extern void poke (gint x,gint y,GckRGB *color); +extern GckVector3 int_to_pos (gint x,gint y); +extern void pos_to_int (gdouble x,gdouble y,gint *scr_x,gint *scr_y); +extern GckRGB get_image_color (gdouble u,gdouble v,gint *inside); + +#endif diff --git a/plug-ins/MapObject/mapobject_main.c b/plug-ins/MapObject/mapobject_main.c new file mode 100644 index 0000000000..101faffa0f --- /dev/null +++ b/plug-ins/MapObject/mapobject_main.c @@ -0,0 +1,284 @@ +/*********************************************************************************/ +/* MapObject 1.00 -- image filter plug-in for The Gimp program */ +/* Copyright (C) 1996-98 Tom Bech */ +/* Copyright (C) 1996-98 Federico Mena Quintero */ +/*===============================================================================*/ +/* E-mail: tomb@gimp.org (Tom) or quartic@gimp.org (Federico) */ +/* You can contact the original The Gimp authors at gimp@xcf.berkeley.edu */ +/*===============================================================================*/ +/* 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 (read the "COPYING" file); if not, write to the Free Software */ +/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/*===============================================================================*/ +/* In other words, you can't sue us for whatever happens while using this ;) */ +/*********************************************************************************/ + +#include "mapobject_main.h" + +/* Global variables */ +/* ================ */ + +MapObjectValues mapvals; + +/******************/ +/* Implementation */ +/******************/ + +void mapobject_interactive (GDrawable *drawable); +void mapobject_noninteractive (GDrawable *drawable); + +/*************************************/ +/* Set parameters to standard values */ +/*************************************/ + +void set_default_settings(void) +{ + gck_vector3_set(&mapvals.viewpoint, 0.5,0.5,2.0); + gck_vector3_set(&mapvals.firstaxis, 1.0,0.0,0.0); + gck_vector3_set(&mapvals.secondaxis, 0.0,1.0,0.0); + gck_vector3_set(&mapvals.normal, 0.0,0.0,1.0); + gck_vector3_set(&mapvals.position, 0.5,0.5,0.0); + gck_vector3_set(&mapvals.lightsource.position, -0.5,-0.5,2.0); + gck_vector3_set(&mapvals.lightsource.direction, -1.0,-1.0,1.0); + + mapvals.maptype=MAP_PLANE; + + mapvals.pixeltreshold=0.25; + mapvals.alpha=mapvals.beta=mapvals.gamma=0.0; + mapvals.maxdepth=3.0; + mapvals.radius=0.25; + + mapvals.preview_zoom_factor=0; + + mapvals.lightsource.type=POINT_LIGHT; + + mapvals.antialiasing=TRUE; + mapvals.create_new_image=FALSE; + mapvals.transparent_background=FALSE; + mapvals.tiled=FALSE; + mapvals.showgrid=FALSE; + mapvals.tooltips_enabled=TRUE; + + mapvals.lightsource.intensity = 1.0; + gck_rgb_set(&mapvals.lightsource.color,1.0,1.0,1.0); + + mapvals.material.ambient_int = 0.3; + mapvals.material.diffuse_int = 1.0; + mapvals.material.diffuse_ref = 0.5; + mapvals.material.specular_ref = 0.5; + mapvals.material.highlight = 27.0; +} + +MAIN(); + +static void query(void) +{ + + static GParamDef args[] = + { + { PARAM_INT32, "run_mode", "Interactive (0), non-interactive (1)" }, + { PARAM_IMAGE, "image", "Input image" }, + { PARAM_DRAWABLE, "drawable", "Input drawable" }, + { PARAM_INT32, "maptype", "Type of mapping (0=plane,1=sphere)" }, + { PARAM_FLOAT, "viewpoint_x", "Position of viewpoint (x,y,z)" }, + { PARAM_FLOAT, "viewpoint_y", "Position of viewpoint (x,y,z)" }, + { PARAM_FLOAT, "viewpoint_z", "Position of viewpoint (x,y,z)" }, + { PARAM_FLOAT, "position_x", "Object position (x,y,z)" }, + { PARAM_FLOAT, "position_y", "Object position (x,y,z)" }, + { PARAM_FLOAT, "position_z", "Object position (x,y,z)" }, + { PARAM_FLOAT, "firstaxis_x", "First axis of object [x,y,z]" }, + { PARAM_FLOAT, "firstaxis_y", "First axis of object [x,y,z]" }, + { PARAM_FLOAT, "firstaxis_z", "First axis of object [x,y,z]" }, + { PARAM_FLOAT, "secondaxis_x", "Second axis of object [x,y,z]" }, + { PARAM_FLOAT, "secondaxis_y", "Second axis of object [x,y,z]" }, + { PARAM_FLOAT, "secondaxis_z", "Second axis of object [x,y,z]" }, + { PARAM_FLOAT, "rotationangle_x", "Axis rotation (xy,xz,yz) in degrees" }, + { PARAM_FLOAT, "rotationangle_y", "Axis rotation (xy,xz,yz) in degrees" }, + { PARAM_FLOAT, "rotationangle_z", "Axis rotation (xy,xz,yz) in degrees" }, + { PARAM_INT32, "lighttype", "Type of lightsource (0=point,1=directional,3=none)" }, + { PARAM_COLOR, "lightcolor", "Lightsource color (r,g,b)" }, + { PARAM_FLOAT, "lightposition_x", "Lightsource position (x,y,z)" }, + { PARAM_FLOAT, "lightposition_y", "Lightsource position (x,y,z)" }, + { PARAM_FLOAT, "lightposition_z", "Lightsource position (x,y,z)" }, + { PARAM_FLOAT, "lightdirection_x", "Lightsource direction [x,y,z]" }, + { PARAM_FLOAT, "lightdirection_y", "Lightsource direction [x,y,z]" }, + { PARAM_FLOAT, "lightdirection_z", "Lightsource direction [x,y,z]" }, + { PARAM_FLOAT, "ambient_intensity", "Material ambient intensity (0..1)" }, + { PARAM_FLOAT, "diffuse_intensity", "Material diffuse intensity (0..1)" }, + { PARAM_FLOAT, "diffuse_reflectivity", "Material diffuse reflectivity (0..1)" }, + { PARAM_FLOAT, "specular_reflectivity", "Material specular reflectivity (0..1)" }, + { PARAM_FLOAT, "highlight", "Material highlight (0..->), note: it's expotential" }, + { PARAM_INT32, "antialiasing", "Apply antialiasing (TRUE/FALSE)" }, + { PARAM_INT32, "tiled", "Tile source image (TRUE/FALSE)" }, + { PARAM_INT32, "newimage", "Create a new image (TRUE/FALSE)" }, + { PARAM_INT32, "transparentbackground", "Make background transparent (TRUE/FALSE)" }, + { PARAM_FLOAT, "radius", "Sphere radius (only used when maptype=1)" } + }; + + static GParamDef *return_vals = NULL; + static gint nargs = sizeof (args) / sizeof (args[0]); + static gint nreturn_vals = 0; + + gimp_install_procedure ("plug_in_map_object", + "Maps a picture to a object (plane, sphere)", + "No help yet", + "Tom Bech & Federico Mena Quintero", + "Tom Bech & Federico Mena Quintero", + "Version 1.00, March 15 1998", + "/Filters/Map/Map Object", + "RGB*", + PROC_PLUG_IN, + nargs, nreturn_vals, + args, return_vals); +} + +static void run(gchar *name, + gint nparams, + GParam *param, + gint *nreturn_vals, + GParam **return_vals) +{ + static GParam values[1]; + GDrawable *drawable; + GRunModeType run_mode; + GStatusType status = STATUS_SUCCESS; + + run_mode = param[0].data.d_int32; + + values[0].type = PARAM_STATUS; + values[0].data.d_status = status; + + *nreturn_vals = 1; + *return_vals = values; + + /* Set default values */ + /* ================== */ + + set_default_settings(); + + /* Get the specified drawable */ + /* ========================== */ + + drawable = gimp_drawable_get (param[2].data.d_drawable); + + switch (run_mode) + { + case RUN_INTERACTIVE: + + /* Possibly retrieve data */ + /* ====================== */ + + gimp_get_data ("plug_in_map_object", &mapvals); + mapobject_interactive(drawable); + gimp_set_data("plug_in_map_object", &mapvals, sizeof(MapObjectValues)); + break; + case RUN_WITH_LAST_VALS: + gimp_get_data ("plug_in_map_object", &mapvals); + image_setup(drawable,FALSE); + compute_image(); + break; + case RUN_NONINTERACTIVE: + if (nparams != 37) + status = STATUS_CALLING_ERROR; + else if (status == STATUS_SUCCESS) + { + mapvals.maptype = (MapType)param[3].data.d_int32; + mapvals.viewpoint.x = param[4].data.d_float; + mapvals.viewpoint.y = param[5].data.d_float; + mapvals.viewpoint.z = param[6].data.d_float; + mapvals.position.x = param[7].data.d_float; + mapvals.position.y = param[8].data.d_float; + mapvals.position.z = param[9].data.d_float; + mapvals.firstaxis.x = param[10].data.d_float; + mapvals.firstaxis.y = param[11].data.d_float; + mapvals.firstaxis.z = param[12].data.d_float; + mapvals.secondaxis.x = param[13].data.d_float; + mapvals.secondaxis.y = param[14].data.d_float; + mapvals.secondaxis.z = param[15].data.d_float; + mapvals.alpha = param[16].data.d_float; + mapvals.beta = param[17].data.d_float; + mapvals.gamma = param[18].data.d_float; + mapvals.lightsource.type = (LightType)param[19].data.d_int32; + mapvals.lightsource.color.r = param[20].data.d_color.red; + mapvals.lightsource.color.g = param[20].data.d_color.green; + mapvals.lightsource.color.b = param[20].data.d_color.blue; + mapvals.lightsource.position.x = param[21].data.d_float; + mapvals.lightsource.position.y = param[22].data.d_float; + mapvals.lightsource.position.z = param[23].data.d_float; + mapvals.lightsource.direction.x = param[24].data.d_float; + mapvals.lightsource.direction.y = param[25].data.d_float; + mapvals.lightsource.direction.z = param[26].data.d_float; + mapvals.material.ambient_int = param[27].data.d_float; + mapvals.material.diffuse_int = param[28].data.d_float; + mapvals.material.diffuse_ref = param[29].data.d_float; + mapvals.material.specular_ref = param[30].data.d_float; + mapvals.material.highlight = param[31].data.d_float; + mapvals.antialiasing = (gint)param[32].data.d_int32; + mapvals.tiled = (gint)param[33].data.d_int32; + mapvals.create_new_image = (gint)param[34].data.d_int32; + mapvals.transparent_background = (gint)param[35].data.d_int32; + mapvals.radius = param[36].data.d_float; + + image_setup(drawable, FALSE); + compute_image(); + } + break; + } + + values[0].data.d_status = status; + gimp_drawable_detach(drawable); +} + +GPlugInInfo PLUG_IN_INFO = +{ + NULL, /* init_proc */ + NULL, /* quit_proc */ + query, /* query_proc */ + run, /* run_proc */ +}; + +void mapobject_interactive(GDrawable *drawable) +{ + gchar **argv; + gint argc; + + argc = 1; + argv = g_new (gchar *, 1); + argv[0] = g_strdup ("map_object"); + + gdk_set_use_xshm(gimp_use_xshm()); + + gtk_init (&argc, &argv); + gtk_rc_parse (gimp_gtkrc ()); + + /* Set up ArcBall stuff */ + /* ==================== */ + + /*ArcBall_Init(); */ + + /* Create application window */ + /* ========================= */ + + create_main_dialog(); + + /* Prepare images */ + /* ============== */ + + image_setup(drawable,TRUE); + + /* Gtk main event loop */ + /* =================== */ + + gtk_main(); + gdk_flush(); +} + diff --git a/plug-ins/MapObject/mapobject_main.h b/plug-ins/MapObject/mapobject_main.h new file mode 100644 index 0000000000..f0af04bb14 --- /dev/null +++ b/plug-ins/MapObject/mapobject_main.h @@ -0,0 +1,90 @@ +#ifndef MAPOBJECTMAINH +#define MAPOBJECTMAINH + +#include +#include +#include +#include +#include +#include +#include + +#include "arcball.h" +#include "mapobject_ui.h" +#include "mapobject_image.h" +#include "mapobject_apply.h" +#include "mapobject_preview.h" + +/* Defines and stuff */ +/* ================= */ + +#define TILE_CACHE_SIZE 16 + +/* Typedefs */ +/* ======== */ + +typedef enum { + POINT_LIGHT, + DIRECTIONAL_LIGHT, + NO_LIGHT +} LightType; + +typedef enum { + MAP_PLANE, + MAP_SPHERE +} MapType; + +/* Typedefs */ +/* ======== */ + +typedef struct +{ + gdouble ambient_int; + gdouble diffuse_int; + gdouble diffuse_ref; + gdouble specular_ref; + gdouble highlight; + GckRGB color; +} MaterialSettings; + +typedef struct +{ + LightType type; + GckVector3 position; + GckVector3 direction; + GckRGB color; + gdouble intensity; +} LightSettings; + +typedef struct { + GckVector3 viewpoint,firstaxis,secondaxis,normal,position; + LightSettings lightsource; + + MaterialSettings material; + MaterialSettings refmaterial; + + MapType maptype; + + gint antialiasing; + gint create_new_image; + gint transparent_background; + gint tiled; + gint showgrid; + gint tooltips_enabled; + + glong preview_zoom_factor; + + gdouble alpha,beta,gamma; + gdouble maxdepth; + gdouble pixeltreshold; + gdouble radius; + +} MapObjectValues; + +/* Externally visible variables */ +/* ============================ */ + +extern MapObjectValues mapvals; +extern GckRGB background; + +#endif diff --git a/plug-ins/MapObject/mapobject_pixmaps.h b/plug-ins/MapObject/mapobject_pixmaps.h new file mode 100644 index 0000000000..37a3e16d6c --- /dev/null +++ b/plug-ins/MapObject/mapobject_pixmaps.h @@ -0,0 +1,26 @@ +#ifndef MAPOBJECTPIXMAPSH +#define MAPOBJECTPIXMAPSH + +#include "amb1.xpm" +#include "amb2.xpm" +#include "diffint1.xpm" +#include "diffint2.xpm" +#include "diffref1.xpm" +#include "diffref2.xpm" +#include "specref1.xpm" +#include "specref2.xpm" +#include "high1.xpm" +#include "high2.xpm" + +extern char *amb1_xpm[]; +extern char *amb2_xpm[]; +extern char *diffint1_xpm[]; +extern char *diffint2_xpm[]; +extern char *diffref1_xpm[]; +extern char *diffref2_xpm[]; +extern char *specref1_xpm[]; +extern char *specref2_xpm[]; +extern char *high1_xpm[]; +extern char *high2_xpm[]; + +#endif diff --git a/plug-ins/MapObject/mapobject_preview.c b/plug-ins/MapObject/mapobject_preview.c new file mode 100644 index 0000000000..290ca9f039 --- /dev/null +++ b/plug-ins/MapObject/mapobject_preview.c @@ -0,0 +1,533 @@ +/*************************************************/ +/* Compute a preview image and preview wireframe */ +/*************************************************/ + +#include "mapobject_preview.h" + +line linetab[WIRESIZE*2+8]; +gdouble mat[3][4]; + +gint lightx,lighty; +BackBuffer backbuf={0,0,0,0,NULL}; + +/* Protos */ +/* ====== */ + +void update_light (gint xpos,gint ypos); +void draw_light_marker (gint xpos,gint ypos); +void clear_light_marker (void); +void draw_wireframe_plane(gint startx,gint starty,gint pw,gint ph); +void draw_wireframe_sphere(gint startx,gint starty,gint pw,gint ph); +void clear_wireframe(void); + +/**************************************************************/ +/* Computes a preview of the rectangle starting at (x,y) with */ +/* dimensions (w,h), placing the result in preview_RGB_data. */ +/**************************************************************/ + +void compute_preview(gint x,gint y,gint w,gint h,gint pw,gint ph) +{ + gdouble xpostab[PREVIEW_WIDTH],ypostab[PREVIEW_HEIGHT],realw,realh; + GckVector3 p1,p2; + GckRGB color,lightcheck,darkcheck,temp; + guchar r,g,b; + gint xcnt,ycnt,f1,f2; + glong index=0; + + init_compute(); + + p1=int_to_pos(x,y); + p2=int_to_pos(x+w,y+h); + + /* First, compute the linear mapping (x,y,x+w,y+h) to (0,0,pw,ph) */ + /* ============================================================== */ + + realw=(p2.x-p1.x); + realh=(p2.y-p1.y); + + for (xcnt=0;xcntvisinfo,preview_rgb_data,image,pw,ph); +} + +/*************************************************/ +/* Check if the given position is within the */ +/* light marker. Return TRUE if so, FALSE if not */ +/*************************************************/ + +gint check_light_hit(gint xpos,gint ypos) +{ + gdouble dx,dy,r; + + if (mapvals.lightsource.type==POINT_LIGHT) + { + dx=(gdouble)lightx-xpos; + dy=(gdouble)lighty-ypos; + r=sqrt(dx*dx+dy*dy)+0.5; + if ((gint)r>7) + return(FALSE); + else + return(TRUE); + } + + return(FALSE); +} + +/****************************************/ +/* Draw a marker to show light position */ +/****************************************/ + +void draw_light_marker(gint xpos,gint ypos) +{ + gck_gc_set_foreground(appwin->visinfo,gc,0,50,255); + gck_gc_set_background(appwin->visinfo,gc,0,0,0); + + gdk_gc_set_function(gc,GDK_COPY); + + if (mapvals.lightsource.type==POINT_LIGHT) + { + lightx=xpos; + lighty=ypos; + + /* Save background */ + /* =============== */ + + backbuf.x=lightx-7; + backbuf.y=lighty-7; + backbuf.w=14; + backbuf.h=14; + + /* X doesn't like images that's outside a window, make sure */ + /* we get the backbuffer image from within the boundaries */ + /* ======================================================== */ + + if (backbuf.x<0) + backbuf.x=0; + else if ((backbuf.x+backbuf.w)>PREVIEW_WIDTH) + backbuf.w=(PREVIEW_WIDTH-backbuf.x); + if (backbuf.y<0) + backbuf.y=0; + else if ((backbuf.y+backbuf.h)>PREVIEW_HEIGHT) + backbuf.h=(PREVIEW_WIDTH-backbuf.y); + + backbuf.image=gdk_image_get(previewarea->window,backbuf.x,backbuf.y,backbuf.w,backbuf.h); + gdk_draw_arc(previewarea->window,gc,TRUE,lightx-7,lighty-7,14,14,0,360*64); + } +} + +void clear_light_marker() +{ + /* Restore background if it has been saved */ + /* ======================================= */ + + if (backbuf.image!=NULL) + { + gck_gc_set_foreground(appwin->visinfo,gc,255,255,255); + gck_gc_set_background(appwin->visinfo,gc,0,0,0); + + gdk_gc_set_function(gc,GDK_COPY); + gdk_draw_image(previewarea->window,gc,backbuf.image,0,0,backbuf.x,backbuf.y, + backbuf.w,backbuf.h); + gdk_image_destroy(backbuf.image); + backbuf.image=NULL; + } +} + +void draw_lights(gint startx,gint starty,gint pw,gint ph) +{ + gdouble dxpos,dypos; + gint xpos,ypos; + + clear_light_marker(); + + gck_3d_to_2d(startx,starty,pw,ph,&dxpos,&dypos,&mapvals.viewpoint, + &mapvals.lightsource.position); + xpos=(gint)(dxpos+0.5); + ypos=(gint)(dypos+0.5); + + if (xpos>=0 && xpos<=PREVIEW_WIDTH && ypos>=0 && ypos<=PREVIEW_HEIGHT) + draw_light_marker(xpos,ypos); +} + +/*************************************************/ +/* Update light position given new screen coords */ +/*************************************************/ + +void update_light(gint xpos,gint ypos) +{ + gint startx,starty,pw,ph; + + pw=PREVIEW_WIDTH >> mapvals.preview_zoom_factor; + ph=PREVIEW_HEIGHT >> mapvals.preview_zoom_factor; + startx=(PREVIEW_WIDTH-pw)>>1; + starty=(PREVIEW_HEIGHT-ph)>>1; + + gck_2d_to_3d(startx,starty,pw,ph,xpos,ypos,&mapvals.viewpoint,&mapvals.lightsource.position); + draw_lights(startx,starty,pw,ph); +} + +/******************************************************************/ +/* Draw preview image. if DoCompute is TRUE then recompute image. */ +/******************************************************************/ + +void draw_preview_image(gint docompute) +{ + gint startx,starty,pw,ph; + + gck_gc_set_foreground(appwin->visinfo,gc,255,255,255); + gck_gc_set_background(appwin->visinfo,gc,0,0,0); + + gdk_gc_set_function(gc,GDK_COPY); + linetab[0].x1=-1; + + pw=PREVIEW_WIDTH >> mapvals.preview_zoom_factor; + ph=PREVIEW_HEIGHT >> mapvals.preview_zoom_factor; + startx=(PREVIEW_WIDTH-pw)>>1; + starty=(PREVIEW_HEIGHT-ph)>>1; + + if (docompute==TRUE) + { + gck_cursor_set(previewarea->window,GDK_WATCH); + compute_preview(0,0,width-1,height-1,pw,ph); + gck_cursor_set(previewarea->window,GDK_HAND2); + clear_light_marker(); + } + + if (pw!=PREVIEW_WIDTH) + gdk_window_clear(previewarea->window); + + gdk_draw_image(previewarea->window,gc,image,0,0,startx,starty,pw,ph); + draw_lights(startx,starty,pw,ph); +} + +/**************************/ +/* Draw preview wireframe */ +/**************************/ + +void draw_preview_wireframe(void) +{ + gint startx,starty,pw,ph; + + gck_gc_set_foreground(appwin->visinfo,gc,255,255,255); + gck_gc_set_background(appwin->visinfo,gc,0,0,0); + + gdk_gc_set_function(gc,GDK_INVERT); + + pw=PREVIEW_WIDTH >> mapvals.preview_zoom_factor; + ph=PREVIEW_HEIGHT >> mapvals.preview_zoom_factor; + startx=(PREVIEW_WIDTH-pw)>>1; + starty=(PREVIEW_HEIGHT-ph)>>1; + + clear_wireframe(); + draw_wireframe(startx,starty,pw,ph); +} + +/****************************/ +/* Draw a wireframe preview */ +/****************************/ + +void draw_wireframe(gint startx,gint starty,gint pw,gint ph) +{ + switch (mapvals.maptype) + { + case MAP_PLANE: + draw_wireframe_plane(startx,starty,pw,ph); + break; + case MAP_SPHERE: + draw_wireframe_sphere(startx,starty,pw,ph); + break; + } +} + +void draw_wireframe_plane(gint startx,gint starty,gint pw,gint ph) +{ + GckVector3 v1,v2,a,b,c,d,dir1,dir2; + gint cnt,n=0; + gdouble x1,y1,x2,y2,cx1,cy1,cx2,cy2,fac; + + /* Find rotated box corners */ + /* ======================== */ + + gck_vector3_set(&v1,0.5,0.0,0.0); + gck_vector3_set(&v2,0.0,0.5,0.0); + + gck_vector3_rotate(&v1,gck_deg_to_rad(mapvals.alpha), + gck_deg_to_rad(mapvals.beta),gck_deg_to_rad(mapvals.gamma)); + gck_vector3_rotate(&v2,gck_deg_to_rad(mapvals.alpha), + gck_deg_to_rad(mapvals.beta),gck_deg_to_rad(mapvals.gamma)); + + dir1=v1; gck_vector3_normalize(&dir1); + dir2=v2; gck_vector3_normalize(&dir2); + + fac=1.0/(gdouble)WIRESIZE; + + gck_vector3_mul(&dir1,fac); + gck_vector3_mul(&dir2,fac); + + gck_vector3_add(&a,&mapvals.position,&v1); + gck_vector3_sub(&b,&a,&v2); + gck_vector3_add(&a,&a,&v2); + gck_vector3_sub(&d,&mapvals.position,&v1); + gck_vector3_sub(&d,&d,&v2); + + c=b; + + cx1=(gdouble)startx; + cy1=(gdouble)starty; + cx2=cx1+(gdouble)pw; + cy2=cy1+(gdouble)ph; + + for (cnt=0;cnt<=WIRESIZE;cnt++) + { + gck_3d_to_2d(startx,starty,pw,ph,&x1,&y1,&mapvals.viewpoint,&a); + gck_3d_to_2d(startx,starty,pw,ph,&x2,&y2,&mapvals.viewpoint,&b); + + if (gck_clip_line(&x1,&y1,&x2,&y2,cx1,cy1,cx2,cy2)==TRUE) + { + linetab[n].x1=(gint)(x1+0.5); + linetab[n].y1=(gint)(y1+0.5); + linetab[n].x2=(gint)(x2+0.5); + linetab[n].y2=(gint)(y2+0.5); + linetab[n].linewidth=1; + linetab[n].linestyle=GDK_LINE_SOLID; + gdk_gc_set_line_attributes(gc,linetab[n].linewidth,linetab[n].linestyle,GDK_CAP_NOT_LAST,GDK_JOIN_MITER); + gdk_draw_line(previewarea->window,gc,linetab[n].x1,linetab[n].y1,linetab[n].x2,linetab[n].y2); + n++; + } + + gck_3d_to_2d(startx,starty,pw,ph,&x1,&y1,&mapvals.viewpoint,&c); + gck_3d_to_2d(startx,starty,pw,ph,&x2,&y2,&mapvals.viewpoint,&d); + + if (gck_clip_line(&x1,&y1,&x2,&y2,cx1,cy1,cx2,cy2)==TRUE) + { + linetab[n].x1=(gint)(x1+0.5); + linetab[n].y1=(gint)(y1+0.5); + linetab[n].x2=(gint)(x2+0.5); + linetab[n].y2=(gint)(y2+0.5); + linetab[n].linewidth=1; + linetab[n].linestyle=GDK_LINE_SOLID; + gdk_gc_set_line_attributes(gc,linetab[n].linewidth,linetab[n].linestyle,GDK_CAP_NOT_LAST,GDK_JOIN_MITER); + gdk_draw_line(previewarea->window,gc,linetab[n].x1,linetab[n].y1,linetab[n].x2,linetab[n].y2); + n++; + } + + gck_vector3_sub(&a,&a,&dir1); + gck_vector3_sub(&b,&b,&dir1); + gck_vector3_add(&c,&c,&dir2); + gck_vector3_add(&d,&d,&dir2); + } + + /* Mark end of lines */ + /* ================= */ + + linetab[n].x1=-1; +} + +void draw_wireframe_sphere(gint startx,gint starty,gint pw,gint ph) +{ + GckVector3 p[2*(WIRESIZE+5)]; + gint cnt,cnt2,n=0; + gdouble x1,y1,x2,y2,twopifac,cx1,cy1,cx2,cy2; + + /* Compute wireframe points */ + /* ======================== */ + + twopifac=(2.0*M_PI)/WIRESIZE; + + for (cnt=0;cntmapvals.position.z && p[cnt+1].z>mapvals.position.z) + { + gck_3d_to_2d(startx,starty,pw,ph,&x1,&y1,&mapvals.viewpoint,&p[cnt]); + gck_3d_to_2d(startx,starty,pw,ph,&x2,&y2,&mapvals.viewpoint,&p[cnt+1]); + + if (gck_clip_line(&x1,&y1,&x2,&y2,cx1,cy1,cx2,cy2)==TRUE) + { + linetab[n].x1=(gint)(x1+0.5); + linetab[n].y1=(gint)(y1+0.5); + linetab[n].x2=(gint)(x2+0.5); + linetab[n].y2=(gint)(y2+0.5); + linetab[n].linewidth=3; + linetab[n].linestyle=GDK_LINE_SOLID; + gdk_gc_set_line_attributes(gc,linetab[n].linewidth,linetab[n].linestyle,GDK_CAP_NOT_LAST,GDK_JOIN_MITER); + gdk_draw_line(previewarea->window,gc,linetab[n].x1,linetab[n].y1,linetab[n].x2,linetab[n].y2); + n++; + } + } + } + + /* Draw the axis (pole to pole and center to zero meridian) */ + /* ======================================================== */ + + for (cnt=0;cnt<3;cnt++) + { + gck_3d_to_2d(startx,starty,pw,ph,&x1,&y1,&mapvals.viewpoint,&p[cnt2]); + gck_3d_to_2d(startx,starty,pw,ph,&x2,&y2,&mapvals.viewpoint,&p[cnt2+1]); + + if (gck_clip_line(&x1,&y1,&x2,&y2,cx1,cy1,cx2,cy2)==TRUE) + { + linetab[n].x1=(gint)(x1+0.5); + linetab[n].y1=(gint)(y1+0.5); + linetab[n].x2=(gint)(x2+0.5); + linetab[n].y2=(gint)(y2+0.5); + + if (p[cnt2].zwindow,gc,linetab[n].x1,linetab[n].y1,linetab[n].x2,linetab[n].y2); + n++; + } + cnt2+=2; + } + + /* Mark end of lines */ + /* ================= */ + + linetab[n].x1=-1; +} + +void clear_wireframe(void) +{ + gint n=0; + + while (linetab[n].x1!=-1) + { + gdk_gc_set_line_attributes(gc,linetab[n].linewidth,linetab[n].linestyle,GDK_CAP_NOT_LAST,GDK_JOIN_MITER); + gdk_draw_line(previewarea->window,gc,linetab[n].x1,linetab[n].y1, + linetab[n].x2,linetab[n].y2); + n++; + } +} diff --git a/plug-ins/MapObject/mapobject_preview.h b/plug-ins/MapObject/mapobject_preview.h new file mode 100644 index 0000000000..16ab8242b2 --- /dev/null +++ b/plug-ins/MapObject/mapobject_preview.h @@ -0,0 +1,56 @@ +#ifndef MAPOBJECTPREVIEWH +#define MAPOBJECTPREVIEWH + +#include +#include +#include +#include +#include +#include +#include + +#include "arcball.h" +#include "mapobject_main.h" +#include "mapobject_ui.h" +#include "mapobject_image.h" +#include "mapobject_apply.h" +#include "mapobject_shade.h" + +#define PREVIEW_WIDTH 200 +#define PREVIEW_HEIGHT 200 + +#define WIRESIZE 16 + +typedef struct +{ + gint x1,y1,x2,y2; + gint linewidth; + GdkLineStyle linestyle; +} line; + +typedef struct +{ + gint x,y,w,h; + GdkImage *image; +} BackBuffer; + +/* Externally visible variables */ +/* ============================ */ + +extern line linetab[]; +extern gdouble mat[3][4]; +extern gint lightx,lighty; +extern BackBuffer backbuf; + +/* Externally visible functions */ +/* ============================ */ + +extern void compute_preview (gint x,gint y,gint w,gint h,gint pw,gint ph); +extern void draw_wireframe (gint startx,gint starty,gint pw,gint ph); +extern void clear_wireframe (void); +extern void draw_preview_image (gint docompute); +extern void draw_preview_wireframe (void); +extern gint check_light_hit (gint xpos,gint ypos); +extern void update_light (gint xpos,gint ypos); + +#endif diff --git a/plug-ins/MapObject/mapobject_shade.c b/plug-ins/MapObject/mapobject_shade.c new file mode 100644 index 0000000000..7d60d98654 --- /dev/null +++ b/plug-ins/MapObject/mapobject_shade.c @@ -0,0 +1,413 @@ +/*****************/ +/* Shading stuff */ +/*****************/ + +#include "mapobject_shade.h" + +gdouble bx1,by1,bx2,by2; +get_ray_color_func get_ray_color; + +/*****************/ +/* Phong shading */ +/*****************/ + +GckRGB phong_shade(GckVector3 *pos,GckVector3 *viewpoint,GckVector3 *normal,GckVector3 *light, + GckRGB *diff_col,GckRGB *spec_col,gint type) +{ + GckRGB ambientcolor,diffusecolor,specularcolor; + gdouble NL,RV,dist; + GckVector3 L,NN,V,N; + + /* Compute ambient intensity */ + /* ========================= */ + + N=*normal; + ambientcolor=*diff_col; + gck_rgb_mul(&ambientcolor,mapvals.material.ambient_int); + + /* Compute (N*L) term of Phong's equation */ + /* ====================================== */ + + if (type==POINT_LIGHT) + gck_vector3_sub(&L,light,pos); + else + L=*light; + + dist=gck_vector3_length(&L); + + if (dist!=0.0) + gck_vector3_mul(&L,1.0/dist); + + NL=2.0*gck_vector3_inner_product(&N,&L); + + if (NL>=0.0) + { + /* Compute (R*V)^alpha term of Phong's equation */ + /* ============================================ */ + + gck_vector3_sub(&V,viewpoint,pos); + gck_vector3_normalize(&V); + + gck_vector3_mul(&N,NL); + gck_vector3_sub(&NN,&N,&L); + RV=gck_vector3_inner_product(&NN,&V); + RV=pow(RV,mapvals.material.highlight); + + /* Compute diffuse and specular intensity contribution */ + /* =================================================== */ + + diffusecolor=*diff_col; + gck_rgb_mul(&diffusecolor,mapvals.material.diffuse_ref); + gck_rgb_mul(&diffusecolor,NL); + + specularcolor=*spec_col; + gck_rgb_mul(&specularcolor,mapvals.material.specular_ref); + gck_rgb_mul(&specularcolor,RV); + + gck_rgb_add(&diffusecolor,&specularcolor); + gck_rgb_mul(&diffusecolor,mapvals.material.diffuse_int); + gck_rgb_clamp(&diffusecolor); + + gck_rgb_add(&ambientcolor,&diffusecolor); + } + + return(ambientcolor); +} + +gint plane_intersect(GckVector3 *dir,GckVector3 *viewp,GckVector3 *ipos,gdouble *u,gdouble *v) +{ + static gdouble det,det1,det2,det3,t; + + imat[0][0]=dir->x; imat[1][0]=dir->y; imat[2][0]=dir->z; + + /* Compute determinant of the first 3x3 sub matrix (denominator) */ + /* ============================================================= */ + + det=imat[0][0]*imat[1][1]*imat[2][2]+imat[0][1]*imat[1][2]*imat[2][0]+ + imat[0][2]*imat[1][0]*imat[2][1]-imat[0][2]*imat[1][1]*imat[2][0]- + imat[0][0]*imat[1][2]*imat[2][1]-imat[2][2]*imat[0][1]*imat[1][0]; + + /* If the determinant is non-zero, a intersection point exists */ + /* =========================================================== */ + + if (det!=0.0) + { + /* Now, lets compute the numerator determinants (wow ;) */ + /* ==================================================== */ + + det1=imat[0][3]*imat[1][1]*imat[2][2]+imat[0][1]*imat[1][2]*imat[2][3]+ + imat[0][2]*imat[1][3]*imat[2][1]-imat[0][2]*imat[1][1]*imat[2][3]- + imat[1][2]*imat[2][1]*imat[0][3]-imat[2][2]*imat[0][1]*imat[1][3]; + + det2=imat[0][0]*imat[1][3]*imat[2][2]+imat[0][3]*imat[1][2]*imat[2][0]+ + imat[0][2]*imat[1][0]*imat[2][3]-imat[0][2]*imat[1][3]*imat[2][0]- + imat[1][2]*imat[2][3]*imat[0][0]-imat[2][2]*imat[0][3]*imat[1][0]; + + det3=imat[0][0]*imat[1][1]*imat[2][3]+imat[0][1]*imat[1][3]*imat[2][0]+ + imat[0][3]*imat[1][0]*imat[2][1]-imat[0][3]*imat[1][1]*imat[2][0]- + imat[1][3]*imat[2][1]*imat[0][0]-imat[2][3]*imat[0][1]*imat[1][0]; + + /* Now we have the simultanous solutions. Lets compute the unknowns */ + /* (skip u&v if t is <0, this means the intersection is behind us) */ + /* ================================================================ */ + + t=det1/det; + + if (t>0.0) + { + *u=1.0+((det2/det)-0.5); + *v=1.0+((det3/det)-0.5); + + ipos->x=viewp->x+t*dir->x; + ipos->y=viewp->y+t*dir->y; + ipos->z=viewp->z+t*dir->z; + + return(TRUE); + } + } + + return(FALSE); +} + +/**********************************************************************************/ +/* These routines computes the color of the surface of the plane at a given point */ +/**********************************************************************************/ + +GckRGB get_ray_color_plane(GckVector3 *pos) +{ + GckRGB color=background; + static gint inside=FALSE; + static GckVector3 ray,spos; + static gdouble vx,vy; + + /* Construct a line from our VP to the point */ + /* ========================================= */ + + gck_vector3_sub(&ray,pos,&mapvals.viewpoint); + gck_vector3_normalize(&ray); + + /* Check for intersection. This is a quasi ray-tracer. */ + /* =================================================== */ + + if (plane_intersect(&ray,&mapvals.viewpoint,&spos,&vx,&vy)==TRUE) + { + color=get_image_color(vx,vy,&inside); + + if (color.a!=0.0 && inside==TRUE && mapvals.lightsource.type!=NO_LIGHT) + { + /* Compute shading at this point */ + /* ============================= */ + + color=phong_shade(&spos,&mapvals.viewpoint,&mapvals.normal, + &mapvals.lightsource.position,&color, + &mapvals.lightsource.color,mapvals.lightsource.type); + + gck_rgb_clamp(&color); + } + } + + + if (color.a==0.0) + color=background; + + return(color); +} + +/***********************************************************************/ +/* Given the NorthPole, Equator and a third vector (normal) compute */ +/* the conversion from spherical oordinates to image space coordinates */ +/***********************************************************************/ + +void sphere_to_image(GckVector3 *normal,gdouble *u,gdouble *v) +{ + static gdouble alpha,fac; + static GckVector3 cross_prod; + + alpha=acos(-gck_vector3_inner_product(&mapvals.secondaxis,normal)); + + *v=alpha/M_PI; + + if (*v==0.0 || *v==1.0) *u=0.0; + else + { + fac=gck_vector3_inner_product(&mapvals.firstaxis,normal)/sin(alpha); + + /* Make sure that we map to -1.0..1.0 (take care of rounding errors) */ + /* ================================================================= */ + + if (fac>1.0) + fac=1.0; + else if (fac<-1.0) + fac=-1.0; + + *u=acos(fac)/(2.0*M_PI); + + cross_prod=gck_vector3_cross_product(&mapvals.secondaxis,&mapvals.firstaxis); + + if (gck_vector3_inner_product(&cross_prod,normal)<0.0) + *u=1.0-*u; + } +} + +/***************************************************/ +/* Compute intersection point with sphere (if any) */ +/***************************************************/ + +gint sphere_intersect(GckVector3 *dir,GckVector3 *viewp,GckVector3 *spos1,GckVector3 *spos2) +{ + static gdouble alpha,beta,tau,s1,s2,tmp; + static GckVector3 t; + + gck_vector3_sub(&t,&mapvals.position,viewp); + + alpha=gck_vector3_inner_product(dir,&t); + beta=gck_vector3_inner_product(&t,&t); + + tau=alpha*alpha-beta+mapvals.radius*mapvals.radius; + + if (tau>=0.0) + { + tau=sqrt(tau); + s1=alpha+tau; + s2=alpha-tau; + + if (s2x=viewp->x+s1*dir->x; + spos1->y=viewp->y+s1*dir->y; + spos1->z=viewp->z+s1*dir->z; + spos2->x=viewp->x+s2*dir->x; + spos2->y=viewp->y+s2*dir->y; + spos2->z=viewp->z+s2*dir->z; + + return(TRUE); + } + + return(FALSE); +} + +/***********************************************************************************/ +/* These routines computes the color of the surface of the sphere at a given point */ +/***********************************************************************************/ + +GckRGB get_ray_color_sphere(GckVector3 *pos) +{ + GckRGB color=background; + static GckRGB color2; + static gint inside=FALSE; + static GckVector3 normal,ray,spos1,spos2; + static gdouble vx,vy; + + /* Check if ray is within the bounding box */ + /* ======================================= */ + + if (pos->xx>bx2 || pos->yy>by2) + return(color); + + /* Construct a line from our VP to the point */ + /* ========================================= */ + + gck_vector3_sub(&ray,pos,&mapvals.viewpoint); + gck_vector3_normalize(&ray); + + /* Check for intersection. This is a quasi ray-tracer. */ + /* =================================================== */ + + if (sphere_intersect(&ray,&mapvals.viewpoint,&spos1,&spos2)==TRUE) + { + /* Compute spherical to rectangular mapping */ + /* ======================================== */ + + gck_vector3_sub(&normal,&spos1,&mapvals.position); + gck_vector3_normalize(&normal); + sphere_to_image(&normal,&vx,&vy); + color=get_image_color(vx,vy,&inside); + + /* Check for total transparency... */ + /* =============================== */ + + if (color.a<1.0) + { + /* Hey, we can see through here! */ + /* Lets see what's on the other side.. */ + /* =================================== */ + + color=phong_shade(&spos1, + &mapvals.viewpoint, + &normal, + &mapvals.lightsource.position, + &color, + &mapvals.lightsource.color, + mapvals.lightsource.type); + + gck_rgba_clamp(&color); + + gck_vector3_sub(&normal,&spos2,&mapvals.position); + gck_vector3_normalize(&normal); + sphere_to_image(&normal,&vx,&vy); + color2=get_image_color(vx,vy,&inside); + + /* Make the normal point inwards */ + /* ============================= */ + + gck_vector3_mul(&normal,-1.0); + + color2=phong_shade(&spos2, + &mapvals.viewpoint, + &normal, + &mapvals.lightsource.position, + &color2, + &mapvals.lightsource.color, + mapvals.lightsource.type); + + gck_rgba_clamp(&color2); + + if (mapvals.transparent_background==FALSE && color2.a<1.0) + { + color2.r = (color2.r*color2.a)+(background.r*(1.0-color2.a)); + color2.g = (color2.g*color2.a)+(background.g*(1.0-color2.a)); + color2.b = (color2.b*color2.a)+(background.b*(1.0-color2.a)); + color2.a = 1.0; + } + + /* Compute a mix of the first and second colors */ + /* ============================================ */ + + color.r = color.r*color2.r; + color.g = color.g*color2.g; + color.b = color.b*color2.b; + color.a = color.a+color2.a; + + gck_rgba_clamp(&color); + } + else if (color.a!=0.0 && inside==TRUE && mapvals.lightsource.type!=NO_LIGHT) + { + /* Compute shading at this point */ + /* ============================= */ + + color=phong_shade(&spos1, + &mapvals.viewpoint, + &normal, + &mapvals.lightsource.position, + &color, + &mapvals.lightsource.color, + mapvals.lightsource.type); + + gck_rgba_clamp(&color); + } + } + + if (color.a==0.0) + color=background; + + return(color); +} + +/***************************************************/ +/* Transform the corners of the bounding box to 2D */ +/***************************************************/ + +void compute_bounding_box(void) +{ + GckVector3 p1,p2; + gdouble t; + GckVector3 dir; + + p1=mapvals.position; + p1.x-=(mapvals.radius+0.01); + p1.y-=(mapvals.radius+0.01); + + p2=mapvals.position; + p2.x+=(mapvals.radius+0.01); + p2.y+=(mapvals.radius+0.01); + + gck_vector3_sub(&dir,&p1,&mapvals.viewpoint); + gck_vector3_normalize(&dir); + + if (dir.z!=0.0) + { + t=(-1.0*mapvals.viewpoint.z)/dir.z; + p1.x=(mapvals.viewpoint.x+t*dir.x); + p1.y=(mapvals.viewpoint.y+t*dir.y); + } + + gck_vector3_sub(&dir,&p2,&mapvals.viewpoint); + gck_vector3_normalize(&dir); + + if (dir.z!=0.0) + { + t=(-1.0*mapvals.viewpoint.z)/dir.z; + p2.x=(mapvals.viewpoint.x+t*dir.x); + p2.y=(mapvals.viewpoint.y+t*dir.y); + } + + bx1=p1.x; + by1=p1.y; + bx2=p2.x; + by2=p2.y; +} diff --git a/plug-ins/MapObject/mapobject_shade.h b/plug-ins/MapObject/mapobject_shade.h new file mode 100644 index 0000000000..5f45bc7d8d --- /dev/null +++ b/plug-ins/MapObject/mapobject_shade.h @@ -0,0 +1,21 @@ +#ifndef MAPOBJECTSHADEH +#define MAPOBJECTSHADEH + +#include +#include +#include +#include +#include + +#include "mapobject_main.h" +#include "mapobject_image.h" + +typedef GckRGB (*get_ray_color_func)(GckVector3 *pos); + +extern get_ray_color_func get_ray_color; +extern GckRGB get_ray_color_plane (GckVector3 *pos); +extern GckRGB get_ray_color_sphere (GckVector3 *pos); +extern void compute_bounding_box (void); + + +#endif diff --git a/plug-ins/MapObject/mapobject_ui.c b/plug-ins/MapObject/mapobject_ui.c new file mode 100644 index 0000000000..4afba5610b --- /dev/null +++ b/plug-ins/MapObject/mapobject_ui.c @@ -0,0 +1,1095 @@ +/**************************************************************/ +/* Dialog creation and updaters, callbacks and event-handlers */ +/**************************************************************/ + +#include "mapobject_ui.h" +#include "mapobject_pixmaps.h" + +extern MapObjectValues mapvals; + +GckApplicationWindow *appwin = NULL; +GtkWidget *color_select_diag = NULL; +GtkNotebook *options_note_book = NULL; +GtkTooltips *tooltips = NULL; + +GdkGC *gc = NULL; +GtkWidget *previewarea,*pointlightwid,*dirlightwid; +GtkWidget *xentry,*yentry,*zentry; + +GckRGB old_light_color; + +gint color_dialog_id = -1; + +guint left_button_pressed = FALSE, light_hit = FALSE; +guint32 blackpixel,whitepixel; + +GckScaleValues angle_scale_vals = { 180, 0.0, -180.0, 180.0, 0.1, 1.0, 1.0, GTK_UPDATE_CONTINUOUS,TRUE }; +GckScaleValues sample_scale_vals = { 128, 3.0, 1.0, 6.0, 1.0, 1.0, 1.0, GTK_UPDATE_CONTINUOUS,TRUE }; + +gchar *light_labels[] = + { + "Point light", + "Directional light", + "No light", + NULL + }; + +gchar *map_labels[] = + { + "Plane", + "Sphere", + NULL + }; + +/**********/ +/* Protos */ +/**********/ + +void create_main_dialog (void); +void create_main_notebook (GtkWidget *); + +/**************************/ +/* Callbacks and updaters */ +/**************************/ + +gint preview_events (GtkWidget *area, GdkEvent *event); + +void update_slider (void); +void update_angle_sliders (void); +void update_light_pos_entries (void); + +void xyzval_update (GtkWidget *widget, GtkEntry *entry); +void entry_update (GtkWidget *widget, GtkEntry *entry); +void angle_update (GtkWidget *widget, GtkScale *scale); +void scale_update (GtkWidget *widget, GtkScale *scale); +void toggle_update (GtkWidget *widget, GtkCheckButton *button); +void togglegrid_update (GtkWidget *widget, GtkCheckButton *button); +void toggletile_update (GtkWidget *widget, GtkCheckButton *button); +void toggleanti_update (GtkWidget *widget, GtkCheckButton *button); +void toggletips_update (GtkWidget *widget, GtkCheckButton *button); +void toggletrans_update (GtkWidget *widget, GtkCheckButton *button); + +void lightmenu_callback (GtkWidget *widget, gpointer client_data); +void preview_callback (GtkWidget *widget, gpointer client_data); +void apply_callback (GtkWidget *widget, gpointer client_data); +void exit_callback (GtkWidget *widget, gpointer client_data); +void color_ok_callback (GtkWidget *widget, gpointer client_data); +void color_cancel_callback (GtkWidget *widget, gpointer client_data); +void light_color_callback (GtkWidget *widget, gpointer client_data); +gint color_delete_callback (GtkWidget *widget, GdkEvent *event, gpointer client_data); +void color_changed_callback (GtkColorSelection *colorsel, gpointer client_data); + +GtkWidget *create_options_page (void); +GtkWidget *create_light_page (void); +GtkWidget *create_material_page (void); +GtkWidget *create_orientation_page (void); + +/******************/ +/* Implementation */ +/******************/ + +/**********************************************************/ +/* Update entry fields that affect the preview parameters */ +/**********************************************************/ + +void xyzval_update(GtkWidget *widget, GtkEntry *entry) +{ + gdouble *valueptr; + gdouble value; + + valueptr=(gdouble *)gtk_object_get_data(GTK_OBJECT(widget),"ValuePtr"); + value = atof(gtk_entry_get_text(entry)); + + *valueptr=value; + + if (mapvals.showgrid==TRUE) + draw_preview_wireframe(); +} + +/*********************/ +/* Std. entry update */ +/*********************/ + +void entry_update(GtkWidget *widget, GtkEntry *entry) +{ + gdouble *valueptr; + gdouble value; + + valueptr=(gdouble *)gtk_object_get_data(GTK_OBJECT(widget),"ValuePtr"); + value = atof(gtk_entry_get_text(entry)); + + *valueptr=value; +} + +/***************************************************/ +/* Update angle sliders (redraw grid if necessary) */ +/***************************************************/ + +void angle_update(GtkWidget *widget, GtkScale *scale) +{ + gdouble *valueptr; + GtkAdjustment *adjustment; + + valueptr=(gdouble *)gtk_object_get_data(GTK_OBJECT(widget),"ValuePtr"); + adjustment=gtk_range_get_adjustment(GTK_RANGE(scale)); + + *valueptr=(gdouble)adjustment->value; + + if (mapvals.showgrid==TRUE) + draw_preview_wireframe(); +} + +void update_light_pos_entries(void) +{ + gchar entrytext[64]; + + sprintf(entrytext,"%f",mapvals.lightsource.position.x); + gtk_entry_set_text(GTK_ENTRY(xentry),entrytext); + sprintf(entrytext,"%f",mapvals.lightsource.position.y); + gtk_entry_set_text(GTK_ENTRY(yentry),entrytext); + sprintf(entrytext,"%f",mapvals.lightsource.position.z); + gtk_entry_set_text(GTK_ENTRY(zentry),entrytext); +} + +void update_slider(void) +{ +} + +void update_angle_sliders(void) +{ +} + +/*********************/ +/* Std. scale update */ +/*********************/ + +void scale_update(GtkWidget *widget,GtkScale *scale) +{ + gdouble *valueptr; + GtkAdjustment *adjustment; + + valueptr=(gdouble *)gtk_object_get_data(GTK_OBJECT(widget),"ValuePtr"); + adjustment=gtk_range_get_adjustment(GTK_RANGE(scale)); + + *valueptr=(gdouble)adjustment->value; +} + +/**********************/ +/* Std. toggle update */ +/**********************/ + +void toggle_update(GtkWidget *widget, GtkCheckButton *button) +{ + gint *value; + + value=(gint *)gtk_object_get_data(GTK_OBJECT(button),"ValuePtr"); + *value=!(*value); +} + +/***************************/ +/* Show grid toggle update */ +/***************************/ + +void togglegrid_update(GtkWidget *widget, GtkCheckButton *button) +{ + gint *value; + + value=(gint *)gtk_object_get_data(GTK_OBJECT(button),"ValuePtr"); + *value=!(*value); + + if (mapvals.showgrid==TRUE && linetab[0].x1==-1) + draw_preview_wireframe(); + else if (mapvals.showgrid==FALSE && linetab[0].x1!=-1) + { + gck_gc_set_foreground(appwin->visinfo,gc,255,255,255); + gck_gc_set_background(appwin->visinfo,gc,0,0,0); + + gdk_gc_set_function(gc,GDK_INVERT); + + clear_wireframe(); + linetab[0].x1=-1; + } +} + +/****************************/ +/* Tile image toggle update */ +/****************************/ + +void toggletile_update(GtkWidget *widget, GtkCheckButton *button) +{ + gint *value; + + value=(gint *)gtk_object_get_data(GTK_OBJECT(button),"ValuePtr"); + *value=!(*value); + + draw_preview_image(TRUE); + linetab[0].x1=-1; +} + +/******************************/ +/* Antialiasing toggle update */ +/******************************/ + +void toggleanti_update(GtkWidget *widget, GtkCheckButton *button) +{ + gint *value; + + value=(gint *)gtk_object_get_data(GTK_OBJECT(button),"ValuePtr"); + *value=!(*value); +} + +/**************************/ +/* Tooltips toggle update */ +/**************************/ + +void toggletips_update(GtkWidget *widget, GtkCheckButton *button) +{ + gint *value; + + value=(gint *)gtk_object_get_data(GTK_OBJECT(button),"ValuePtr"); + *value=!(*value); + + if (tooltips!=NULL) + { + if (mapvals.tooltips_enabled==TRUE) + gtk_tooltips_enable(tooltips); + else + gtk_tooltips_disable(tooltips); + } +} + +/****************************************/ +/* Transparent background toggle update */ +/****************************************/ + +void toggletrans_update(GtkWidget *widget, GtkCheckButton *button) +{ + gint *value; + + value=(gint *)gtk_object_get_data(GTK_OBJECT(button),"ValuePtr"); + *value=!(*value); + + draw_preview_image(TRUE); + linetab[0].x1=-1; +} + +/*****************************************/ +/* Main window light type menu callback. */ +/*****************************************/ + +void lightmenu_callback(GtkWidget *widget, gpointer client_data) +{ + mapvals.lightsource.type=(gint)gtk_object_get_data(GTK_OBJECT(widget),"_GckOptionMenuItemID"); + + if (mapvals.lightsource.type==POINT_LIGHT) + { + gtk_widget_hide(dirlightwid); + gtk_widget_show(pointlightwid); + } + else if (mapvals.lightsource.type==DIRECTIONAL_LIGHT) + { + gtk_widget_hide(pointlightwid); + gtk_widget_show(dirlightwid); + } + else + { + gtk_widget_hide(pointlightwid); + gtk_widget_hide(dirlightwid); + } +} + +/***************************************/ +/* Main window map type menu callback. */ +/***************************************/ + +void mapmenu_callback(GtkWidget *widget, gpointer client_data) +{ + mapvals.maptype=(MapType)gtk_object_get_data(GTK_OBJECT(widget),"_GckOptionMenuItemID"); + + draw_preview_image(TRUE); + + if (mapvals.showgrid==TRUE && linetab[0].x1==-1) + draw_preview_wireframe(); + else if (mapvals.showgrid==FALSE && linetab[0].x1!=-1) + { + gck_gc_set_foreground(appwin->visinfo,gc,255,255,255); + gck_gc_set_background(appwin->visinfo,gc,0,0,0); + + gdk_gc_set_function(gc,GDK_INVERT); + + clear_wireframe(); + linetab[0].x1=-1; + } +} + +/******************************************/ +/* Main window "Preview!" button callback */ +/******************************************/ + +void preview_callback(GtkWidget *widget, gpointer client_data) +{ + draw_preview_image(TRUE); + linetab[0].x1=-1; +} + +/*********************************************/ +/* Main window "-" (zoom in) button callback */ +/*********************************************/ + +void zoomout_callback(GtkWidget *widget, gpointer client_data) +{ + if (mapvals.preview_zoom_factor<2) + { + mapvals.preview_zoom_factor++; + if (linetab[0].x1!=-1) + clear_wireframe(); + draw_preview_image(TRUE); + } +} + +/*********************************************/ +/* Main window "+" (zoom out) button callback */ +/*********************************************/ + +void zoomin_callback(GtkWidget *widget, gpointer client_data) +{ + if (mapvals.preview_zoom_factor>0) + { + mapvals.preview_zoom_factor--; + if (linetab[0].x1!=-1) + clear_wireframe(); + draw_preview_image(TRUE); + } +} + +/**********************************************/ +/* Main window "Apply" button callback. */ +/* Render to GIMP image, close down and exit. */ +/**********************************************/ + +void apply_callback(GtkWidget *widget, gpointer client_data) +{ + if (preview_rgb_data!=NULL) + free(preview_rgb_data); + + if (image!=NULL) + gdk_image_destroy(image); + + gtk_object_unref(GTK_OBJECT(tooltips)); + gck_application_window_destroy(appwin); + gdk_flush(); + + compute_image(); + + gtk_main_quit(); +} + +/*************************************************************/ +/* Main window "Cancel" button callback. Shut down and exit. */ +/*************************************************************/ + +void exit_callback(GtkWidget *widget, gpointer client_data) +{ + if (preview_rgb_data!=NULL) + free(preview_rgb_data); + + if (image!=NULL) + gdk_image_destroy(image); + + if (backbuf.image!=NULL) + gdk_image_destroy(backbuf.image); + + gtk_object_unref(GTK_OBJECT(tooltips)); + gck_application_window_destroy(appwin); + + gtk_main_quit(); +} + +/*************************************/ +/* Color dialog "Ok" button callback */ +/*************************************/ + +void color_ok_callback(GtkWidget *widget, gpointer client_data) +{ + gtk_widget_destroy(color_select_diag); + color_select_diag=NULL; +} + +/********************************************/ +/* Color dialog "Cancel" button callback. */ +/* Close dialog & restore old color values. */ +/********************************************/ + +void color_changed_callback (GtkColorSelection *colorsel, gpointer client_data) +{ + gdouble color[3]; + + gtk_color_selection_get_color(colorsel, color); + mapvals.lightsource.color.r=color[0]; + mapvals.lightsource.color.g=color[1]; + mapvals.lightsource.color.b=color[2]; +} + +gint color_delete_callback(GtkWidget *widget, GdkEvent *event, gpointer client_data) +{ + color_select_diag=NULL; + return FALSE; +} + +void color_cancel_callback(GtkWidget *widget, gpointer client_data) +{ + gtk_widget_destroy(color_select_diag); + color_select_diag=NULL; +} + +void light_color_callback(GtkWidget *widget, gpointer client_data) +{ + GtkColorSelectionDialog *csd; + + if (mapvals.lightsource.type!=NO_LIGHT && color_select_diag==NULL) + { + color_select_diag=gtk_color_selection_dialog_new("Select lightsource color"); + gtk_window_position (GTK_WINDOW (color_select_diag), GTK_WIN_POS_MOUSE); + gtk_widget_show(color_select_diag); + csd=GTK_COLOR_SELECTION_DIALOG(color_select_diag); + gtk_signal_connect(GTK_OBJECT(csd),"delete_event", + (GtkSignalFunc)color_delete_callback,(gpointer)color_select_diag); + gtk_signal_connect(GTK_OBJECT(csd->ok_button),"clicked", + (GtkSignalFunc)color_ok_callback,(gpointer)color_select_diag); + gtk_signal_connect(GTK_OBJECT(csd->cancel_button),"clicked", + (GtkSignalFunc)color_cancel_callback,(gpointer)color_select_diag); + gtk_signal_connect(GTK_OBJECT(csd->colorsel),"color_changed", + (GtkSignalFunc)color_changed_callback,(gpointer)color_select_diag); + } +} + +/******************************/ +/* Preview area event handler */ +/******************************/ + +gint preview_events(GtkWidget *area, GdkEvent *event) +{ + HVect pos; +/* HMatrix RotMat; + gdouble a,b,c; */ + + switch (event->type) + { + case GDK_EXPOSE: + + /* Is this the first exposure? */ + /* =========================== */ + + if (!gc) + { + gc=gdk_gc_new(area->window); + draw_preview_image(TRUE); + } + else + { + draw_preview_image(FALSE); + if (mapvals.showgrid==1 && linetab[0].x1!=-1) + draw_preview_wireframe(); + } + break; + case GDK_ENTER_NOTIFY: + break; + case GDK_LEAVE_NOTIFY: + break; + case GDK_BUTTON_PRESS: + light_hit=check_light_hit(event->button.x,event->button.y); + if (light_hit==FALSE) + { + pos.x=-(2.0*(gdouble)event->button.x/(gdouble)PREVIEW_WIDTH-1.0); + pos.y=2.0*(gdouble)event->button.y/(gdouble)PREVIEW_HEIGHT-1.0; + /*ArcBall_Mouse(pos); + ArcBall_BeginDrag(); */ + } + left_button_pressed=TRUE; + break; + case GDK_BUTTON_RELEASE: + if (light_hit==TRUE) + draw_preview_image(TRUE); + else + { + pos.x=-(2.0*(gdouble)event->button.x/(gdouble)PREVIEW_WIDTH-1.0); + pos.y=2.0*(gdouble)event->button.y/(gdouble)PREVIEW_HEIGHT-1.0; + /*ArcBall_Mouse(pos); + ArcBall_EndDrag(); */ + } + left_button_pressed=FALSE; + break; + case GDK_MOTION_NOTIFY: + if (left_button_pressed==TRUE) + { + if (light_hit==TRUE) + { + update_light(event->motion.x,event->motion.y); + update_light_pos_entries(); + } + else + { + pos.x=-(2.0*(gdouble)event->motion.x/(gdouble)PREVIEW_WIDTH-1.0); + pos.y=2.0*(gdouble)event->motion.y/(gdouble)PREVIEW_HEIGHT-1.0; +/* ArcBall_Mouse(pos); + ArcBall_Update(); + ArcBall_Values(&a,&b,&c); + Alpha+=RadToDeg(-a); + Beta+RadToDeg(-b); + Gamma+=RadToDeg(-c); + if (Alpha>180) Alpha-=360; + if (Alpha<-180) Alpha+=360; + if (Beta>180) Beta-=360; + if (Beta<-180) Beta+=360; + if (Gamma>180) Gamma-=360; + if (Gamma<-180) Gamma+=360; + UpdateAngleSliders(); */ + } + } + break; + default: + break; + } + return(FALSE); +} + +/*******************************/ +/* Create general options page */ +/*******************************/ + +GtkWidget *create_options_page(void) +{ + GtkWidget *page,*frame,*vbox,*hbox,*label; + GtkWidget *toggletile,*toggleanti; + GtkWidget *toggletrans,*toggleimage,*toggletips; + GtkWidget *widget1,*widget2; + + page=gck_vbox_new(NULL,FALSE,FALSE,FALSE,0,0,0); + + frame=gck_frame_new("General options",page,GTK_SHADOW_ETCHED_IN,FALSE,FALSE,0,2); + vbox=gck_vbox_new(frame,FALSE,FALSE,FALSE,0,2,2); + + gck_auto_show(TRUE); + widget1=gck_option_menu_new("Map to:",vbox,TRUE,TRUE,0,map_labels, + (GtkSignalFunc)mapmenu_callback, NULL); + gck_auto_show(FALSE); + gtk_widget_show(vbox); + + gtk_option_menu_set_history(GTK_OPTION_MENU(widget1),mapvals.maptype); + gtk_tooltips_set_tip(tooltips,widget1,"Type of object to map to",NULL); + + vbox=gck_vbox_new(vbox,FALSE,FALSE,FALSE,0,0,0); + toggletrans=gck_checkbutton_new("Transparent background",vbox,mapvals.transparent_background, + (GtkSignalFunc)toggletrans_update); + toggletile=gck_checkbutton_new("Tile source image",vbox,mapvals.tiled, + (GtkSignalFunc)toggletile_update); + toggleimage=gck_checkbutton_new("Create new image",vbox,mapvals.create_new_image, + (GtkSignalFunc)toggle_update); + toggletips=gck_checkbutton_new("Enable tooltips",vbox,mapvals.tooltips_enabled, + (GtkSignalFunc)toggletips_update); + + gtk_tooltips_set_tip(tooltips,toggletrans,"Make image transparent outside object",NULL); + gtk_tooltips_set_tip(tooltips,toggletile,"Tile source image: useful for infinite planes",NULL); + gtk_tooltips_set_tip(tooltips,toggleimage,"Create a new image when applying filter",NULL); + gtk_tooltips_set_tip(tooltips,toggletips,"Enable/disable tooltip messages",NULL); + + gtk_object_set_data(GTK_OBJECT(toggletrans),"ValuePtr",(gpointer)&mapvals.transparent_background); + gtk_object_set_data(GTK_OBJECT(toggletile),"ValuePtr",(gpointer)&mapvals.tiled); + gtk_object_set_data(GTK_OBJECT(toggleimage),"ValuePtr",(gpointer)&mapvals.create_new_image); + gtk_object_set_data(GTK_OBJECT(toggletips),"ValuePtr", (gpointer)&mapvals.tooltips_enabled); + + gtk_widget_show(toggletrans); + gtk_widget_show(toggletile); + gtk_widget_show(toggleimage); + gtk_widget_show(toggletips); + gtk_widget_show(vbox); + gtk_widget_show(frame); + + frame=gck_frame_new("Antialiasing options",page,GTK_SHADOW_ETCHED_IN,FALSE,FALSE,0,2); + vbox=gck_vbox_new(frame,FALSE,FALSE,FALSE,0,2,2); + + toggleanti=gck_checkbutton_new("Enable antialiasing",vbox,mapvals.antialiasing, + (GtkSignalFunc)toggleanti_update); + gtk_object_set_data(GTK_OBJECT(toggleanti),"ValuePtr",(gpointer)&mapvals.antialiasing); + gtk_tooltips_set_tip(tooltips,toggleanti,"Enable/disable jagged edges removal (antialiasing)",NULL); + + hbox=gck_hbox_new(vbox,FALSE,TRUE,TRUE,0,0,0); + + gtk_widget_show(toggleanti); + gtk_widget_show(vbox); + gtk_widget_show(frame); + + vbox=gck_vbox_new(hbox,TRUE,FALSE,TRUE,0,0,0); + + frame=gck_frame_new(NULL,vbox,GTK_SHADOW_NONE,TRUE,TRUE,0,0); + label=gck_label_aligned_new("Depth:",frame,GCK_ALIGN_RIGHT,GCK_ALIGN_BOTTOM); + + gtk_widget_show(label); + gtk_widget_show(frame); + + frame=gck_frame_new(NULL,vbox,GTK_SHADOW_NONE,TRUE,TRUE,0,0); + label=gck_label_aligned_new("Treshold:",frame,GCK_ALIGN_RIGHT,GCK_ALIGN_CENTERED); + + gtk_widget_show(label); + gtk_widget_show(frame); + gtk_widget_show(vbox); + + vbox=gck_vbox_new(hbox,TRUE,FALSE,FALSE,5,0,0); + + widget1=gck_hscale_new(NULL,vbox,&sample_scale_vals,(GtkSignalFunc)scale_update); + widget2=gck_entryfield_new(NULL,vbox,mapvals.pixeltreshold,(GtkSignalFunc)entry_update); + gtk_object_set_data(GTK_OBJECT(widget1),"ValuePtr",(gpointer)&mapvals.maxdepth); + gtk_object_set_data(GTK_OBJECT(widget2),"ValuePtr",(gpointer)&mapvals.pixeltreshold); + + gtk_tooltips_set_tip(tooltips,widget1,"Antialiasing quality. Higher is better, but slower",NULL); + gtk_tooltips_set_tip(tooltips,widget2,"Stop when pixel differences are smaller than this value",NULL); + + gtk_widget_show(widget1); + gtk_widget_show(widget2); + gtk_widget_show(vbox); + gtk_widget_show(hbox); + + gtk_widget_show(page); + + return page; +} + +/******************************/ +/* Create light settings page */ +/******************************/ + +GtkWidget *create_light_page(void) +{ + GtkWidget *page,*frame,*vbox; + GtkWidget *widget1,*widget2,*widget3; + + page=gtk_vbox_new(FALSE,0); + + frame=gck_frame_new("Light settings",page,GTK_SHADOW_ETCHED_IN,FALSE,FALSE,0,5); + vbox=gck_vbox_new(frame,FALSE,TRUE,TRUE,5,0,5); + + gck_auto_show(TRUE); + widget1=gck_option_menu_new("Lightsource type:",vbox,TRUE,TRUE,0, + light_labels,(GtkSignalFunc)lightmenu_callback, NULL); + gtk_option_menu_set_history(GTK_OPTION_MENU(widget1),mapvals.lightsource.type); + gck_auto_show(FALSE); + + widget2=gck_pushbutton_new("Lightsource color",vbox,TRUE,FALSE,0, + (GtkSignalFunc)light_color_callback); + + gtk_widget_show(widget2); + gtk_widget_show(vbox); + gtk_widget_show(frame); + + gtk_tooltips_set_tip(tooltips,widget1,"Type of light source to apply",NULL); + gtk_tooltips_set_tip(tooltips,widget2,"Set light source color (white is default)",NULL); + + pointlightwid=gck_frame_new("Position",page,GTK_SHADOW_ETCHED_IN,FALSE,FALSE,0,5); + vbox=gck_vbox_new(pointlightwid,FALSE,FALSE,FALSE,5,0,5); + + xentry=gck_entryfield_new("X:",vbox,mapvals.lightsource.position.x,(GtkSignalFunc)entry_update); + yentry=gck_entryfield_new("Y:",vbox,mapvals.lightsource.position.y,(GtkSignalFunc)entry_update); + zentry=gck_entryfield_new("Z:",vbox,mapvals.lightsource.position.z,(GtkSignalFunc)entry_update); + + gtk_object_set_data(GTK_OBJECT(xentry),"ValuePtr",(gpointer)&mapvals.lightsource.position.x); + gtk_object_set_data(GTK_OBJECT(yentry),"ValuePtr",(gpointer)&mapvals.lightsource.position.y); + gtk_object_set_data(GTK_OBJECT(zentry),"ValuePtr",(gpointer)&mapvals.lightsource.position.z); + + gtk_tooltips_set_tip(tooltips,xentry,"Light source X position in XYZ space",NULL); + gtk_tooltips_set_tip(tooltips,yentry,"Light source Y position in XYZ space",NULL); + gtk_tooltips_set_tip(tooltips,zentry,"Light source Z position in XYZ space",NULL); + + gtk_widget_show(xentry); + gtk_widget_show(yentry); + gtk_widget_show(zentry); + gtk_widget_show(vbox); + gtk_widget_show(frame); + gtk_widget_show(pointlightwid); + + dirlightwid=gck_frame_new("Direction vector",page,GTK_SHADOW_ETCHED_IN,FALSE,FALSE,0,5); + vbox=gck_vbox_new(dirlightwid,FALSE,FALSE,FALSE,5,0,5); + + widget1=gck_entryfield_new("X:",vbox,mapvals.lightsource.direction.x,(GtkSignalFunc)entry_update); + widget2=gck_entryfield_new("Y:",vbox,mapvals.lightsource.direction.y,(GtkSignalFunc)entry_update); + widget3=gck_entryfield_new("Z:",vbox,mapvals.lightsource.direction.z,(GtkSignalFunc)entry_update); + + gtk_tooltips_set_tip(tooltips,widget1,"Light source X direction in XYZ space",NULL); + gtk_tooltips_set_tip(tooltips,widget2,"Light source Y direction in XYZ space",NULL); + gtk_tooltips_set_tip(tooltips,widget3,"Light source Z direction in XYZ space",NULL); + + gtk_object_set_data(GTK_OBJECT(widget1),"ValuePtr",(gpointer)&mapvals.lightsource.direction.x); + gtk_object_set_data(GTK_OBJECT(widget2),"ValuePtr",(gpointer)&mapvals.lightsource.direction.y); + gtk_object_set_data(GTK_OBJECT(widget3),"ValuePtr",(gpointer)&mapvals.lightsource.direction.z); + + gtk_widget_show(widget1); + gtk_widget_show(widget2); + gtk_widget_show(widget3); + gtk_widget_show(vbox); + + gtk_widget_show(page); + + return page; +} + +/*********************************/ +/* Create material settings page */ +/*********************************/ + +GtkWidget *create_material_page(void) +{ + GtkWidget *page,*frame,*table; + GtkWidget *label1,*label2,*label3; + GtkWidget *widget1,*widget2,*widget3; + GdkPixmap *image; + GdkBitmap *mask; + GtkStyle *style; + GtkWidget *pixmap; + + page=gck_vbox_new(NULL,FALSE,FALSE,FALSE,0,0,0); + + frame=gck_frame_new("Intensity levels",page,GTK_SHADOW_ETCHED_IN,FALSE,FALSE,0,5); + + table=gtk_table_new(2,4,FALSE); + gtk_container_add(GTK_CONTAINER(frame),table); + + label1=gck_label_aligned_new("Ambient:",NULL,GCK_ALIGN_RIGHT,GCK_ALIGN_CENTERED); + label2=gck_label_aligned_new("Diffuse:",NULL,GCK_ALIGN_RIGHT,GCK_ALIGN_CENTERED); + + gtk_table_attach(GTK_TABLE(table),label1,0,1,0,1, 0,0,0,0); + gtk_table_attach(GTK_TABLE(table),label2,0,1,1,2, 0,0,0,0); + + widget1=gck_entryfield_new(NULL,NULL,mapvals.material.ambient_int,(GtkSignalFunc)entry_update); + widget2=gck_entryfield_new(NULL,NULL,mapvals.material.diffuse_int,(GtkSignalFunc)entry_update); + + gtk_table_attach(GTK_TABLE(table),widget1,2,3,0,1, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_table_attach(GTK_TABLE(table),widget2,2,3,1,2, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + + style=gtk_widget_get_style(table); + + image=gdk_pixmap_create_from_xpm_d(appwin->widget->window,&mask,&style->bg[GTK_STATE_NORMAL],amb1_xpm); + pixmap=gtk_pixmap_new(image,mask); + gtk_table_attach(GTK_TABLE(table),pixmap,1,2,0,1, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_widget_show(pixmap); + + image=gdk_pixmap_create_from_xpm_d(appwin->widget->window,&mask,&style->bg[GTK_STATE_NORMAL],amb2_xpm); + pixmap=gtk_pixmap_new(image,mask); + gtk_table_attach(GTK_TABLE(table),pixmap,3,4,0,1, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_widget_show(pixmap); + + image=gdk_pixmap_create_from_xpm_d(appwin->widget->window,&mask,&style->bg[GTK_STATE_NORMAL],diffint1_xpm); + pixmap=gtk_pixmap_new(image,mask); + gtk_table_attach(GTK_TABLE(table),pixmap,1,2,1,2, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_widget_show(pixmap); + + image=gdk_pixmap_create_from_xpm_d(appwin->widget->window,&mask,&style->bg[GTK_STATE_NORMAL],diffint2_xpm); + pixmap=gtk_pixmap_new(image,mask); + gtk_table_attach(GTK_TABLE(table),pixmap,3,4,1,2, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_widget_show(pixmap); + + gtk_widget_show(label1); + gtk_widget_show(label2); + gtk_widget_show(widget1); + gtk_widget_show(widget2); + gtk_widget_show(table); + gtk_widget_show(frame); + + gtk_tooltips_set_tip(tooltips,widget1,"Amount of original color to show where no direct light falls",NULL); + gtk_tooltips_set_tip(tooltips,widget2,"Intensity of original color when lit by a light source",NULL); + + gtk_object_set_data(GTK_OBJECT(widget1),"ValuePtr",(gpointer)&mapvals.material.ambient_int); + gtk_object_set_data(GTK_OBJECT(widget2),"ValuePtr",(gpointer)&mapvals.material.diffuse_int); + + frame=gck_frame_new("Reflectivity",page,GTK_SHADOW_ETCHED_IN,FALSE,FALSE,0,5); + + table=gtk_table_new(3,4,FALSE); + gtk_container_add(GTK_CONTAINER(frame),table); + + label1=gck_label_aligned_new("Diffuse:",NULL,GCK_ALIGN_RIGHT,GCK_ALIGN_CENTERED); + label2=gck_label_aligned_new("Specular:",NULL,GCK_ALIGN_RIGHT,GCK_ALIGN_CENTERED); + label3=gck_label_aligned_new("Hightlight:",NULL,GCK_ALIGN_RIGHT,GCK_ALIGN_CENTERED); + + gtk_table_attach(GTK_TABLE(table),label1,0,1,0,1, 0,0,0,0); + gtk_table_attach(GTK_TABLE(table),label2,0,1,1,2, 0,0,0,0); + gtk_table_attach(GTK_TABLE(table),label3,0,1,2,3, 0,0,0,0); + + widget1=gck_entryfield_new(NULL,NULL,mapvals.material.diffuse_ref,(GtkSignalFunc)entry_update); + widget2=gck_entryfield_new(NULL,NULL,mapvals.material.specular_ref,(GtkSignalFunc)entry_update); + widget3=gck_entryfield_new(NULL,NULL,mapvals.material.highlight,(GtkSignalFunc)entry_update); + + gtk_table_attach(GTK_TABLE(table),widget1,2,3,0,1, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_table_attach(GTK_TABLE(table),widget2,2,3,1,2, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_table_attach(GTK_TABLE(table),widget3,2,3,2,3, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + + gtk_tooltips_set_tip(tooltips,widget1,"Higher values makes the object reflect more light (appear lighter)",NULL); + gtk_tooltips_set_tip(tooltips,widget2,"Controls how intense the highlights will be",NULL); + gtk_tooltips_set_tip(tooltips,widget3,"Higher values makes the highlights more focused",NULL); + + gtk_object_set_data(GTK_OBJECT(widget1),"ValuePtr",(gpointer)&mapvals.material.diffuse_ref); + gtk_object_set_data(GTK_OBJECT(widget2),"ValuePtr",(gpointer)&mapvals.material.specular_ref); + gtk_object_set_data(GTK_OBJECT(widget3),"ValuePtr",(gpointer)&mapvals.material.highlight); + + style=gtk_widget_get_style(table); + + image=gdk_pixmap_create_from_xpm_d(appwin->widget->window,&mask,&style->bg[GTK_STATE_NORMAL],diffref1_xpm); + pixmap=gtk_pixmap_new(image,mask); + gtk_table_attach(GTK_TABLE(table),pixmap,1,2,0,1, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_widget_show(pixmap); + + image=gdk_pixmap_create_from_xpm_d(appwin->widget->window,&mask,&style->bg[GTK_STATE_NORMAL],diffref2_xpm); + pixmap=gtk_pixmap_new(image,mask); + gtk_table_attach(GTK_TABLE(table),pixmap,3,4,0,1, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_widget_show(pixmap); + + image=gdk_pixmap_create_from_xpm_d(appwin->widget->window,&mask,&style->bg[GTK_STATE_NORMAL],specref1_xpm); + pixmap=gtk_pixmap_new(image,mask); + gtk_table_attach(GTK_TABLE(table),pixmap,1,2,1,2, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_widget_show(pixmap); + + image=gdk_pixmap_create_from_xpm_d(appwin->widget->window,&mask,&style->bg[GTK_STATE_NORMAL],specref2_xpm); + pixmap=gtk_pixmap_new(image,mask); + gtk_table_attach(GTK_TABLE(table),pixmap,3,4,1,2, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_widget_show(pixmap); + + image=gdk_pixmap_create_from_xpm_d(appwin->widget->window,&mask,&style->bg[GTK_STATE_NORMAL],high1_xpm); + pixmap=gtk_pixmap_new(image,mask); + gtk_table_attach(GTK_TABLE(table),pixmap,1,2,2,3, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_widget_show(pixmap); + + image=gdk_pixmap_create_from_xpm_d(appwin->widget->window,&mask,&style->bg[GTK_STATE_NORMAL],high2_xpm); + pixmap=gtk_pixmap_new(image,mask); + gtk_table_attach(GTK_TABLE(table),pixmap,3,4,2,3, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_widget_show(pixmap); + + gtk_widget_show(label1); + gtk_widget_show(label2); + gtk_widget_show(label3); + gtk_widget_show(widget1); + gtk_widget_show(widget2); + gtk_widget_show(widget3); + gtk_widget_show(table); + gtk_widget_show(frame); + + gtk_widget_show(page); + + return page; +} + +/****************************************/ +/* Create orientation and position page */ +/****************************************/ + +GtkWidget *create_orientation_page(void) +{ + GtkWidget *page,*frame,*vbox,*label,*table; + GtkWidget *widget1,*widget2,*widget3; + + page=gck_vbox_new(NULL,FALSE,FALSE,FALSE,0,0,0); + + frame=gck_frame_new("Position and orientation",page,GTK_SHADOW_ETCHED_IN,TRUE,TRUE,0,5); + vbox=gck_vbox_new(frame,FALSE,FALSE,FALSE,0,0,5); + + widget1=gck_entryfield_new("X pos.:",vbox,mapvals.position.x,(GtkSignalFunc)xyzval_update); + widget2=gck_entryfield_new("Y pos.:",vbox,mapvals.position.y,(GtkSignalFunc)xyzval_update); + widget3=gck_entryfield_new("Z pos.:",vbox,mapvals.position.z,(GtkSignalFunc)xyzval_update); + + gtk_tooltips_set_tip(tooltips,widget1,"Object X position in XYZ space (0.5 is center)",NULL); + gtk_tooltips_set_tip(tooltips,widget2,"Object Y position in XYZ space (0.5 is center)",NULL); + gtk_tooltips_set_tip(tooltips,widget3,"Object Z position in XYZ space (0.5 is center)",NULL); + + gtk_object_set_data(GTK_OBJECT(widget1),"ValuePtr",(gpointer)&mapvals.position.x); + gtk_object_set_data(GTK_OBJECT(widget2),"ValuePtr",(gpointer)&mapvals.position.y); + gtk_object_set_data(GTK_OBJECT(widget3),"ValuePtr",(gpointer)&mapvals.position.z); + + gtk_widget_show(widget1); + gtk_widget_show(widget2); + gtk_widget_show(widget3); + + table = gtk_table_new(3,2,FALSE); + gtk_box_pack_start(GTK_BOX(vbox),table,TRUE,TRUE,5); + + label=gck_label_aligned_new("XY:",NULL,GCK_ALIGN_RIGHT,0.7); + gtk_table_attach(GTK_TABLE(table),label,0,1,0,1, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_widget_show(label); + + label=gck_label_aligned_new("YZ:",NULL,GCK_ALIGN_RIGHT,0.7); + gtk_table_attach(GTK_TABLE(table),label,0,1,1,2, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_widget_show(label); + + label=gck_label_aligned_new("XZ:",NULL,GCK_ALIGN_RIGHT,0.7); + gtk_table_attach(GTK_TABLE(table),label,0,1,2,3, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_widget_show(label); + + angle_scale_vals.value = mapvals.alpha; + widget1=gck_hscale_new(NULL,NULL,&angle_scale_vals,(GtkSignalFunc)angle_update); + angle_scale_vals.value = mapvals.beta; + widget2=gck_hscale_new(NULL,NULL,&angle_scale_vals,(GtkSignalFunc)angle_update); + angle_scale_vals.value = mapvals.gamma; + widget3=gck_hscale_new(NULL,NULL,&angle_scale_vals,(GtkSignalFunc)angle_update); + + gtk_table_attach(GTK_TABLE(table),widget1,1,2,0,1, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_table_attach(GTK_TABLE(table),widget2,1,2,1,2, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + gtk_table_attach(GTK_TABLE(table),widget3,1,2,2,3, GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL, 0,0); + + gtk_widget_show(widget1); + gtk_widget_show(widget2); + gtk_widget_show(widget3); + gtk_widget_show(table); + gtk_widget_show(vbox); + gtk_widget_show(frame); + + gtk_tooltips_set_tip(tooltips,widget1,"XY axis rotation angle",NULL); + gtk_tooltips_set_tip(tooltips,widget2,"YZ axis rotation angle",NULL); + gtk_tooltips_set_tip(tooltips,widget3,"XZ axis rotation angle",NULL); + + gtk_object_set_data(GTK_OBJECT(widget1),"ValuePtr",(gpointer)&mapvals.alpha); + gtk_object_set_data(GTK_OBJECT(widget2),"ValuePtr",(gpointer)&mapvals.beta); + gtk_object_set_data(GTK_OBJECT(widget3),"ValuePtr",(gpointer)&mapvals.gamma); + + gtk_widget_show(page); + + return page; +} + +/****************************/ +/* Create notbook and pages */ +/****************************/ + +void create_main_notebook(GtkWidget *container) +{ + GtkWidget *page,*label; + + gck_auto_show(FALSE); + + options_note_book=GTK_NOTEBOOK(gtk_notebook_new()); + gtk_container_add(GTK_CONTAINER(container),GTK_WIDGET(options_note_book)); + + page = create_options_page(); + label=gtk_label_new("Options"); + gtk_widget_show(label); + + gtk_notebook_append_page(options_note_book,page,label); + + page = create_light_page(); + label=gtk_label_new("Light"); + gtk_widget_show(label); + + gtk_notebook_append_page(options_note_book,page,label); + + page = create_material_page(); + label=gtk_label_new("Material"); + gtk_widget_show(label); + + gtk_notebook_append_page(options_note_book,page,label); + + page = create_orientation_page(); + label=gtk_label_new("Orientation"); + gtk_widget_show(label); + + gtk_notebook_append_page(options_note_book,page,label); + + gtk_widget_show(GTK_WIDGET(options_note_book)); + + gck_auto_show(TRUE); +} + +/*****************************************************/ +/* Create and show main dialog. Uses the plugin_ui.c */ +/* routines when possible, gtk itself when not. */ +/*****************************************************/ + +void create_main_dialog(void) +{ + GtkWidget *main_vbox,*main_workbox,*actionbox,*workbox1,*workbox1b,*workbox2,*vbox; + GtkWidget *frame,*applybutton,*cancelbutton,*helpbutton,*hbox,*gridtoggle; + GtkWidget *wid; + + appwin = gck_application_window_new("Map to object"); + gtk_widget_realize(appwin->widget); + + tooltips=gtk_tooltips_new(); + + /* Main manager widget */ + /* =================== */ + + main_vbox=gck_vbox_new(appwin->widget,FALSE,FALSE,FALSE,8,0,0); + + /* Work area manager widget */ + /* ======================== */ + + main_workbox=gck_hbox_new(main_vbox,FALSE,FALSE,FALSE,5,0,5); + + /* Action area manager widget */ + /* ========================== */ + + gck_hseparator_new(main_vbox); + actionbox=gck_hbox_new(main_vbox,TRUE,TRUE,TRUE,5,0,5); + + /* Add Ok, Cancel and Help buttons to the action area */ + /* ================================================== */ + + applybutton=gck_pushbutton_new("Apply",actionbox,FALSE,TRUE,5,(GtkSignalFunc)apply_callback); + cancelbutton=gck_pushbutton_new("Cancel",actionbox,FALSE,TRUE,5,(GtkSignalFunc)exit_callback); + helpbutton=gck_pushbutton_new("Help",actionbox,FALSE,TRUE,5,NULL); + + GTK_WIDGET_SET_FLAGS (applybutton, GTK_CAN_DEFAULT); + GTK_WIDGET_SET_FLAGS (cancelbutton, GTK_CAN_DEFAULT); + GTK_WIDGET_SET_FLAGS (helpbutton, GTK_CAN_DEFAULT); + + gtk_widget_grab_default (applybutton); + gtk_widget_set_sensitive(helpbutton,FALSE); + + gtk_tooltips_set_tip(tooltips,applybutton,"Apply filter with current settings",NULL); + gtk_tooltips_set_tip(tooltips,cancelbutton,"Close filter without doing anything",NULL); + + /* Split the workarea in two */ + /* ========================= */ + + frame=gck_frame_new(NULL,main_workbox,GTK_SHADOW_ETCHED_IN,TRUE,TRUE,0,0); + workbox1=gck_vbox_new(frame,FALSE,TRUE,TRUE,5,0,5); + workbox2=gck_vbox_new(main_workbox,FALSE,FALSE,FALSE,0,0,0); + + /* Add preview widget and various buttons to the first part */ + /* ======================================================== */ + + frame=gck_frame_new(NULL,workbox1,GTK_SHADOW_IN,FALSE,FALSE,0,0); + previewarea = gck_drawing_area_new(frame, PREVIEW_WIDTH, PREVIEW_HEIGHT, + GDK_EXPOSURE_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK, (GtkSignalFunc)preview_events); + + workbox1b=gck_vbox_new(workbox1,TRUE,TRUE,TRUE,0,0,0); + hbox=gck_hbox_new(workbox1b,FALSE,TRUE,TRUE,5,0,0); + wid=gck_pushbutton_new("Preview!",hbox,TRUE,TRUE,0,(GtkSignalFunc)preview_callback); + gtk_tooltips_set_tip(tooltips,wid,"Recompute preview image",NULL); + + hbox=gck_hbox_new(hbox,FALSE,TRUE,TRUE,0,0,0); + wid=gck_pushbutton_new("+",hbox,TRUE,TRUE,0,(GtkSignalFunc)zoomin_callback); + gtk_tooltips_set_tip(tooltips,wid,"Zoom in (make image bigger)",NULL); + wid=gck_pushbutton_new("-",hbox,TRUE,TRUE,0,(GtkSignalFunc)zoomout_callback); + gtk_tooltips_set_tip(tooltips,wid,"Zoom out (make image smaller)",NULL); + + vbox = gck_vbox_new(workbox1b, FALSE, FALSE, FALSE, 0, 0, 5); + gridtoggle=gck_checkbutton_new("Show preview wireframe",vbox,mapvals.showgrid, + (GtkSignalFunc)togglegrid_update); + gtk_object_set_data(GTK_OBJECT(gridtoggle),"ValuePtr",&mapvals.showgrid); + gtk_tooltips_set_tip(tooltips,gridtoggle,"Show/hide preview wireframe",NULL); + + create_main_notebook(workbox2); + + /* Endmarkers for line table */ + /* ========================= */ + + linetab[0].x1=-1; + + /* Phew :) Now lets check out the result of this mess */ + /* ================================================== */ + + gtk_widget_show(appwin->widget); + + gck_cursor_set(previewarea->window,GDK_HAND2); + gtk_tooltips_set_colors(tooltips, + gck_rgb_to_gdkcolor(appwin->visinfo,255,255,220), + gck_rgb_to_gdkcolor(appwin->visinfo,0,0,0)); + + if (mapvals.tooltips_enabled==FALSE) + gtk_tooltips_disable(tooltips); +} diff --git a/plug-ins/MapObject/mapobject_ui.h b/plug-ins/MapObject/mapobject_ui.h new file mode 100644 index 0000000000..cf6167dcf1 --- /dev/null +++ b/plug-ins/MapObject/mapobject_ui.h @@ -0,0 +1,30 @@ +#ifndef MAPOBJECTUIH +#define MAPOBJECTUIH + +#include +#include +#include +#include +#include +#include + +#include "arcball.h" +#include "mapobject_main.h" +#include "mapobject_image.h" +#include "mapobject_apply.h" +#include "mapobject_preview.h" + +/* Externally visible variables */ +/* ============================ */ + +extern GckApplicationWindow *appwin; + +extern GdkGC *gc; +extern GtkWidget *previewarea; + +/* Externally visible functions */ +/* ============================ */ + +extern void create_main_dialog(void); + +#endif diff --git a/plug-ins/MapObject/specref1.xpm b/plug-ins/MapObject/specref1.xpm new file mode 100644 index 0000000000..fea662e764 --- /dev/null +++ b/plug-ins/MapObject/specref1.xpm @@ -0,0 +1,75 @@ +/* XPM */ +char * specref1_xpm[] = { +"32 32 40 1", +" c None", +". c #A699A699A699", +"X c #A699A289A699", +"o c #965896589658", +"O c #BEFBBEFBBEFB", +"+ c #CF3CCB2BCF3C", +"@ c #C71BC71BC71B", +"# c #C71BC30BC71B", +"$ c #B6DAB6DAB6DA", +"% c #8E388E388E38", +"& c #69A669A669A6", +"* c #D75CD75CD75C", +"= c #DF7DDB6CDF7D", +"- c #CF3CCF3CCF3C", +"; c #965892489658", +": c #DF7DDF7DDF7D", +"> c #E79DE38DE79D", +", c #D75CD34CD75C", +"< c #AEBAAEBAAEBA", +"1 c #9E799E799E79", +"2 c #861786178617", +"3 c #596559655965", +"4 c #E79DE79DE79D", +"5 c #B6DAB2CAB6DA", +"6 c #71C671C671C6", +"7 c #492449244924", +"8 c #71C675D671C6", +"9 c #514455555144", +"0 c #BEFBBAEABEFB", +"q c #AEBAAAAAAEBA", +"w c #9E799A699E79", +"e c #8E388A288E38", +"r c #49244D344924", +"t c #861782078617", +"y c #69A66DB669A6", +"u c #79E779E779E7", +"i c #618565956185", +"p c #514451445144", +"a c #618561856185", +"s c #410345144103", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" .Xo ", +" .O+@#$.%& ", +" $*==*-#$.;& ", +" $=:>:=,+O<123 ", +" .*:>4>=*+O5X%67 ", +" O=>4>>=,+O5X%89 ", +" +=:>>:*-@0<1%83 ", +" .@*===*,+#$qwe83r ", +" X#-,*,-+#0 c #E79DE38DE79D", +", c #D75CD34CD75C", +"< c #AEBAAEBAAEBA", +"1 c #9E799E799E79", +"2 c #861786178617", +"3 c #596559655965", +"4 c #E79DE79DE79D", +"5 c #EFBEEFBEEFBE", +"6 c #B6DAB2CAB6DA", +"7 c #71C671C671C6", +"8 c #492449244924", +"9 c #FFFFFBEEFFFF", +"0 c #FFFFFFFFFFFF", +"q c #71C675D671C6", +"w c #514455555144", +"e c #EFBEEBADEFBE", +"r c #BEFBBAEABEFB", +"t c #AEBAAAAAAEBA", +"y c #9E799A699E79", +"u c #8E388A288E38", +"i c #49244D344924", +"p c #861782078617", +"a c #69A66DB669A6", +"s c #79E779E779E7", +"d c #618565956185", +"f c #514451445144", +"g c #618561856185", +"h c #410345144103", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" .Xo ", +" .O+@#$.%& ", +" $*==*-#$.;& ", +" $=:>:=,+O<123 ", +" .*:4454*+O6X%78 ", +" O=>4900>+O6X%qw ", +" +=:5000e+r<1%q3 ", +" .@*=4009=#$tyuq3i ", +" X#-,*>e=@r