This is disc.c in view mode; [Download] [Up]
/* * disc.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 "object.h" #include "disc.h" static Methods *iDiscMethods = NULL; static char discName[] = "disc"; unsigned long DiscTests, DiscHits; Disc * DiscCreate(r, pos, norm) Float r; Vector *pos, *norm; { Disc *disc; /* Pointer to new disc. */ if (r < EPSILON) { RLerror(RL_WARN, "Degenerate disc.\n"); /* * Don't create this primitive. */ return (Disc *)NULL; } if (VecNormalize(norm) == 0.) { RLerror(RL_WARN, "Degenerate disc normal.\n"); return (Disc *)NULL; } /* * Allocate new Disc. */ disc = (Disc *)Malloc(sizeof(Disc)); /* * Initialize new disc. * We store the square of the radius to save us a sqrt(). */ disc->radius = r*r; disc->pos = *pos; disc->norm = *norm; /* * Compute plane constant. */ disc->d = dotp(pos, norm); /* * Allocate new primitive */ return disc; } Methods * DiscMethods() { if (iDiscMethods == (Methods *)NULL) { iDiscMethods = MethodsCreate(); iDiscMethods->name = DiscName; iDiscMethods->create = (ObjCreateFunc *)DiscCreate; iDiscMethods->methods = DiscMethods; iDiscMethods->intersect = DiscIntersect; iDiscMethods->normal = DiscNormal; iDiscMethods->uv = DiscUV; iDiscMethods->bounds = DiscBounds; iDiscMethods->stats = DiscStats; iDiscMethods->checkbounds = FALSE; iDiscMethods->closed = FALSE; } return iDiscMethods; } int DiscIntersect(disc, ray, mindist, maxdist) Disc *disc; Ray *ray; Float mindist, *maxdist; { Vector hit; Float denom, dist; DiscTests++; denom = dotp(&disc->norm, &ray->dir); if (fabs(denom) < EPSILON) /* Edge-on intersection */ return FALSE; dist = (disc->d - dotp(&disc->norm, &ray->pos)) / denom; if (dist < mindist || dist > *maxdist) /* Too close or too far */ return FALSE; /* * Find difference between point of intersection and center of disc. */ VecAddScaled(ray->pos, dist, ray->dir, &hit); VecSub(hit, disc->pos, &hit); /* * If hit point is <= disc->radius from center, we've hit the disc. */ if (dotp(&hit, &hit) <= disc->radius) { *maxdist = dist; DiscHits++; return TRUE; } return FALSE; } int DiscNormal(disc, pos, nrm, gnrm) Disc *disc; Vector *pos, *nrm, *gnrm; { *gnrm = *nrm = disc->norm; return FALSE; } void DiscUV(disc, pos, norm, uv, dpdu, dpdv) Disc *disc; Vector *pos, *norm, *dpdu, *dpdv; Vec2d *uv; { Float dist, val; dist = (pos->x - disc->pos.x) * (pos->x - disc->pos.x) + (pos->y - disc->pos.y) * (pos->y - disc->pos.y) + (pos->z - disc->pos.z) * (pos->z - disc->pos.z); if (dist < EPSILON) { uv->u = uv->v = 0.; return; } dist = sqrt(dist); uv->v = dist / sqrt(disc->radius); /* should store r and r*r */ val = pos->x / dist; if (fabs(val) > 1.) uv->u = 0.5; else { uv->u = acos(val) / TWOPI; if (pos->y < 0.) uv->u = 1. - uv->u; } if (dpdu) { VecSub(*pos, disc->pos, dpdv); /* dpdu = dpdv X norm */ VecCross(dpdv, norm, dpdu); } } void DiscBounds(disc, bounds) Disc *disc; Float bounds[2][3]; { Float extent, rad; rad = sqrt(disc->radius); /* * Project disc along each of X, Y and Z axes. */ extent = rad * sqrt(1. - disc->norm.x * disc->norm.x); bounds[LOW][X] = disc->pos.x - extent; bounds[HIGH][X] = disc->pos.x + extent; extent = rad * sqrt(1. - disc->norm.y * disc->norm.y); bounds[LOW][Y] = disc->pos.y - extent; bounds[HIGH][Y] = disc->pos.y + extent; extent = rad * sqrt(1. - disc->norm.z * disc->norm.z); bounds[LOW][Z] = disc->pos.z - extent; bounds[HIGH][Z] = disc->pos.z + extent; } char * DiscName() { return discName; } void DiscStats(tests, hits) unsigned long *tests, *hits; { *tests = DiscTests; *hits = DiscHits; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.