mirror of https://github.com/GNOME/gimp.git
277 lines
8.0 KiB
C
277 lines
8.0 KiB
C
/******************************************************/
|
|
/* Apply mapping and shading on the whole input image */
|
|
/******************************************************/
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include <libgimp/gimp.h>
|
|
|
|
#include <gck/gck.h>
|
|
|
|
#include "mapobject_main.h"
|
|
#include "mapobject_image.h"
|
|
#include "mapobject_shade.h"
|
|
|
|
/*************/
|
|
/* Main loop */
|
|
/*************/
|
|
|
|
gdouble imat[4][4];
|
|
gfloat rotmat[16], a[16], b[16];
|
|
|
|
void init_compute(void)
|
|
{
|
|
gint i;
|
|
|
|
switch (mapvals.maptype)
|
|
{
|
|
case MAP_SPHERE:
|
|
|
|
/* Rotate the equator/northpole axis */
|
|
/* ================================= */
|
|
|
|
gimp_vector3_set(&mapvals.firstaxis,0.0,0.0,-1.0);
|
|
gimp_vector3_set(&mapvals.secondaxis,0.0,1.0,0.0);
|
|
|
|
gimp_vector3_rotate(&mapvals.firstaxis,gimp_deg_to_rad(mapvals.alpha),
|
|
gimp_deg_to_rad(mapvals.beta),gimp_deg_to_rad(mapvals.gamma));
|
|
gimp_vector3_rotate(&mapvals.secondaxis,gimp_deg_to_rad(mapvals.alpha),
|
|
gimp_deg_to_rad(mapvals.beta),gimp_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 */
|
|
/* ===================== */
|
|
|
|
gimp_vector3_set(&mapvals.firstaxis, 1.0,0.0,0.0);
|
|
gimp_vector3_set(&mapvals.secondaxis,0.0,1.0,0.0);
|
|
gimp_vector3_set(&mapvals.normal,0.0,0.0,1.0);
|
|
|
|
gimp_vector3_rotate(&mapvals.firstaxis,gimp_deg_to_rad(mapvals.alpha),
|
|
gimp_deg_to_rad(mapvals.beta),gimp_deg_to_rad(mapvals.gamma));
|
|
gimp_vector3_rotate(&mapvals.secondaxis,gimp_deg_to_rad(mapvals.alpha),
|
|
gimp_deg_to_rad(mapvals.beta),gimp_deg_to_rad(mapvals.gamma));
|
|
|
|
mapvals.normal=gimp_vector3_cross_product(&mapvals.firstaxis,&mapvals.secondaxis);
|
|
|
|
if (mapvals.normal.z<0.0)
|
|
gimp_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:
|
|
gimp_vector3_set(&mapvals.firstaxis, 1.0,0.0,0.0);
|
|
gimp_vector3_set(&mapvals.secondaxis,0.0,1.0,0.0);
|
|
gimp_vector3_set(&mapvals.normal,0.0,0.0,1.0);
|
|
|
|
get_ray_color=get_ray_color_box;
|
|
|
|
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] = gimp_drawable_get (mapvals.boxmap_id[i]);
|
|
|
|
gimp_pixel_rgn_init (&box_regions[i], box_drawables[i],
|
|
0, 0,
|
|
box_drawables[i]->width, box_drawables[i]->height,
|
|
FALSE, FALSE);
|
|
}
|
|
break;
|
|
case MAP_CYLINDER:
|
|
get_ray_color=get_ray_color_cylinder;
|
|
|
|
gimp_vector3_set(&mapvals.firstaxis, 1.0,0.0,0.0);
|
|
gimp_vector3_set(&mapvals.secondaxis,0.0,1.0,0.0);
|
|
gimp_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] = gimp_drawable_get (mapvals.cylindermap_id[i]);
|
|
|
|
gimp_pixel_rgn_init (&cylinder_regions[i], cylinder_drawables[i],
|
|
0, 0,
|
|
cylinder_drawables[i]->width, cylinder_drawables[i]->height,
|
|
FALSE, FALSE);
|
|
}
|
|
break;
|
|
}
|
|
|
|
max_depth=(gint)mapvals.maxdepth;
|
|
}
|
|
|
|
void render(gdouble x,gdouble y,GckRGB *col)
|
|
{
|
|
GimpVector3 pos;
|
|
|
|
pos.x=x/(gdouble)width;
|
|
pos.y=y/(gdouble)height;
|
|
pos.z=0.0;
|
|
|
|
*col=get_ray_color(&pos);
|
|
}
|
|
|
|
void show_progress(gint min,gint max,gint curr)
|
|
{
|
|
gimp_progress_update((gdouble)curr/(gdouble)max);
|
|
}
|
|
|
|
/**************************************************/
|
|
/* Performs map-to-sphere on the whole input image */
|
|
/* and updates or creates a new GIMP image. */
|
|
/**************************************************/
|
|
|
|
void compute_image(void)
|
|
{
|
|
gint xcount,ycount;
|
|
GckRGB color;
|
|
glong progress_counter=0;
|
|
GimpVector3 p;
|
|
gint32 new_image_id=-1,new_layer_id=-1;
|
|
|
|
init_compute();
|
|
|
|
if (mapvals.create_new_image==TRUE || (mapvals.transparent_background==TRUE
|
|
&& input_drawable->bpp!=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);
|
|
|
|
switch (mapvals.maptype)
|
|
{
|
|
case MAP_PLANE:
|
|
gimp_progress_init("Map to object (plane)");
|
|
break;
|
|
case MAP_SPHERE:
|
|
gimp_progress_init("Map to object (sphere)");
|
|
break;
|
|
case MAP_BOX:
|
|
gimp_progress_init("Map to object (box)");
|
|
break;
|
|
case MAP_CYLINDER:
|
|
gimp_progress_init("Map to object (cylinder)");
|
|
break;
|
|
}
|
|
|
|
if (mapvals.antialiasing==FALSE)
|
|
{
|
|
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);
|
|
if ((progress_counter++ % width)==0)
|
|
gimp_progress_update((gdouble)progress_counter/(gdouble)maxcounter);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
gck_adaptive_supersample_area(0,0,width-1,height-1,max_depth,mapvals.pixeltreshold,
|
|
render,poke,show_progress);
|
|
|
|
/* Update the region */
|
|
/* ================= */
|
|
|
|
gimp_drawable_flush (output_drawable);
|
|
gimp_drawable_merge_shadow (output_drawable->id, 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);
|
|
}
|
|
}
|
|
|