This is surfshade.c in view mode; [Download] [Up]
/* * surfshade.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 "libobj/object.h" #include "surface.h" /* * Compute surface properties from given hitlist * Returns TRUE if ray is entering object, FALSE otherwise. */ int ComputeSurfProps(hitlist, ray, pos, norm, gnorm, surf, smooth) HitList *hitlist; /* Hit information (path through DAG) */ Ray *ray; /* Ray in world space */ Vector *pos; /* Intersection point */ Vector *norm, *gnorm; /* shading normal, geometric normal (return values) */ Surface *surf; /* Copy of surface to use (return value) */ int *smooth; { HitNode *hp; int i; Ray rtmp; Object *prim, *obj; Surface *stmp; Float k, kp; int texturing, transforming, entering; Trans prim2model, world2model; hp = hitlist->data; prim = hp->obj; /* * Compute point of intersection in "primitive space". */ VecAddScaled(hp->ray.pos, hp->dist, hp->ray.dir, pos); /* * Find normal to primitive at point of intersection. */ *smooth = PrimNormal(prim, pos, norm, gnorm); texturing = transforming = FALSE; /* * Walk down hit list, constructing world<-->primitive transformation * and determining if we need to perform texture mapping. * The last node is the World node, which cannot be textured or * transformed, so we skip it. */ for (i = 0, hp = hitlist->data; i < hitlist->nodes -1; hp++, i++) { obj = hp->obj; if (obj->trans) { /* * Here we're actually computing prim2world. * When finished, we invert it. */ if (transforming) TransCompose(obj->trans, &world2model, &world2model); else TransCopy(obj->trans, &world2model); transforming = TRUE; } if (obj->texture) texturing = TRUE; } /* * Get surface to use via the application-provided function. */ stmp = GetShadingSurf(hitlist); if (stmp == (Surface *)NULL) RLerror(RL_PANIC, "GetShadingSurf returned NULL!\n"); /* * Make a copy so it may be modified via texturing. */ *surf = *stmp; /* * Determine if we're entering or exiting the surface, * flipping surface normals if necessary. */ k = dotp(&hitlist->data[0].ray.dir, norm); if (*smooth) { /* * If gnorm and shading norm differ and * their dot products with the ray have * different signs, use the geometric normal * instead, ala Snyder & Barr's paper. */ kp = dotp(&hitlist->data[0].ray.dir, gnorm); if (k <= 0. && kp > 0. || k >= 0. && kp < 0.) k = kp; } if (k > 0.) { /* flip normals */ VecScale(-1., *gnorm, gnorm); VecScale(-1., *norm, norm); /* * Normal indicates that we're exiting. * Only set entering to TRUE if csg has indicated * that the ray is, indeed, entering. */ entering = (hitlist->data[0].enter == ENTERING); } else { /* * Normal indicates that we're entering. * Set entering flag as such unless csg has * told us that we're exiting. */ entering = !(hitlist->data[0].enter == EXITING); } /* * If there are no transformations, then world2model is identity. */ if (!transforming) TransInit(&world2model); /* * If we're not performing texturing, we simply need to compute * the normal and point of intersection to world space. */ if (!texturing) { /* * At this point 'world2model' is really 'prim2world'. */ if (transforming) { NormalTransform(norm, &world2model.itrans); NormalTransform(gnorm, &world2model.itrans); VecAddScaled(ray->pos, hitlist->data[hitlist->nodes -1].dist, ray->dir, pos); } return entering; } /* * world2model currently transforms from primitive to world space. * Invert it to get transformation from world to primitive space. */ TransInvert(&world2model, &world2model); TransInit(&prim2model); rtmp = hitlist->data[0].ray; /* * Walk down hitlist. */ for (hp = hitlist->data, i = 0; i < hitlist->nodes -1; i++, hp++) { obj = hp->obj; if (obj->trans) { NormalTransform(norm, &obj->trans->itrans); if (texturing) { /* * Compose prim<-->model and world<-->model * with current transformation. */ TransCompose(obj->trans, &prim2model, &prim2model); TransCompose(obj->trans, &world2model, &world2model); /* * Transform point and ray to model space. */ PointTransform(pos, &obj->trans->trans); (void)RayTransform(&rtmp, &obj->trans->trans); } } /* * Apply textures */ if (obj->texture) TextApply(obj->texture, prim, &rtmp, pos, norm, gnorm, surf, &prim2model, &world2model); } return entering; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.