This is imagetext.c in view mode; [Download] [Up]
/* * imagetext.c * * Copyright (C) 1989, 1991, Craig E. Kolb * All rights reserved. * * This software may be freely copied, modified, and redistributed * provided that this copyright notice is preserved on all copies. * * You may not distribute this software, in whole or in part, as part of * any commercial product without the express consent of the authors. * * There is no warranty or other guarantee of fitness of this software * for any purpose. It is provided solely "as is". * * $Id$ * * $Log$ */ #include "texture.h" #include "libimage/image.h" #include "imagetext.h" #define INTERP(v) (text->lo + (v)*(text->hi - text->lo)) /* * Create Image texture. * Image texture has so many options that there's usually no * nice way to parse without resorting to additional keywords. * Thus the ImageTextCreate routine only reads the image to be used; * all but ->component must be set by hand. The routine * ImageTextSetComponent is provided to set the component and * ensure that the image being used is appropriate. */ ImageText * ImageTextCreate(imagefile) char *imagefile; { ImageText *text; text = (ImageText *)Calloc(1, sizeof(ImageText)); text->component = COLOR; /* texture all colors by default*/ /* * Only apply one copy of the texture by default */ text->tileu = text->tilev = 0; text->mapping = UVMappingCreate(); text->image = ImageRead(imagefile); return text; } /* * Set image texture to apply to given component, * ensuring that the image that is being used is compatible. */ void ImageTextSetComponent(text, component) ImageText *text; int component; { switch (component) { case COLOR: /* usual case, texture on amb, diff, spec */ case AMBIENT: case DIFFUSE: case SPECULAR: /* all of the above can use 1 or 3 channel images */ if (text->image->chan != 1 && text->image->chan != 3) { RLerror(RL_ABORT, "Image %s must have 1 or 3 channels\n", text->image->filename); } break; case SPECPOW: case REFLECT: case TRANSP: case BUMP: /* the above need 1 channel images */ if (text->image->chan != 1) { RLerror(RL_ABORT, "Image %s must have 1 channel\n", text->image->filename); } break; } text->component = component; } void ImageTextApply(text, prim, ray, pos, norm, gnorm, surf) ImageText *text; Object *prim; Ray *ray; Vector *pos, *norm, *gnorm; Surface *surf; { Float fx, fy; Float outval[4], outval_u[4], outval_v[4]; Float u, v; Surface tmpsurf; int ix, iy; int rchan, gchan, bchan; Vector dpdu, dpdv, ntmp; /* * First, find the floating point location in image coords. * Then set ix, iy to the integer location in image coords and * use fx, fy to represent the subpixel position. */ if (text->component == BUMP) TextToUV(text->mapping, prim, pos, gnorm, &u, &v, &dpdu, &dpdv); else TextToUV(text->mapping, prim, pos, gnorm, &u, &v, (Vector *)NULL, (Vector *)NULL); /* * Handle tiling at this point. */ if (TileValue(text->tileu, text->tilev, u, v)) return; u -= floor(u); v -= floor(v); fx = u * (Float) text->image->width; fy = v * (Float) text->image->height; ix = fx; iy = fy; fx = fx - (Float) ix; fy = fy - (Float) iy; if (text->image->has_alpha) { /* Alpha channel is 0 */ rchan = 1; gchan = 2; bchan = 3; } else { rchan = 0; gchan = 1; bchan = 2; } if (text->image->chan == 1) { gchan = rchan; bchan = rchan; } ImageIndex(text->image, ix, iy, fx, fy, text->smooth, outval); /* * escape when alpha is zero, 'cause there is no change */ if (text->image->has_alpha && (outval[0] < 0.001)) return; if (text->component != COLOR || text->surf == (Surface *)NULL) { tmpsurf = *surf; } else { tmpsurf = *text->surf; } switch (text->component) { case COLOR: /* amb, diff, spec */ tmpsurf.spec.r *= outval[rchan]; tmpsurf.spec.g *= outval[gchan]; tmpsurf.spec.b *= outval[bchan]; tmpsurf.diff.r *= outval[rchan]; tmpsurf.diff.g *= outval[gchan]; tmpsurf.diff.b *= outval[bchan]; tmpsurf.amb.r *= outval[rchan]; tmpsurf.amb.g *= outval[gchan]; tmpsurf.amb.b *= outval[bchan]; break; case AMBIENT: /* ambient */ tmpsurf.amb.r = INTERP(outval[rchan]); tmpsurf.amb.g = INTERP(outval[gchan]); tmpsurf.amb.b = INTERP(outval[bchan]); break; case DIFFUSE: /* diffuse */ tmpsurf.diff.r = INTERP(outval[rchan]); tmpsurf.diff.g = INTERP(outval[gchan]); tmpsurf.diff.b = INTERP(outval[bchan]); break; case SPECULAR: /* specular */ tmpsurf.spec.r = INTERP(outval[rchan]); tmpsurf.spec.g = INTERP(outval[gchan]); tmpsurf.spec.b = INTERP(outval[bchan]); break; case SPECPOW: /* specpow */ tmpsurf.coef = INTERP(outval[rchan]); break; case REFLECT: /* reflect */ tmpsurf.refl = INTERP(outval[rchan]); break; case TRANSP: /* refract */ tmpsurf.transp = INTERP(outval[rchan]); break; case BUMP: /* bump map */ ImageIndex(text->image, (ix == text->image->width - 1) ? 0 : ix+1, iy, fx, fy, text->smooth, outval_u); ImageIndex(text->image, ix, (iy == text->image->height - 1) ? 0 : iy+1, fx, fy, text->smooth, outval_v); MakeBump(norm, &dpdu, &dpdv, INTERP(outval_u[rchan] - outval[rchan]), INTERP(outval_v[rchan] - outval[rchan])); return; } if (text->image->has_alpha && (outval[0] < 0.999)) { /* * image partial coverage means blend surf and text->surf */ SurfaceBlend(surf, &tmpsurf, 1. - outval[0], outval[0]); } else { /* * image full coverage means use text->surf */ *surf = tmpsurf; } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.