static VALUE rb_gimp_rgb_composite_replace (VALUE self, VALUE other, VALUE mode) { gimp_rgb_composite(rb2GimpRGBPtr(self), rb2GimpRGBPtr(other), (GimpRGBCompositeMode)NUM2INT(mode)); return self; }
static VALUE rb_gimp_rgb_composite (VALUE self, VALUE other, VALUE mode) { GimpRGB color = rb2GimpRGB(self); gimp_rgb_composite(&color, rb2GimpRGBPtr(other), (GimpRGBCompositeMode)NUM2INT(mode)); return GimpRGB2rb(&color); }
GimpRGB get_ray_color_plane (GimpVector3 *pos) { GimpRGB color = background; static gint inside = FALSE; static GimpVector3 ray, spos; static gdouble vx, vy; /* Construct a line from our VP to the point */ /* ========================================= */ gimp_vector3_sub (&ray, pos, &mapvals.viewpoint); gimp_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); gimp_rgb_clamp (&color); } } if (mapvals.transparent_background == FALSE && color.a < 1.0) { gimp_rgb_composite (&color, &background, GIMP_RGB_COMPOSITE_BEHIND); } return color; }
static void compute_preview (gint startx, gint starty, gint w, gint h) { gint xcnt, ycnt, f1, f2; gdouble imagex, imagey; gint32 index = 0; GimpRGB color; GimpRGB lightcheck, darkcheck; GimpVector3 pos; get_ray_func ray_func; if (xpostab_size != w) { if (xpostab) { g_free (xpostab); xpostab = NULL; } } if (!xpostab) { xpostab = g_new (gdouble, w); xpostab_size = w; } if (ypostab_size != h) { if (ypostab) { g_free (ypostab); ypostab = NULL; } } if (!ypostab) { ypostab = g_new (gdouble, h); ypostab_size = h; } for (xcnt = 0; xcnt < w; xcnt++) xpostab[xcnt] = (gdouble) width *((gdouble) xcnt / (gdouble) w); for (ycnt = 0; ycnt < h; ycnt++) ypostab[ycnt] = (gdouble) height *((gdouble) ycnt / (gdouble) h); precompute_init (width, height); gimp_rgba_set (&lightcheck, GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT, 1.0); gimp_rgba_set (&darkcheck, GIMP_CHECK_DARK, GIMP_CHECK_DARK, GIMP_CHECK_DARK, 1.0); if (mapvals.bump_mapped == TRUE && mapvals.bumpmap_id != -1) { gimp_pixel_rgn_init (&bump_region, gimp_drawable_get (mapvals.bumpmap_id), 0, 0, width, height, FALSE, FALSE); } imagey = 0; if (mapvals.previewquality) ray_func = get_ray_color; else ray_func = get_ray_color_no_bilinear; if (mapvals.env_mapped == TRUE && mapvals.envmap_id != -1) { env_width = gimp_drawable_width (mapvals.envmap_id); env_height = gimp_drawable_height (mapvals.envmap_id); gimp_pixel_rgn_init (&env_region, gimp_drawable_get (mapvals.envmap_id), 0, 0, env_width, env_height, FALSE, FALSE); if (mapvals.previewquality) ray_func = get_ray_color_ref; else ray_func = get_ray_color_no_bilinear_ref; } for (ycnt = 0; ycnt < PREVIEW_HEIGHT; ycnt++) { for (xcnt = 0; xcnt < PREVIEW_WIDTH; xcnt++) { if ((ycnt >= starty && ycnt < (starty + h)) && (xcnt >= startx && xcnt < (startx + w))) { imagex = xpostab[xcnt - startx]; imagey = ypostab[ycnt - starty]; pos = int_to_posf (imagex, imagey); if (mapvals.bump_mapped == TRUE && mapvals.bumpmap_id != -1 && xcnt == startx) { pos_to_float (pos.x, pos.y, &imagex, &imagey); precompute_normals (0, width, RINT (imagey)); } color = (*ray_func) (&pos); 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 gimp_rgb_composite (&color, &lightcheck, GIMP_RGB_COMPOSITE_BEHIND); } else { if (color.a == 0.0) color = darkcheck; else gimp_rgb_composite (&color, &darkcheck, GIMP_RGB_COMPOSITE_BEHIND); } } gimp_rgb_get_uchar (&color, preview_rgb_data + index, preview_rgb_data + index + 1, preview_rgb_data + index + 2); index += 3; imagex++; } else { preview_rgb_data[index++] = 200; preview_rgb_data[index++] = 200; preview_rgb_data[index++] = 200; } } } }
GimpRGB get_ray_color_box (GimpVector3 *pos) { GimpVector3 lvp, ldir, vp, p, dir, ns, nn; GimpRGB color, color2; gfloat m[16]; gint i; FaceIntersectInfo face_intersect[2]; color = background; vp = mapvals.viewpoint; p = *pos; /* Translate viewpoint so that the box has its origin */ /* at its lower left corner. */ /* ================================================== */ vp.x = vp.x - mapvals.position.x; vp.y = vp.y - mapvals.position.y; vp.z = vp.z - mapvals.position.z; p.x = p.x - mapvals.position.x; p.y = p.y - mapvals.position.y; p.z = p.z - mapvals.position.z; /* Compute direction */ /* ================= */ gimp_vector3_sub (&dir, &p, &vp); gimp_vector3_normalize (&dir); /* Compute inverse of rotation matrix and apply it to */ /* the viewpoint and direction. This transforms the */ /* observer into the local coordinate system of the box */ /* ==================================================== */ memcpy (m, rotmat, sizeof (gfloat) * 16); transpose_mat (m); vecmulmat (&lvp, &vp, m); vecmulmat (&ldir, &dir, m); /* Ok. Now the observer is in the space where the box is located */ /* with its lower left corner at the origin and its axis aligned */ /* to the cartesian basis. Check if the transformed ray hits it. */ /* ============================================================= */ face_intersect[0].t = 1000000.0; face_intersect[1].t = 1000000.0; if (intersect_box (mapvals.scale, lvp, ldir, face_intersect) == TRUE) { /* We've hit the box. Transform the hit points and */ /* normals back into the world coordinate system */ /* =============================================== */ for (i = 0; i < 2; i++) { vecmulmat (&ns, &face_intersect[i].s, rotmat); vecmulmat (&nn, &face_intersect[i].n, rotmat); ns.x = ns.x + mapvals.position.x; ns.y = ns.y + mapvals.position.y; ns.z = ns.z + mapvals.position.z; face_intersect[i].s = ns; face_intersect[i].n = nn; } color = get_box_image_color (face_intersect[0].face, face_intersect[0].u, face_intersect[0].v); /* 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 (&face_intersect[0].s, &mapvals.viewpoint, &face_intersect[0].n, &mapvals.lightsource.position, &color, &mapvals.lightsource.color, mapvals.lightsource.type); gimp_rgb_clamp (&color); color2 = get_box_image_color (face_intersect[1].face, face_intersect[1].u, face_intersect[1].v); /* Make the normal point inwards */ /* ============================= */ gimp_vector3_mul (&face_intersect[1].n, -1.0); color2 = phong_shade (&face_intersect[1].s, &mapvals.viewpoint, &face_intersect[1].n, &mapvals.lightsource.position, &color2, &mapvals.lightsource.color, mapvals.lightsource.type); gimp_rgb_clamp (&color2); if (mapvals.transparent_background == FALSE && color2.a < 1.0) { gimp_rgb_composite (&color2, &background, GIMP_RGB_COMPOSITE_BEHIND); } /* Compute a mix of the first and second colors */ /* ============================================ */ gimp_rgb_composite (&color, &color2, GIMP_RGB_COMPOSITE_NORMAL); gimp_rgb_clamp (&color); } else if (color.a != 0.0 && mapvals.lightsource.type != NO_LIGHT) { color = phong_shade (&face_intersect[0].s, &mapvals.viewpoint, &face_intersect[0].n, &mapvals.lightsource.position, &color, &mapvals.lightsource.color, mapvals.lightsource.type); gimp_rgb_clamp (&color); } } else { if (mapvals.transparent_background == TRUE) gimp_rgb_set_alpha (&color, 0.0); } return color; }
GimpRGB get_ray_color_sphere (GimpVector3 *pos) { GimpRGB color = background; static GimpRGB color2; static gint inside = FALSE; static GimpVector3 normal, ray, spos1, spos2; static gdouble vx, vy; /* Check if ray is within the bounding box */ /* ======================================= */ if (pos->x<bx1 || pos->x>bx2 || pos->y<by1 || pos->y>by2) return color; /* Construct a line from our VP to the point */ /* ========================================= */ gimp_vector3_sub (&ray, pos, &mapvals.viewpoint); gimp_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 */ /* ======================================== */ gimp_vector3_sub (&normal, &spos1, &mapvals.position); gimp_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); gimp_rgb_clamp (&color); gimp_vector3_sub (&normal, &spos2, &mapvals.position); gimp_vector3_normalize (&normal); sphere_to_image (&normal, &vx, &vy); color2 = get_image_color (vx, vy, &inside); /* Make the normal point inwards */ /* ============================= */ gimp_vector3_mul (&normal, -1.0); color2 = phong_shade (&spos2, &mapvals.viewpoint, &normal, &mapvals.lightsource.position, &color2, &mapvals.lightsource.color, mapvals.lightsource.type); gimp_rgb_clamp (&color2); /* Compute a mix of the first and second colors */ /* ============================================ */ gimp_rgb_composite (&color, &color2, GIMP_RGB_COMPOSITE_NORMAL); gimp_rgb_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); gimp_rgb_clamp (&color); } } if (mapvals.transparent_background == FALSE && color.a < 1.0) { gimp_rgb_composite (&color, &background, GIMP_RGB_COMPOSITE_BEHIND); } return color; }
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; GimpVector3 p1, p2; GimpRGB color; GimpRGB lightcheck, darkcheck; 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; 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) { gimp_rgba_set (&background, 0.0, 0.0, 0.0, 0.0); } else { gimp_context_get_background (&background); gimp_rgb_set_alpha (&background, 1.0); } gimp_rgba_set (&lightcheck, GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT, 1.0); gimp_rgba_set (&darkcheck, GIMP_CHECK_DARK, GIMP_CHECK_DARK, GIMP_CHECK_DARK, 1.0); gimp_vector3_set (&p2, -1.0, -1.0, 0.0); for (ycnt = 0; ycnt < ph; ycnt++) { 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 gimp_rgb_composite (&color, &lightcheck, GIMP_RGB_COMPOSITE_BEHIND); } else { if (color.a == 0.0) color = darkcheck; else gimp_rgb_composite (&color, &darkcheck, GIMP_RGB_COMPOSITE_BEHIND); } } gimp_rgb_get_uchar (&color, preview_rgb_data + index, preview_rgb_data + index + 1, preview_rgb_data + index + 2); index += 3; } } }