Initial checkin of Pika from heckimp

This commit is contained in:
2023-09-25 15:35:21 -07:00
commit 891e999216
6761 changed files with 5240685 additions and 0 deletions

View File

@ -0,0 +1,22 @@
Changes (post 0.3.1):
=====================
-> 0.3.1 Merged MapPlane and MapSphere. Added support for non-interactive
execution (for script-fu).
-> 0.3.2 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.4.0 Some source/algorithm cleanups, fixed gtk+ object refcounting bugs. Some
changes to compile with gtk+ 0.99.4.
-> 1.0.0 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.
-> 1.1.0 Added box object and changed PDB interface accordingly; this will unfortunately
break old scripts. The transparency code should be a little saner now.
-> 1.2.0 Added cylinder object. Fixed a few things, thanks to Yosh <yosh@gimp.org> and
Pedro <pkaempf@master.echo.ch> for pointing them out to me.

View File

@ -0,0 +1,61 @@
MapObject 1.2.0 -- image filter plug-in for PIKA
===========================================================
Copyright (C) 1996-98 Tom Bech
Copyright (C) 1996-98 Federico Mena Quintero
Released 16th of July, 1998
You can reach the author(s) via E-mail:
tomb@gimp.org (Tom) or quartic@gimp.org (Federico).
PIKA was developed by Peter Mattis and Spencer Kimball.
You can contact them at pika@xcf.berkeley.edu.
There's more PIKA stuff on our home pages:
http://www.ii.uib.no/~tomb/pika.html (Tom's page)
http://www.nuclecu.unam.mx/~federico/pika/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 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
In other words, you can't sue us for whatever happens while using this ;)
Compiling
=========
To compile you'll need PIKA 1.0 and GTK+ 1.0.4 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 "MapObject"
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

18
plug-ins/map-object/TODO Normal file
View File

@ -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?
* 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

View File

@ -0,0 +1,515 @@
/************************************/
/* ArcBall.c (c) Ken Shoemake, 1993 */
/* Modified by Tom Bech, 1996 */
/************************************/
#include "config.h"
#include <libpika/pika.h>
#include "arcball.h"
/* Global variables */
/* ================ */
Quat qOne = { 0, 0, 0, 1 };
static HVect center;
static double radius;
static Quat qNow, qDown, qDrag;
static HVect vNow, vDown, vFrom, vTo, vrFrom, vrTo;
static HMatrix mNow, mDown;
static unsigned int showResult, dragging;
static ConstraintSet sets[NSets];
static int setSizes[NSets];
static AxisSet axisSet;
static int axisIndex;
static HMatrix mId =
{
{ 1, 0, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 1 }
};
static double otherAxis[][4] =
{
{-0.48, 0.80, 0.36, 1}
};
/* Internal methods */
/* ================ */
static void Qt_ToMatrix(Quat q,HMatrix out);
static Quat Qt_Conj(Quat q);
static Quat Qt_Mul(Quat qL, Quat qR);
static Quat Qt_FromBallPoints(HVect from, HVect to);
static void Qt_ToBallPoints(Quat q, HVect *arcFrom, HVect *arcTo);
static HVect V3_(double x, double y, double z);
static double V3_Norm(HVect v);
static HVect V3_Unit(HVect v);
static HVect V3_Scale(HVect v, double s);
static HVect V3_Negate(HVect v);
/*
static HVect V3_Add(HVect v1, HVect v2);
*/
static HVect V3_Sub(HVect v1, HVect v2);
static double V3_Dot(HVect v1, HVect v2);
/*
static HVect V3_Cross(HVect v1, HVect v2);
static HVect V3_Bisect(HVect v0, HVect v1);
*/
static HVect MouseOnSphere(HVect mouse, HVect ballCenter, double ballRadius);
static HVect ConstrainToAxis(HVect loose, HVect axis);
static 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. */
/* ============================================================= */
static 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. */
/* ============================================================== */
static void
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 conjugate of quaternion. */
/* =============================== */
static 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 */
/* ==================================== */
static 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 */
/* ========================================================= */
static 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 */
/* ============================================== */
static 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 */
/* =============================== */
static 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 */
/* ==================== */
static 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 */
/* ======================= */
/*
static 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 */
/* ================================ */
static 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. */
/* ========================================= */
/*
static 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 */
/* =============================== */
static 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 */
/* ============================= */
/*
static 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. */
/* ================================================= */
static 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 */
/* ========================================================== */
static 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 */
/* ====================================================== */
static 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. */
/* =============================================== */
static 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. */
/* ========================================== */
static 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; i<nAxes; i++)
{
onPlane = ConstrainToAxis(loose, axes[i]);
dot = V3_Dot(onPlane, loose);
if (dot>max)
{
max = dot; nearest = i;
}
}
return (nearest);
}

View File

@ -0,0 +1,50 @@
#ifndef __ARCBALL_H__
#define __ARCBALL_H__
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;
void ArcBall_Init (void);
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);
#endif /* __ARCBALL_H__ */

View File

@ -0,0 +1,328 @@
/******************************************************/
/* Apply mapping and shading on the whole input image */
/******************************************************/
#include "config.h"
#include <string.h>
#include <gtk/gtk.h>
#include <libpika/pika.h>
#include <libpika/pikaui.h>
#include "map-object-main.h"
#include "map-object-image.h"
#include "map-object-shade.h"
#include "map-object-apply.h"
#include "libpika/stdplugins-intl.h"
/*************/
/* Main loop */
/*************/
gdouble imat[4][4];
gfloat rotmat[16];
static gfloat a[16], b[16];
void
init_compute (void)
{
gint i;
switch (mapvals.maptype)
{
case MAP_SPHERE:
/* Rotate the equator/northpole axis */
/* ================================= */
pika_vector3_set (&mapvals.firstaxis, 0.0, 0.0, -1.0);
pika_vector3_set (&mapvals.secondaxis, 0.0, 1.0, 0.0);
pika_vector3_rotate (&mapvals.firstaxis,
pika_deg_to_rad (mapvals.alpha),
pika_deg_to_rad (mapvals.beta),
pika_deg_to_rad (mapvals.gamma));
pika_vector3_rotate (&mapvals.secondaxis,
pika_deg_to_rad (mapvals.alpha),
pika_deg_to_rad (mapvals.beta),
pika_deg_to_rad (mapvals.gamma));
/* Compute the 2D bounding box of the sphere spanned by the axis */
/* ============================================================= */
compute_bounding_box ();
get_ray_color = get_ray_color_sphere;
break;
case MAP_PLANE:
/* Rotate the plane axis */
/* ===================== */
pika_vector3_set (&mapvals.firstaxis, 1.0, 0.0, 0.0);
pika_vector3_set (&mapvals.secondaxis, 0.0, 1.0, 0.0);
pika_vector3_set (&mapvals.normal, 0.0, 0.0, 1.0);
pika_vector3_rotate (&mapvals.firstaxis,
pika_deg_to_rad (mapvals.alpha),
pika_deg_to_rad (mapvals.beta),
pika_deg_to_rad (mapvals.gamma));
pika_vector3_rotate (&mapvals.secondaxis,
pika_deg_to_rad (mapvals.alpha),
pika_deg_to_rad (mapvals.beta),
pika_deg_to_rad (mapvals.gamma));
mapvals.normal = pika_vector3_cross_product (&mapvals.firstaxis,
&mapvals.secondaxis);
if (mapvals.normal.z < 0.0)
pika_vector3_mul (&mapvals.normal, -1.0);
/* Initialize intersection matrix */
/* ============================== */
imat[0][1] = -mapvals.firstaxis.x;
imat[1][1] = -mapvals.firstaxis.y;
imat[2][1] = -mapvals.firstaxis.z;
imat[0][2] = -mapvals.secondaxis.x;
imat[1][2] = -mapvals.secondaxis.y;
imat[2][2] = -mapvals.secondaxis.z;
imat[0][3] = mapvals.position.x - mapvals.viewpoint.x;
imat[1][3] = mapvals.position.y - mapvals.viewpoint.y;
imat[2][3] = mapvals.position.z - mapvals.viewpoint.z;
get_ray_color = get_ray_color_plane;
break;
case MAP_BOX:
get_ray_color = get_ray_color_box;
pika_vector3_set (&mapvals.firstaxis, 1.0, 0.0, 0.0);
pika_vector3_set (&mapvals.secondaxis, 0.0, 1.0, 0.0);
pika_vector3_set (&mapvals.normal, 0.0, 0.0, 1.0);
ident_mat (rotmat);
rotatemat (mapvals.alpha, &mapvals.firstaxis, a);
matmul (a, rotmat, b);
memcpy (rotmat, b, sizeof (gfloat) * 16);
rotatemat (mapvals.beta, &mapvals.secondaxis, a);
matmul (a, rotmat, b);
memcpy (rotmat, b, sizeof (gfloat) * 16);
rotatemat (mapvals.gamma, &mapvals.normal, a);
matmul (a, rotmat, b);
memcpy (rotmat, b, sizeof (gfloat) * 16);
/* Set up pixel regions for the box face images */
/* ============================================ */
for (i = 0; i < 6; i++)
{
box_drawables[i] = pika_drawable_get_by_id (mapvals.boxmap_id[i]);
box_buffers[i] = pika_drawable_get_buffer (box_drawables[i]);
}
break;
case MAP_CYLINDER:
get_ray_color = get_ray_color_cylinder;
pika_vector3_set (&mapvals.firstaxis, 1.0, 0.0, 0.0);
pika_vector3_set (&mapvals.secondaxis, 0.0, 1.0, 0.0);
pika_vector3_set (&mapvals.normal, 0.0, 0.0, 1.0);
ident_mat (rotmat);
rotatemat (mapvals.alpha, &mapvals.firstaxis, a);
matmul (a, rotmat, b);
memcpy (rotmat, b, sizeof (gfloat) * 16);
rotatemat (mapvals.beta, &mapvals.secondaxis, a);
matmul (a, rotmat, b);
memcpy (rotmat, b, sizeof (gfloat) * 16);
rotatemat (mapvals.gamma, &mapvals.normal, a);
matmul (a, rotmat, b);
memcpy (rotmat, b, sizeof (gfloat) * 16);
/* Set up pixel regions for the cylinder cap images */
/* ================================================ */
for (i = 0; i < 2; i++)
{
cylinder_drawables[i] = pika_drawable_get_by_id (mapvals.cylindermap_id[i]);;
cylinder_buffers[i] = pika_drawable_get_buffer (cylinder_drawables[i]);
}
break;
}
max_depth = (gint) mapvals.maxdepth;
}
static void
render (gdouble x,
gdouble y,
PikaRGB *col,
gpointer data)
{
PikaVector3 pos;
pos.x = x / (gdouble) width;
pos.y = y / (gdouble) height;
pos.z = 0.0;
*col = get_ray_color (&pos);
}
static void
show_progress (gint min,
gint max,
gint curr,
gpointer data)
{
pika_progress_update ((gdouble) curr / (gdouble) max);
}
/**************************************************/
/* Performs map-to-sphere on the whole input image */
/* and updates or creates a new PIKA image. */
/**************************************************/
void
compute_image (void)
{
gint xcount, ycount;
PikaRGB color;
glong progress_counter = 0;
PikaVector3 p;
PikaImage *new_image = NULL;
PikaLayer *new_layer = NULL;
gboolean insert_layer = FALSE;
init_compute ();
if (mapvals.create_new_image)
{
new_image = pika_image_new (width, height, PIKA_RGB);
}
else
{
new_image = image;
}
pika_image_undo_group_start (new_image);
if (mapvals.create_new_image ||
mapvals.create_new_layer ||
(mapvals.transparent_background &&
! pika_drawable_has_alpha (output_drawable)))
{
gchar *layername[] = {_("Map to plane"),
_("Map to sphere"),
_("Map to box"),
_("Map to cylinder"),
_("Background")};
new_layer = pika_layer_new (new_image,
layername[mapvals.create_new_image ? 4 :
mapvals.maptype],
width, height,
mapvals.transparent_background ?
PIKA_RGBA_IMAGE :
PIKA_RGB_IMAGE,
100.0,
pika_image_get_default_new_layer_mode (new_image));
insert_layer = TRUE;
output_drawable = PIKA_DRAWABLE (new_layer);
}
dest_buffer = pika_drawable_get_shadow_buffer (output_drawable);
switch (mapvals.maptype)
{
case MAP_PLANE:
pika_progress_init (_("Map to plane"));
break;
case MAP_SPHERE:
pika_progress_init (_("Map to sphere"));
break;
case MAP_BOX:
pika_progress_init (_("Map to box"));
break;
case MAP_CYLINDER:
pika_progress_init (_("Map to cylinder"));
break;
}
if (! mapvals.antialiasing)
{
for (ycount = 0; ycount < height; ycount++)
{
for (xcount = 0; xcount < width; xcount++)
{
p = int_to_pos (xcount, ycount);
color = (* get_ray_color) (&p);
poke (xcount, ycount, &color, NULL);
progress_counter++;
}
pika_progress_update ((gdouble) progress_counter /
(gdouble) maxcounter);
}
}
else
{
pika_adaptive_supersample_area (0, 0,
width - 1, height - 1,
max_depth,
mapvals.pixelthreshold,
render,
NULL,
poke,
NULL,
show_progress,
NULL);
}
pika_progress_update (1.0);
g_object_unref (source_buffer);
g_object_unref (dest_buffer);
if (insert_layer)
pika_image_insert_layer (new_image, new_layer, NULL, 0);
pika_drawable_merge_shadow (output_drawable, TRUE);
pika_drawable_update (output_drawable, 0, 0, width, height);
if (new_image != image)
{
pika_display_new (new_image);
pika_displays_flush ();
}
pika_image_undo_group_end (new_image);
}

View File

@ -0,0 +1,10 @@
#ifndef __MAPOBJECT_APPLY_H__
#define __MAPOBJECT_APPLY_H__
extern gdouble imat[4][4];
extern gfloat rotmat[16];
void init_compute (void);
void compute_image (void);
#endif /* __MAPOBJECT_APPLY_H__ */

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gtk/gtk.h>
#include "map-object-icons.h"
#include "../lighting/images/lighting-icon-images.h"
void
mapobject_icons_init (void)
{
static gboolean initialized = FALSE;
GtkIconTheme *icon_theme;
if (initialized)
return;
initialized = TRUE;
icon_theme = gtk_icon_theme_get_default ();
gtk_icon_theme_add_resource_path (icon_theme, "/technology.heckin/lighting/icons");
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __MAPOBJECT_ICONS_H__
#define __MAPOBJECT_ICONS_H__
#define MAPOBJECT_INTENSITY_AMBIENT_LOW "lighting-intensity-ambient-low"
#define MAPOBJECT_INTENSITY_AMBIENT_HIGH "lighting-intensity-ambient-high"
#define MAPOBJECT_INTENSITY_DIFFUSE_LOW "lighting-intensity-diffuse-low"
#define MAPOBJECT_INTENSITY_DIFFUSE_HIGH "lighting-intensity-diffuse-high"
#define MAPOBJECT_REFLECTIVITY_DIFFUSE_LOW "lighting-reflectivity-diffuse-low"
#define MAPOBJECT_REFLECTIVITY_DIFFUSE_HIGH "lighting-reflectivity-diffuse-high"
#define MAPOBJECT_REFLECTIVITY_SPECULAR_LOW "lighting-reflectivity-specular-low"
#define MAPOBJECT_REFLECTIVITY_SPECULAR_HIGH "lighting-reflectivity-specular-high"
#define MAPOBJECT_REFLECTIVITY_HIGHLIGHT_LOW "lighting-reflectivity-highlight-low"
#define MAPOBJECT_REFLECTIVITY_HIGHLIGHT_HIGH "lighting-reflectivity-highlight-high"
void mapobject_icons_init (void);
#endif /* __MAPOBJECT_ICONS_H__ */

View File

@ -0,0 +1,354 @@
/*********************************************************/
/* 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 "config.h"
#include <string.h>
#include <sys/types.h>
#include <gtk/gtk.h>
#include <libpika/pika.h>
#include <libpika/pikaui.h>
#include "map-object-main.h"
#include "map-object-preview.h"
#include "map-object-shade.h"
#include "map-object-ui.h"
#include "map-object-image.h"
PikaImage *image;
PikaDrawable *input_drawable;
PikaDrawable *output_drawable;
GeglBuffer *source_buffer;
GeglBuffer *dest_buffer;
PikaDrawable *box_drawables[6];
GeglBuffer *box_buffers[6];
PikaDrawable *cylinder_drawables[2];
GeglBuffer *cylinder_buffers[2];
guchar *preview_rgb_data = NULL;
gint preview_rgb_stride;
cairo_surface_t *preview_surface = NULL;
glong maxcounter, old_depth, max_depth;
gint width, height;
PikaRGB background;
gint border_x, border_y, border_w, border_h;
/******************/
/* Implementation */
/******************/
PikaRGB
peek (gint x,
gint y)
{
PikaRGB color;
gegl_buffer_sample (source_buffer, x, y, NULL,
&color, babl_format ("R'G'B'A double"),
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
if (! babl_format_has_alpha (gegl_buffer_get_format (source_buffer)))
color.a = 1.0;
return color;
}
static PikaRGB
peek_box_image (gint image,
gint x,
gint y)
{
PikaRGB color;
gegl_buffer_sample (box_buffers[image], x, y, NULL,
&color, babl_format ("R'G'B'A double"),
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
if (! babl_format_has_alpha (gegl_buffer_get_format (box_buffers[image])))
color.a = 1.0;
return color;
}
static PikaRGB
peek_cylinder_image (gint image,
gint x,
gint y)
{
PikaRGB color;
gegl_buffer_sample (cylinder_buffers[image], x, y, NULL,
&color, babl_format ("R'G'B'A double"),
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
if (! babl_format_has_alpha (gegl_buffer_get_format (cylinder_buffers[image])))
color.a = 1.0;
return color;
}
void
poke (gint x,
gint y,
PikaRGB *color,
gpointer user_data)
{
gegl_buffer_set (dest_buffer, GEGL_RECTANGLE (x, y, 1, 1), 0,
babl_format ("R'G'B'A double"), color,
GEGL_AUTO_ROWSTRIDE);
}
gint
checkbounds (gint x,
gint y)
{
if (x < border_x ||
y < border_y ||
x >= border_x + border_w ||
y >= border_y + border_h)
return FALSE;
else
return TRUE;
}
static gint
checkbounds_box_image (gint image,
gint x,
gint y)
{
gint w, h;
w = gegl_buffer_get_width (box_buffers[image]);
h = gegl_buffer_get_height (box_buffers[image]);
if (x < 0 || y < 0 || x >= w || y >= h)
return FALSE ;
else
return TRUE ;
}
static gint
checkbounds_cylinder_image (gint image,
gint x,
gint y)
{
gint w, h;
w = gegl_buffer_get_width (cylinder_buffers[image]);
h = gegl_buffer_get_height (cylinder_buffers[image]);
if (x < 0 || y < 0 || x >= w || y >= h)
return FALSE;
else
return TRUE;
}
PikaVector3
int_to_pos (gint x,
gint y)
{
PikaVector3 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. */
/**********************************************/
PikaRGB
get_image_color (gdouble u,
gdouble v,
gint *inside)
{
gint x1, y1, x2, y2;
PikaRGB 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 pika_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 pika_bilinear_rgba (u * width, v * height, p);
}
PikaRGB
get_box_image_color (gint image,
gdouble u,
gdouble v)
{
gint w, h;
gint x1, y1, x2, y2;
PikaRGB p[4];
w = gegl_buffer_get_width (box_buffers[image]);
h = gegl_buffer_get_height (box_buffers[image]);
x1 = (gint) ((u * (gdouble) w));
y1 = (gint) ((v * (gdouble) h));
if (checkbounds_box_image (image, x1, y1) == FALSE)
return background;
x2 = (x1 + 1);
y2 = (y1 + 1);
if (checkbounds_box_image (image, x2, y2) == FALSE)
return peek_box_image (image, x1,y1);
p[0] = peek_box_image (image, x1, y1);
p[1] = peek_box_image (image, x2, y1);
p[2] = peek_box_image (image, x1, y2);
p[3] = peek_box_image (image, x2, y2);
return pika_bilinear_rgba (u * w, v * h, p);
}
PikaRGB
get_cylinder_image_color (gint image,
gdouble u,
gdouble v)
{
gint w, h;
gint x1, y1, x2, y2;
PikaRGB p[4];
w = gegl_buffer_get_width (cylinder_buffers[image]);
h = gegl_buffer_get_height (cylinder_buffers[image]);
x1 = (gint) ((u * (gdouble) w));
y1 = (gint) ((v * (gdouble) h));
if (checkbounds_cylinder_image (image, x1, y1) == FALSE)
return background;
x2 = (x1 + 1);
y2 = (y1 + 1);
if (checkbounds_cylinder_image (image, x2, y2) == FALSE)
return peek_cylinder_image (image, x1,y1);
p[0] = peek_cylinder_image (image, x1, y1);
p[1] = peek_cylinder_image (image, x2, y1);
p[2] = peek_cylinder_image (image, x1, y2);
p[3] = peek_cylinder_image (image, x2, y2);
return pika_bilinear_rgba (u * w, v * h, p);
}
/****************************************/
/* Allocate memory for temporary images */
/****************************************/
gint
image_setup (PikaDrawable *drawable,
gint interactive)
{
input_drawable = drawable;
output_drawable = drawable;
if (! pika_drawable_mask_intersect (drawable, &border_x, &border_y,
&border_w, &border_h))
return FALSE;
width = pika_drawable_get_width (input_drawable);
height = pika_drawable_get_height (input_drawable);
source_buffer = pika_drawable_get_buffer (input_drawable);
maxcounter = (glong) width * (glong) height;
if (mapvals.transparent_background == TRUE)
{
pika_rgba_set (&background, 0.0, 0.0, 0.0, 0.0);
}
else
{
pika_context_get_background (&background);
pika_rgb_set_alpha (&background, 1.0);
}
if (interactive == TRUE)
{
preview_rgb_stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24,
PREVIEW_WIDTH);
preview_rgb_data = g_new0 (guchar, preview_rgb_stride * PREVIEW_HEIGHT);
preview_surface = cairo_image_surface_create_for_data (preview_rgb_data,
CAIRO_FORMAT_RGB24,
PREVIEW_WIDTH,
PREVIEW_HEIGHT,
preview_rgb_stride);
}
return TRUE;
}

View File

@ -0,0 +1,64 @@
#ifndef __MAPOBJECT_IMAGE_H__
#define __MAPOBJECT_IMAGE_H__
/* Externally visible variables */
/* ============================ */
extern PikaImage *image;
extern PikaDrawable *input_drawable;
extern PikaDrawable *output_drawable;
extern GeglBuffer *source_buffer;
extern GeglBuffer *dest_buffer;
extern PikaDrawable *box_drawables[6];
extern GeglBuffer *box_buffers[6];
extern PikaDrawable *cylinder_drawables[2];
extern GeglBuffer *cylinder_buffers[2];
extern guchar *preview_rgb_data;
extern gint preview_rgb_stride;
extern cairo_surface_t *preview_surface;
extern glong maxcounter, old_depth, max_depth;
extern gint width, height;
extern PikaRGB background;
extern gint border_x1, border_y1, border_x2, border_y2;
/* Externally visible functions */
/* ============================ */
extern gint image_setup (PikaDrawable *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 PikaRGB peek (gint x,
gint y);
extern void poke (gint x,
gint y,
PikaRGB *color,
gpointer user_data);
extern PikaVector3 int_to_pos (gint x,
gint y);
extern void pos_to_int (gdouble x,
gdouble y,
gint *scr_x,
gint *scr_y);
extern PikaRGB get_image_color (gdouble u,
gdouble v,
gint *inside);
extern PikaRGB get_box_image_color (gint image,
gdouble u,
gdouble v);
extern PikaRGB get_cylinder_image_color (gint image,
gdouble u,
gdouble v);
#endif /* __MAPOBJECT_IMAGE_H__ */

View File

@ -0,0 +1,612 @@
/* MapObject 1.2.0 -- image filter plug-in for PIKA
*
* Copyright (C) 1996-98 Tom Bech
* Copyright (C) 1996-98 Federico Mena Quintero
*
* E-mail: tomb@gimp.org (Tom) or quartic@gimp.org (Federico)
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gtk/gtk.h>
#include <libpika/pika.h>
#include <libpika/pikaui.h>
#include "map-object-ui.h"
#include "map-object-image.h"
#include "map-object-apply.h"
#include "map-object-preview.h"
#include "map-object-main.h"
#include "libpika/stdplugins-intl.h"
MapObjectValues mapvals;
typedef struct _Map Map;
typedef struct _MapClass MapClass;
struct _Map
{
PikaPlugIn parent_instance;
};
struct _MapClass
{
PikaPlugInClass parent_class;
};
#define MAP_TYPE (map_get_type ())
#define MAP (obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAP_TYPE, Map))
GType map_get_type (void) G_GNUC_CONST;
static GList * map_query_procedures (PikaPlugIn *plug_in);
static PikaProcedure * map_create_procedure (PikaPlugIn *plug_in,
const gchar *name);
static PikaValueArray * map_run (PikaProcedure *procedure,
PikaRunMode run_mode,
PikaImage *image,
gint n_drawables,
PikaDrawable **drawables,
const PikaValueArray *args,
gpointer run_data);
static void set_default_settings (void);
static void check_drawables (PikaDrawable *drawable);
G_DEFINE_TYPE (Map, map, PIKA_TYPE_PLUG_IN)
PIKA_MAIN (MAP_TYPE)
DEFINE_STD_SET_I18N
static void
map_class_init (MapClass *klass)
{
PikaPlugInClass *plug_in_class = PIKA_PLUG_IN_CLASS (klass);
plug_in_class->query_procedures = map_query_procedures;
plug_in_class->create_procedure = map_create_procedure;
plug_in_class->set_i18n = STD_SET_I18N;
}
static void
map_init (Map *map)
{
}
static GList *
map_query_procedures (PikaPlugIn *plug_in)
{
return g_list_append (NULL, g_strdup (PLUG_IN_PROC));
}
static PikaProcedure *
map_create_procedure (PikaPlugIn *plug_in,
const gchar *name)
{
PikaProcedure *procedure = NULL;
if (! strcmp (name, PLUG_IN_PROC))
{
PikaRGB white = { 1.0, 1.0, 1.0, 1.0 };
procedure = pika_image_procedure_new (plug_in, name,
PIKA_PDB_PROC_TYPE_PLUGIN,
map_run, NULL, NULL);
pika_procedure_set_image_types (procedure, "RGB*");
pika_procedure_set_sensitivity_mask (procedure,
PIKA_PROCEDURE_SENSITIVE_DRAWABLE);
pika_procedure_set_menu_label (procedure, _("Map _Object..."));
pika_procedure_add_menu_path (procedure, "<Image>/Filters/Map");
pika_procedure_set_documentation (procedure,
_("Map the image to an object "
"(plane, sphere, box or cylinder)"),
"No help yet",
name);
pika_procedure_set_attribution (procedure,
"Tom Bech & Federico Mena Quintero",
"Tom Bech & Federico Mena Quintero",
"Version 1.2.0, July 16 1998");
PIKA_PROC_ARG_INT (procedure, "map-type",
"Map type",
"Type of mapping (0=plane, 1=sphere, 2=box, "
"3=cylinder)",
0, 2, MAP_PLANE,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "viewpoint-x",
"Viewpoint X",
"Position of viewpoint (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, 0.5,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "viewpoint-y",
"Viewpoint Y",
"Position of viewpoint (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, 0.5,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "viewpoint-z",
"Viewpoint Z",
"Position of viewpoint (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, 2.0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "position-x",
"Position X",
"Object position (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, 0.5,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "position-y",
"Position Y",
"Object position (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, 0.5,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "position-z",
"Position Z",
"Object position (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "first-axis-x",
"First axis X",
"First axis of object (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, 1.0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "first-axis-y",
"First axis y",
"First axis of object (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "first-axis-z",
"First axis Z",
"First axis of object (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "second-axis-x",
"Second axis X",
"Second axis of object (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "second-axis-y",
"Second axis Y",
"Second axis of object (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, 1.0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "second-axis-z",
"Second axis Z",
"Second axis of object (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "rotation-angle-x",
"Rotation angle X",
"Rotation about X axis in degrees",
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "rotation-angle-y",
"Rotation angle Y",
"Rotation about Y axis in degrees",
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "rotation-angle-z",
"Rotation angle Z",
"Rotation about Z axis in degrees",
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_INT (procedure, "light-type",
"Light type",
"Type of lightsource (0=point, 1=directional, 2=none)",
0, 2, POINT_LIGHT,
G_PARAM_READWRITE);
PIKA_PROC_ARG_RGB (procedure, "light-color",
"Light color",
"Light source color",
TRUE, &white,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "light-position-x",
"Light position X",
"Light source position (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, -0.5,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "light-position-y",
"Light position Y",
"Light source position (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, -0.5,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "light-position-z",
"Light position Z",
"Light source position (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, 2.0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "light-direction-x",
"Light direction X",
"Light source direction (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, -1.0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "light-direction-y",
"Light direction Y",
"Light source direction (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, -1.0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "light-direction-z",
"Light direction Z",
"Light source direction (x,y,z)",
-G_MAXDOUBLE, G_MAXDOUBLE, 1.0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "ambient-intensity",
"Ambient intensity",
"Material ambient intensity",
0, 1, 0.3,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "diffuse-intensity",
"Diffuse intensity",
"Material diffuse intensity",
0, 1, 1.0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "diffuse-reflectivity",
"Diffuse reflectivity",
"Material diffuse reflectivity",
0, 1, 0.5,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "specular-reflectivity",
"Specular reflectivity",
"Material specular reflectivity",
0, 1, 0.5,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "highlight",
"Highlight",
"Material highlight (note, it's exponential)",
0, G_MAXDOUBLE, 27.0,
G_PARAM_READWRITE);
PIKA_PROC_ARG_BOOLEAN (procedure, "antialiasing",
"Antialiasing",
"Apply antialiasing",
TRUE,
G_PARAM_READWRITE);
PIKA_PROC_ARG_BOOLEAN (procedure, "tiled",
"Tiled",
"Tile source image",
FALSE,
G_PARAM_READWRITE);
PIKA_PROC_ARG_BOOLEAN (procedure, "new-image",
"New image",
"Create a new image",
FALSE,
G_PARAM_READWRITE);
PIKA_PROC_ARG_BOOLEAN (procedure, "transparent-background",
"Transparent background",
"Make background transparent",
FALSE,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "radius",
"Radius",
"Sphere/cylinder radius (only used when "
"maptype=1 or 3)",
0, G_MAXDOUBLE, 0.25,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "x-scale",
"X scale",
"Box X size",
0, G_MAXDOUBLE, 0.5,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "y-scale",
"Y scale",
"Box Y size",
0, G_MAXDOUBLE, 0.5,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "z-scale",
"Z scale",
"Box Z size",
0, G_MAXDOUBLE, 0.5,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DOUBLE (procedure, "cylinder-length",
"Cylinder length",
"Cylinder length",
0, G_MAXDOUBLE, 0.25,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DRAWABLE (procedure, "box-front-drawable",
"Box front drawable",
"Box front face (set these to NULL if not used)",
TRUE,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DRAWABLE (procedure, "box-back-drawable",
"Box back drawable",
"Box back face",
TRUE,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DRAWABLE (procedure, "box-top-drawable",
"Box top drawable",
"Box top face",
TRUE,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DRAWABLE (procedure, "box-bottom-drawable",
"Box bottom drawable",
"Box bottom face",
TRUE,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DRAWABLE (procedure, "box-left-drawable",
"Box left drawable",
"Box left face",
TRUE,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DRAWABLE (procedure, "box-right-drawable",
"Box right drawable",
"Box right face",
TRUE,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DRAWABLE (procedure, "cyl-top-drawable",
"Cyl top drawable",
"Cylinder top face (set these to NULL if not used)",
TRUE,
G_PARAM_READWRITE);
PIKA_PROC_ARG_DRAWABLE (procedure, "cyl-bottom-drawable",
"Cyl bottom drawable",
"Cylinder bottom face",
TRUE,
G_PARAM_READWRITE);
}
return procedure;
}
static void
set_default_settings (void)
{
gint i;
pika_vector3_set (&mapvals.viewpoint, 0.5, 0.5, 2.0);
pika_vector3_set (&mapvals.firstaxis, 1.0, 0.0, 0.0);
pika_vector3_set (&mapvals.secondaxis, 0.0, 1.0, 0.0);
pika_vector3_set (&mapvals.normal, 0.0, 0.0, 1.0);
pika_vector3_set (&mapvals.position, 0.5, 0.5, 0.0);
pika_vector3_set (&mapvals.lightsource.position, -0.5, -0.5, 2.0);
pika_vector3_set (&mapvals.lightsource.direction, -1.0, -1.0, 1.0);
pika_vector3_set (&mapvals.scale, 0.5, 0.5, 0.5);
mapvals.maptype = MAP_PLANE;
mapvals.pixelthreshold = 0.25;
mapvals.alpha = 0.0;
mapvals.beta = 0.0;
mapvals.gamma = 0.0;
mapvals.maxdepth = 3.0;
mapvals.radius = 0.25;
mapvals.cylinder_radius = 0.25;
mapvals.cylinder_length = 1.0;
mapvals.zoom = 1.0;
mapvals.lightsource.type = POINT_LIGHT;
mapvals.antialiasing = TRUE;
mapvals.create_new_image = FALSE;
mapvals.create_new_layer = FALSE;
mapvals.transparent_background = FALSE;
mapvals.tiled = FALSE;
mapvals.livepreview = FALSE;
mapvals.showgrid = TRUE;
mapvals.lightsource.intensity = 1.0;
pika_rgba_set (&mapvals.lightsource.color, 1.0, 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;
for (i = 0; i < 6; i++)
mapvals.boxmap_id[i] = -1;
for (i = 0; i < 2; i++)
mapvals.cylindermap_id[i] = -1;
}
static void
check_drawables (PikaDrawable *drawable)
{
PikaDrawable *map;
gint i;
/* Check that boxmap images are valid */
/* ================================== */
for (i = 0; i < 6; i++)
{
map = pika_drawable_get_by_id (mapvals.boxmap_id[i]);
if (! map || pika_drawable_is_gray (map))
mapvals.boxmap_id[i] = pika_item_get_id (PIKA_ITEM (drawable));
}
/* Check that cylindermap images are valid */
/* ======================================= */
for (i = 0; i < 2; i++)
{
map = pika_drawable_get_by_id (mapvals.cylindermap_id[i]);
if (! map || pika_drawable_is_gray (map))
mapvals.cylindermap_id[i] = pika_item_get_id (PIKA_ITEM (drawable));
}
}
static PikaValueArray *
map_run (PikaProcedure *procedure,
PikaRunMode run_mode,
PikaImage *_image,
gint n_drawables,
PikaDrawable **drawables,
const PikaValueArray *args,
gpointer run_data)
{
PikaDrawable *drawable;
gint i;
gegl_init (NULL, NULL);
image = _image;
if (n_drawables != 1)
{
GError *error = NULL;
g_set_error (&error, PIKA_PLUG_IN_ERROR, 0,
_("Procedure '%s' only works with one drawable."),
pika_procedure_get_name (procedure));
return pika_procedure_new_return_values (procedure,
PIKA_PDB_CALLING_ERROR,
error);
}
else
{
drawable = drawables[0];
}
set_default_settings ();
switch (run_mode)
{
case PIKA_RUN_INTERACTIVE:
pika_get_data (PLUG_IN_PROC, &mapvals);
check_drawables (drawable);
if (! main_dialog (drawable))
{
return pika_procedure_new_return_values (procedure,
PIKA_PDB_CANCEL,
NULL);
}
compute_image ();
pika_set_data (PLUG_IN_PROC, &mapvals, sizeof (MapObjectValues));
break;
case PIKA_RUN_WITH_LAST_VALS:
pika_get_data (PLUG_IN_PROC, &mapvals);
check_drawables (drawable);
if (! image_setup (drawable, FALSE))
{
return pika_procedure_new_return_values (procedure,
PIKA_PDB_SUCCESS,
NULL);
}
compute_image ();
break;
case PIKA_RUN_NONINTERACTIVE:
mapvals.maptype = PIKA_VALUES_GET_INT (args, 0);
mapvals.viewpoint.x = PIKA_VALUES_GET_DOUBLE (args, 1);
mapvals.viewpoint.y = PIKA_VALUES_GET_DOUBLE (args, 2);
mapvals.viewpoint.z = PIKA_VALUES_GET_DOUBLE (args, 3);
mapvals.position.x = PIKA_VALUES_GET_DOUBLE (args, 4);
mapvals.position.y = PIKA_VALUES_GET_DOUBLE (args, 5);
mapvals.position.z = PIKA_VALUES_GET_DOUBLE (args, 6);
mapvals.firstaxis.x = PIKA_VALUES_GET_DOUBLE (args, 7);
mapvals.firstaxis.y = PIKA_VALUES_GET_DOUBLE (args, 8);
mapvals.firstaxis.z = PIKA_VALUES_GET_DOUBLE (args, 9);
mapvals.secondaxis.x = PIKA_VALUES_GET_DOUBLE (args, 10);
mapvals.secondaxis.y = PIKA_VALUES_GET_DOUBLE (args, 11);
mapvals.secondaxis.z = PIKA_VALUES_GET_DOUBLE (args, 12);
mapvals.alpha = PIKA_VALUES_GET_DOUBLE (args, 13);
mapvals.beta = PIKA_VALUES_GET_DOUBLE (args, 14);
mapvals.gamma = PIKA_VALUES_GET_DOUBLE (args, 15);
mapvals.lightsource.type = PIKA_VALUES_GET_INT (args, 16);
PIKA_VALUES_GET_RGB (args, 17, &mapvals.lightsource.color);
mapvals.lightsource.position.x = PIKA_VALUES_GET_DOUBLE (args, 18);
mapvals.lightsource.position.y = PIKA_VALUES_GET_DOUBLE (args, 19);
mapvals.lightsource.position.z = PIKA_VALUES_GET_DOUBLE (args, 20);
mapvals.lightsource.direction.x = PIKA_VALUES_GET_DOUBLE (args, 21);
mapvals.lightsource.direction.y = PIKA_VALUES_GET_DOUBLE (args, 22);
mapvals.lightsource.direction.z = PIKA_VALUES_GET_DOUBLE (args, 23);
mapvals.material.ambient_int = PIKA_VALUES_GET_DOUBLE (args, 24);
mapvals.material.diffuse_int = PIKA_VALUES_GET_DOUBLE (args, 25);
mapvals.material.diffuse_ref = PIKA_VALUES_GET_DOUBLE (args, 26);
mapvals.material.specular_ref = PIKA_VALUES_GET_DOUBLE (args, 27);
mapvals.material.highlight = PIKA_VALUES_GET_DOUBLE (args, 28);
mapvals.antialiasing = PIKA_VALUES_GET_BOOLEAN (args, 29);
mapvals.tiled = PIKA_VALUES_GET_BOOLEAN (args, 30);
mapvals.create_new_image = PIKA_VALUES_GET_BOOLEAN (args, 31);
mapvals.transparent_background = PIKA_VALUES_GET_BOOLEAN (args, 32);
mapvals.radius =
mapvals.cylinder_radius = PIKA_VALUES_GET_DOUBLE (args, 33);
mapvals.scale.x = PIKA_VALUES_GET_DOUBLE (args, 34);
mapvals.scale.y = PIKA_VALUES_GET_DOUBLE (args, 35);
mapvals.scale.z = PIKA_VALUES_GET_DOUBLE (args, 36);
mapvals.cylinder_length = PIKA_VALUES_GET_DOUBLE (args, 37);
for (i = 0; i < 6; i++)
{
mapvals.boxmap_id[i] = PIKA_VALUES_GET_DRAWABLE_ID (args, 38 + i);
}
for (i = 0; i < 2; i++)
{
mapvals.cylindermap_id[i] = PIKA_VALUES_GET_DRAWABLE_ID (args, 44 + i);
}
check_drawables (drawable);
if (! image_setup (drawable, FALSE))
{
return pika_procedure_new_return_values (procedure,
PIKA_PDB_SUCCESS,
NULL);
}
compute_image ();
break;
}
if (run_mode != PIKA_RUN_NONINTERACTIVE)
pika_displays_flush ();
return pika_procedure_new_return_values (procedure, PIKA_PDB_SUCCESS, NULL);
}

View File

@ -0,0 +1,90 @@
#ifndef __MAPOBJECT_MAIN_H__
#define __MAPOBJECT_MAIN_H__
/* Defines and stuff */
/* ================= */
#define PLUG_IN_PROC "plug-in-map-object"
#define PLUG_IN_BINARY "map-object"
#define PLUG_IN_ROLE "pika-map-object"
#define TILE_CACHE_SIZE 16
/* Typedefs */
/* ======== */
typedef enum
{
POINT_LIGHT,
DIRECTIONAL_LIGHT,
NO_LIGHT
} LightType;
typedef enum
{
MAP_PLANE,
MAP_SPHERE,
MAP_BOX,
MAP_CYLINDER
} MapType;
/* Typedefs */
/* ======== */
typedef struct
{
gdouble ambient_int;
gdouble diffuse_int;
gdouble diffuse_ref;
gdouble specular_ref;
gdouble highlight;
PikaRGB color;
} MaterialSettings;
typedef struct
{
LightType type;
PikaVector3 position;
PikaVector3 direction;
PikaRGB color;
gdouble intensity;
} LightSettings;
typedef struct
{
PikaVector3 viewpoint,firstaxis,secondaxis,normal,position,scale;
LightSettings lightsource;
MaterialSettings material;
MaterialSettings refmaterial;
MapType maptype;
gint antialiasing;
gint create_new_image;
gint create_new_layer;
gint transparent_background;
gint tiled;
gint livepreview;
gint showgrid;
gint showcaps;
gdouble zoom;
gdouble alpha,beta,gamma;
gdouble maxdepth;
gdouble pixelthreshold;
gdouble radius;
gdouble cylinder_radius;
gdouble cylinder_length;
gint32 boxmap_id[6];
gint32 cylindermap_id[2];
} MapObjectValues;
/* Externally visible variables */
/* ============================ */
extern MapObjectValues mapvals;
#endif /* __MAPOBJECT_MAIN_H__ */

View File

@ -0,0 +1,741 @@
/*************************************************/
/* Compute a preview image and preview wireframe */
/*************************************************/
#include "config.h"
#include <gtk/gtk.h>
#include <libpika/pika.h>
#include <libpika/pikaui.h>
#include "map-object-main.h"
#include "map-object-ui.h"
#include "map-object-image.h"
#include "map-object-apply.h"
#include "map-object-shade.h"
#include "map-object-preview.h"
gdouble mat[3][4];
gint lightx, lighty;
/* Protos */
/* ====== */
static void compute_preview (gint x,
gint y,
gint w,
gint h,
gint pw,
gint ph);
static void draw_light_marker (cairo_t *cr,
gint xpos,
gint ypos);
static void draw_line (cairo_t *cr,
gint startx,
gint starty,
gint pw,
gint ph,
gdouble cx1,
gdouble cy1,
gdouble cx2,
gdouble cy2,
PikaVector3 a,
PikaVector3 b);
static void draw_wireframe (cairo_t *cr,
gint startx,
gint starty,
gint pw,
gint ph);
static void draw_preview_wireframe (cairo_t *cr);
static void draw_wireframe_plane (cairo_t *cr,
gint startx,
gint starty,
gint pw,
gint ph);
static void draw_wireframe_sphere (cairo_t *cr,
gint startx,
gint starty,
gint pw,
gint ph);
static void draw_wireframe_box (cairo_t *cr,
gint startx,
gint starty,
gint pw,
gint ph);
static void draw_wireframe_cylinder (cairo_t *cr,
gint startx,
gint starty,
gint pw,
gint ph);
/**************************************************************/
/* Computes a preview of the rectangle starting at (x,y) with */
/* dimensions (w,h), placing the result in preview_RGB_data. */
/**************************************************************/
static void
compute_preview (gint x,
gint y,
gint w,
gint h,
gint pw,
gint ph)
{
gdouble xpostab[PREVIEW_WIDTH];
gdouble ypostab[PREVIEW_HEIGHT];
gdouble realw;
gdouble realh;
PikaVector3 p1, p2;
PikaRGB color;
PikaRGB lightcheck, darkcheck;
gint xcnt, ycnt, f1, f2;
guchar r, g, b;
glong index = 0;
init_compute ();
if (! preview_surface)
return;
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; xcnt < pw; xcnt++)
xpostab[xcnt] = p1.x + realw * ((gdouble) xcnt / (gdouble) pw);
for (ycnt = 0; ycnt < ph; ycnt++)
ypostab[ycnt] = p1.y + realh * ((gdouble) ycnt / (gdouble) ph);
/* Compute preview using the offset tables */
/* ======================================= */
if (mapvals.transparent_background == TRUE)
{
pika_rgba_set (&background, 0.0, 0.0, 0.0, 0.0);
}
else
{
pika_context_get_background (&background);
pika_rgb_set_alpha (&background, 1.0);
}
pika_rgba_set (&lightcheck,
PIKA_CHECK_LIGHT, PIKA_CHECK_LIGHT, PIKA_CHECK_LIGHT, 1.0);
pika_rgba_set (&darkcheck,
PIKA_CHECK_DARK, PIKA_CHECK_DARK, PIKA_CHECK_DARK, 1.0);
pika_vector3_set (&p2, -1.0, -1.0, 0.0);
cairo_surface_flush (preview_surface);
for (ycnt = 0; ycnt < ph; ycnt++)
{
index = ycnt * preview_rgb_stride;
for (xcnt = 0; xcnt < pw; xcnt++)
{
p1.x = xpostab[xcnt];
p1.y = ypostab[ycnt];
p2 = p1;
color = (* get_ray_color) (&p1);
if (color.a < 1.0)
{
f1 = ((xcnt % 32) < 16);
f2 = ((ycnt % 32) < 16);
f1 = f1 ^ f2;
if (f1)
{
if (color.a == 0.0)
color = lightcheck;
else
pika_rgb_composite (&color, &lightcheck,
PIKA_RGB_COMPOSITE_BEHIND);
}
else
{
if (color.a == 0.0)
color = darkcheck;
else
pika_rgb_composite (&color, &darkcheck,
PIKA_RGB_COMPOSITE_BEHIND);
}
}
pika_rgb_get_uchar (&color, &r, &g, &b);
PIKA_CAIRO_RGB24_SET_PIXEL((preview_rgb_data + index), r, g, b);
index += 4;
}
}
cairo_surface_mark_dirty (preview_surface);
}
/*************************************************/
/* 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 */
/****************************************/
static void
draw_light_marker (cairo_t *cr,
gint xpos,
gint ypos)
{
GdkRGBA color;
if (mapvals.lightsource.type != POINT_LIGHT)
return;
cairo_set_line_width (cr, 1.0);
color.red = 0.0;
color.green = 0.2;
color.blue = 1.0;
color.alpha = 1.0;
gdk_cairo_set_source_rgba (cr, &color);
lightx = xpos;
lighty = ypos;
cairo_arc (cr, lightx, lighty, 7, 0, 2 * G_PI);
cairo_fill (cr);
}
static void
draw_lights (cairo_t *cr,
gint startx,
gint starty,
gint pw,
gint ph)
{
gdouble dxpos, dypos;
gint xpos, ypos;
pika_vector_3d_to_2d (startx, starty, pw, ph,
&dxpos, &dypos, &mapvals.viewpoint,
&mapvals.lightsource.position);
xpos = RINT (dxpos);
ypos = RINT (dypos);
if (xpos >= 0 && xpos <= PREVIEW_WIDTH &&
ypos >= 0 && ypos <= PREVIEW_HEIGHT)
{
draw_light_marker (cr, 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.zoom;
ph = PREVIEW_HEIGHT * mapvals.zoom;
startx = (PREVIEW_WIDTH - pw) / 2;
starty = (PREVIEW_HEIGHT - ph) / 2;
pika_vector_2d_to_3d (startx, starty, pw, ph, xpos, ypos,
&mapvals.viewpoint, &mapvals.lightsource.position);
gtk_widget_queue_draw (previewarea);
}
/**************************/
/* Compute preview image. */
/**************************/
void
compute_preview_image (void)
{
GdkDisplay *display = gtk_widget_get_display (previewarea);
GdkCursor *cursor;
gint pw, ph;
pw = PREVIEW_WIDTH * mapvals.zoom;
ph = PREVIEW_HEIGHT * mapvals.zoom;
cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
gdk_window_set_cursor (gtk_widget_get_window (previewarea), cursor);
g_object_unref (cursor);
compute_preview (0, 0, width - 1, height - 1, pw, ph);
cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
gdk_window_set_cursor(gtk_widget_get_window (previewarea), cursor);
g_object_unref (cursor);
}
gboolean
preview_draw (GtkWidget *widget,
cairo_t *cr)
{
gint startx, starty, pw, ph;
pw = PREVIEW_WIDTH * mapvals.zoom;
ph = PREVIEW_HEIGHT * mapvals.zoom;
startx = (PREVIEW_WIDTH - pw) / 2;
starty = (PREVIEW_HEIGHT - ph) / 2;
cairo_set_source_surface (cr, preview_surface, startx, starty);
cairo_rectangle (cr, startx, starty, pw, ph);
cairo_clip (cr);
cairo_paint (cr);
cairo_reset_clip (cr);
if (mapvals.showgrid)
draw_preview_wireframe (cr);
cairo_reset_clip (cr);
draw_lights (cr, startx, starty, pw, ph);
return FALSE;
}
/**************************/
/* Draw preview wireframe */
/**************************/
void
draw_preview_wireframe (cairo_t *cr)
{
gint startx, starty, pw, ph;
pw = PREVIEW_WIDTH * mapvals.zoom;
ph = PREVIEW_HEIGHT * mapvals.zoom;
startx = (PREVIEW_WIDTH - pw) / 2;
starty = (PREVIEW_HEIGHT - ph) / 2;
draw_wireframe (cr, startx, starty, pw, ph);
}
/****************************/
/* Draw a wireframe preview */
/****************************/
void
draw_wireframe (cairo_t *cr,
gint startx,
gint starty,
gint pw,
gint ph)
{
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
switch (mapvals.maptype)
{
case MAP_PLANE:
draw_wireframe_plane (cr, startx, starty, pw, ph);
break;
case MAP_SPHERE:
draw_wireframe_sphere (cr, startx, starty, pw, ph);
break;
case MAP_BOX:
draw_wireframe_box (cr, startx, starty, pw, ph);
break;
case MAP_CYLINDER:
draw_wireframe_cylinder (cr, startx, starty, pw, ph);
break;
}
}
static void
draw_wireframe_plane (cairo_t *cr,
gint startx,
gint starty,
gint pw,
gint ph)
{
PikaVector3 v1, v2, a, b, c, d, dir1, dir2;
gint cnt;
gdouble x1, y1, x2, y2, fac;
cairo_rectangle (cr, startx, starty, pw, ph);
cairo_clip (cr);
/* Find rotated box corners */
/* ======================== */
pika_vector3_set (&v1, 0.5, 0.0, 0.0);
pika_vector3_set (&v2, 0.0, 0.5, 0.0);
pika_vector3_rotate (&v1,
pika_deg_to_rad (mapvals.alpha),
pika_deg_to_rad (mapvals.beta),
pika_deg_to_rad (mapvals.gamma));
pika_vector3_rotate (&v2,
pika_deg_to_rad (mapvals.alpha),
pika_deg_to_rad (mapvals.beta),
pika_deg_to_rad (mapvals.gamma));
dir1 = v1; pika_vector3_normalize (&dir1);
dir2 = v2; pika_vector3_normalize (&dir2);
fac = 1.0 / (gdouble) WIRESIZE;
pika_vector3_mul (&dir1, fac);
pika_vector3_mul (&dir2, fac);
pika_vector3_add (&a, &mapvals.position, &v1);
pika_vector3_sub (&b, &a, &v2);
pika_vector3_add (&a, &a, &v2);
pika_vector3_sub (&d, &mapvals.position, &v1);
pika_vector3_sub (&d, &d, &v2);
c = b;
for (cnt = 0; cnt <= WIRESIZE; cnt++)
{
pika_vector_3d_to_2d (startx, starty, pw, ph,
&x1, &y1, &mapvals.viewpoint, &a);
pika_vector_3d_to_2d (startx, starty, pw, ph,
&x2, &y2, &mapvals.viewpoint, &b);
cairo_move_to (cr, RINT (x1) + 0.5, RINT (y1) + 0.5);
cairo_line_to (cr, RINT (x2) + 0.5, RINT (y2) + 0.5);
pika_vector_3d_to_2d (startx, starty, pw, ph,
&x1, &y1, &mapvals.viewpoint, &c);
pika_vector_3d_to_2d (startx, starty, pw, ph,
&x2, &y2, &mapvals.viewpoint, &d);
cairo_move_to (cr, RINT (x1) + 0.5, RINT (y1) + 0.5);
cairo_line_to (cr, RINT (x2) + 0.5, RINT (y2) + 0.5);
pika_vector3_sub (&a, &a, &dir1);
pika_vector3_sub (&b, &b, &dir1);
pika_vector3_add (&c, &c, &dir2);
pika_vector3_add (&d, &d, &dir2);
}
cairo_set_line_width (cr, 3.0);
cairo_stroke_preserve (cr);
cairo_set_line_width (cr, 1.0);
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
cairo_stroke (cr);
}
static void
draw_wireframe_sphere (cairo_t *cr,
gint startx,
gint starty,
gint pw,
gint ph)
{
PikaVector3 p[2 * (WIRESIZE + 5)];
gint cnt, cnt2;
gdouble x1, y1, x2, y2, twopifac;
cairo_rectangle (cr, startx, starty, pw, ph);
cairo_clip (cr);
/* Compute wireframe points */
/* ======================== */
twopifac = (2.0 * G_PI) / WIRESIZE;
for (cnt = 0; cnt < WIRESIZE; cnt++)
{
p[cnt].x = mapvals.radius * cos ((gdouble) cnt * twopifac);
p[cnt].y = 0.0;
p[cnt].z = mapvals.radius * sin ((gdouble) cnt * twopifac);
pika_vector3_rotate (&p[cnt],
pika_deg_to_rad (mapvals.alpha),
pika_deg_to_rad (mapvals.beta),
pika_deg_to_rad (mapvals.gamma));
pika_vector3_add (&p[cnt], &p[cnt], &mapvals.position);
}
p[cnt] = p[0];
for (cnt = WIRESIZE + 1; cnt < 2 * WIRESIZE + 1; cnt++)
{
p[cnt].x = mapvals.radius * cos ((gdouble) (cnt-(WIRESIZE+1))*twopifac);
p[cnt].y = mapvals.radius * sin ((gdouble) (cnt-(WIRESIZE+1))*twopifac);
p[cnt].z = 0.0;
pika_vector3_rotate (&p[cnt],
pika_deg_to_rad (mapvals.alpha),
pika_deg_to_rad (mapvals.beta),
pika_deg_to_rad (mapvals.gamma));
pika_vector3_add (&p[cnt], &p[cnt], &mapvals.position);
}
p[cnt] = p[WIRESIZE+1];
cnt++;
cnt2 = cnt;
/* Find rotated axis */
/* ================= */
pika_vector3_set (&p[cnt], 0.0, -0.35, 0.0);
pika_vector3_rotate (&p[cnt],
pika_deg_to_rad (mapvals.alpha),
pika_deg_to_rad (mapvals.beta),
pika_deg_to_rad (mapvals.gamma));
p[cnt+1] = mapvals.position;
pika_vector3_set (&p[cnt+2], 0.0, 0.0, -0.35);
pika_vector3_rotate (&p[cnt+2],
pika_deg_to_rad (mapvals.alpha),
pika_deg_to_rad (mapvals.beta),
pika_deg_to_rad (mapvals.gamma));
p[cnt+3] = mapvals.position;
p[cnt + 4] = p[cnt];
pika_vector3_mul (&p[cnt + 4], -1.0);
p[cnt + 5] = p[cnt + 1];
pika_vector3_add (&p[cnt], &p[cnt], &mapvals.position);
pika_vector3_add (&p[cnt + 2], &p[cnt + 2], &mapvals.position);
pika_vector3_add (&p[cnt + 4], &p[cnt + 4], &mapvals.position);
/* Draw the circles (equator and zero meridian) */
/* ============================================ */
for (cnt = 0; cnt < cnt2 - 1; cnt++)
{
if (p[cnt].z > mapvals.position.z && p[cnt + 1].z > mapvals.position.z)
{
pika_vector_3d_to_2d (startx, starty, pw, ph,
&x1, &y1, &mapvals.viewpoint, &p[cnt]);
pika_vector_3d_to_2d (startx, starty, pw, ph,
&x2, &y2, &mapvals.viewpoint, &p[cnt + 1]);
cairo_move_to (cr, (gint) (x1 + 0.5) + 0.5, (gint) (y1 + 0.5) + 0.5);
cairo_line_to (cr, (gint) (x2 + 0.5) + 0.5, (gint) (y2 + 0.5) + 0.5);
}
}
/* Draw the axis (pole to pole and center to zero meridian) */
/* ======================================================== */
for (cnt = 0; cnt < 3; cnt++)
{
pika_vector_3d_to_2d (startx, starty, pw, ph,
&x1, &y1, &mapvals.viewpoint, &p[cnt2]);
pika_vector_3d_to_2d (startx, starty, pw, ph,
&x2, &y2, &mapvals.viewpoint, &p[cnt2 + 1]);
cairo_move_to (cr, RINT (x1) + 0.5, RINT (y1) + 0.5);
cairo_line_to (cr, RINT (x2) + 0.5, RINT (y2) + 0.5);
cnt2 += 2;
}
cairo_set_line_width (cr, 3.0);
cairo_stroke_preserve (cr);
cairo_set_line_width (cr, 1.0);
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
cairo_stroke (cr);
}
static void
draw_line (cairo_t *cr,
gint startx,
gint starty,
gint pw,
gint ph,
gdouble cx1,
gdouble cy1,
gdouble cx2,
gdouble cy2,
PikaVector3 a,
PikaVector3 b)
{
gdouble x1, y1, x2, y2;
pika_vector_3d_to_2d (startx, starty, pw, ph,
&x1, &y1, &mapvals.viewpoint, &a);
pika_vector_3d_to_2d (startx, starty, pw, ph,
&x2, &y2, &mapvals.viewpoint, &b);
cairo_move_to (cr, RINT (x1) + 0.5, RINT (y1) + 0.5);
cairo_line_to (cr, RINT (x2) + 0.5, RINT (y2) + 0.5);
}
static void
draw_wireframe_box (cairo_t *cr,
gint startx,
gint starty,
gint pw,
gint ph)
{
PikaVector3 p[8], tmp, scale;
gint i;
gdouble cx1, cy1, cx2, cy2;
cairo_rectangle (cr, startx, starty, pw, ph);
cairo_clip (cr);
/* Compute wireframe points */
/* ======================== */
init_compute ();
scale = mapvals.scale;
pika_vector3_mul (&scale, 0.5);
pika_vector3_set (&p[0], -scale.x, -scale.y, scale.z);
pika_vector3_set (&p[1], scale.x, -scale.y, scale.z);
pika_vector3_set (&p[2], scale.x, scale.y, scale.z);
pika_vector3_set (&p[3], -scale.x, scale.y, scale.z);
pika_vector3_set (&p[4], -scale.x, -scale.y, -scale.z);
pika_vector3_set (&p[5], scale.x, -scale.y, -scale.z);
pika_vector3_set (&p[6], scale.x, scale.y, -scale.z);
pika_vector3_set (&p[7], -scale.x, scale.y, -scale.z);
/* Rotate and translate points */
/* =========================== */
for (i = 0; i < 8; i++)
{
vecmulmat (&tmp, &p[i], rotmat);
pika_vector3_add (&p[i], &tmp, &mapvals.position);
}
/* Draw the box */
/* ============ */
cx1 = (gdouble) startx;
cy1 = (gdouble) starty;
cx2 = cx1 + (gdouble) pw;
cy2 = cy1 + (gdouble) ph;
draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[0],p[1]);
draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[1],p[2]);
draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[2],p[3]);
draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[3],p[0]);
draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[4],p[5]);
draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[5],p[6]);
draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[6],p[7]);
draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[7],p[4]);
draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[0],p[4]);
draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[1],p[5]);
draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[2],p[6]);
draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[3],p[7]);
cairo_set_line_width (cr, 3.0);
cairo_stroke_preserve (cr);
cairo_set_line_width (cr, 1.0);
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
cairo_stroke (cr);
}
static void
draw_wireframe_cylinder (cairo_t *cr,
gint startx,
gint starty,
gint pw,
gint ph)
{
PikaVector3 p[2*8], a, axis, scale;
gint i;
gdouble cx1, cy1, cx2, cy2;
gfloat m[16], l, angle;
cairo_rectangle (cr, startx, starty, pw, ph);
cairo_clip (cr);
/* Compute wireframe points */
/* ======================== */
init_compute ();
scale = mapvals.scale;
pika_vector3_mul (&scale, 0.5);
l = mapvals.cylinder_length / 2.0;
angle = 0;
pika_vector3_set (&axis, 0.0, 1.0, 0.0);
for (i = 0; i < 8; i++)
{
rotatemat (angle, &axis, m);
pika_vector3_set (&a, mapvals.cylinder_radius, 0.0, 0.0);
vecmulmat (&p[i], &a, m);
p[i+8] = p[i];
p[i].y += l;
p[i+8].y -= l;
angle += 360.0 / 8.0;
}
/* Rotate and translate points */
/* =========================== */
for (i = 0; i < 16; i++)
{
vecmulmat (&a, &p[i], rotmat);
pika_vector3_add (&p[i], &a, &mapvals.position);
}
/* Draw the box */
/* ============ */
cx1 = (gdouble) startx;
cy1 = (gdouble) starty;
cx2 = cx1 + (gdouble) pw;
cy2 = cy1 + (gdouble) ph;
for (i = 0; i < 7; i++)
{
draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[i],p[i+1]);
draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[i+8],p[i+9]);
draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[i],p[i+8]);
}
draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[7],p[0]);
draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[15],p[8]);
cairo_set_line_width (cr, 3.0);
cairo_stroke_preserve (cr);
cairo_set_line_width (cr, 1.0);
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
cairo_stroke (cr);
}

View File

@ -0,0 +1,26 @@
#ifndef __MAPOBJECT_PREVIEW_H__
#define __MAPOBJECT_PREVIEW_H__
#define PREVIEW_WIDTH 200
#define PREVIEW_HEIGHT 200
#define WIRESIZE 16
/* Externally visible variables */
/* ============================ */
extern gdouble mat[3][4];
extern gint lightx,lighty;
/* Externally visible functions */
/* ============================ */
void compute_preview_image (void);
gboolean preview_draw (GtkWidget *widget,
cairo_t *cr);
gint check_light_hit (gint xpos,
gint ypos);
void update_light (gint xpos,
gint ypos);
#endif /* __MAPOBJECT_PREVIEW_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
#ifndef __MAPOBJECT_SHADE_H__
#define __MAPOBJECT_SHADE_H__
typedef PikaRGB (* get_ray_color_func) (PikaVector3 *pos);
extern get_ray_color_func get_ray_color;
PikaRGB get_ray_color_plane (PikaVector3 *pos);
PikaRGB get_ray_color_sphere (PikaVector3 *pos);
PikaRGB get_ray_color_box (PikaVector3 *pos);
PikaRGB get_ray_color_cylinder (PikaVector3 *pos);
void compute_bounding_box (void);
void vecmulmat (PikaVector3 *u,
PikaVector3 *v,
gfloat m[16]);
void rotatemat (gfloat angle,
PikaVector3 *v,
gfloat m[16]);
void transpose_mat (gfloat m[16]);
void matmul (gfloat a[16],
gfloat b[16],
gfloat c[16]);
void ident_mat (gfloat m[16]);
#endif /* __MAPOBJECT_SHADE_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
#ifndef __MAPOBJECT_UI_H__
#define __MAPOBJECT_UI_H__
/* Externally visible variables */
/* ============================ */
extern GtkWidget *previewarea;
/* Externally visible functions */
/* ============================ */
gboolean main_dialog (PikaDrawable *drawable);
#endif /* __MAPOBJECT_UI_H__ */

View File

@ -0,0 +1,38 @@
plugin_name = 'map-object'
plugin_sources = [
'arcball.c',
'map-object-apply.c',
'map-object-icons.c',
'map-object-image.c',
'map-object-main.c',
'map-object-preview.c',
'map-object-shade.c',
'map-object-ui.c',
lighting_icon_sources,
]
if platform_windows
plugin_sources += windows.compile_resources(
pika_plugins_rc,
args: [
'--define', 'ORIGINALFILENAME_STR="@0@"'.format(plugin_name+'.exe'),
'--define', 'INTERNALNAME_STR="@0@"' .format(plugin_name),
'--define', 'TOP_SRCDIR="@0@"' .format(meson.project_source_root()),
],
include_directories: [
rootInclude, appInclude,
],
)
endif
executable(plugin_name,
plugin_sources,
dependencies: [
libpikaui_dep,
math,
],
install: true,
install_dir: pikaplugindir / 'plug-ins' / plugin_name,
)