Mapping * SphereMappingCreate( Vector *center, Vector *norm, Vector *uaxis) { Mapping *res; res = (Mapping *)Malloc(sizeof(Mapping)); res->flags = OBJSPACE; res->method = SphereMapping; if (center) res->center = *center; else res->center.x = res->center.y = res->center.z = 0.; if (norm && uaxis) { res->norm = *norm; if (VecNormalize(&res->norm) == 0.) { RLerror(RL_ABORT, "Degenerate mapping vector.\n"); return (Mapping *)NULL; } if (VecNormCross(norm, uaxis, &res->vaxis) == 0.) { RLerror(RL_ABORT, "Degenerate mapping vector.\n"); return (Mapping *)NULL; } (void)VecNormCross(&res->vaxis, norm, &res->uaxis); } else { res->norm.x = res->norm.y = res->uaxis.y = res->uaxis.z = res->vaxis.x = res->vaxis.z = 0.; res->norm.z = res->uaxis.x = res->vaxis.y = 1.; } return res; }
void OpenGLDrawCone(VECTOR *size, ULONG flags) { VECTOR bottom,bottom1, centertop; int i; VECTOR norm, e0,e1; if(!(flags & OBJECT_OPENBOTTOM)) { glEnable(GL_CULL_FACE); glBegin(GL_TRIANGLE_FAN); glNormal3f(0.f, -1.f, 0.f); glVertex3f(0.f, 0.f, 0.f); for(i = 0; i <= 360; i += OGL_CONE_DIVS) glVertex3f(sin(i*PI_180)*size->x, 0.f, cos(i*PI_180)*size->z); glEnd(); } glBegin(GL_TRIANGLE_FAN); glNormal3f(0.f, 1.f, 0.f); SetVector(¢ertop, 0.f, size->y, 0.f); glVertex3fv((GLfloat*)¢ertop); SetVector(&bottom, 0.f, 0.f, size->z); SetVector(&bottom1, sin((360-OGL_CONE_DIVS)*PI_180)*size->x, 0.f, cos((360-OGL_CONE_DIVS)*PI_180)*size->z); VecSub(¢ertop, &bottom, &e0); VecSub(¢ertop, &bottom1, &e1); VecNormCross(&e0, &e1, &norm); glNormal3fv((GLfloat*)&norm); glVertex3fv((GLfloat*)&bottom); for(i = 360-OGL_CONE_DIVS; i >= -OGL_CONE_DIVS; i -= OGL_CONE_DIVS) { bottom = bottom1; SetVector(&bottom1, sin(i*PI_180)*size->x, 0.f, cos(i*PI_180)*size->z); VecSub(¢ertop, &bottom, &e0); VecSub(¢ertop, &bottom1, &e1); VecNormCross(&e0, &e1, &norm); glNormal3fv((GLfloat*)&norm); glVertex3fv((GLfloat*)&bottom); } glEnd(); if(!(flags & OBJECT_OPENBOTTOM)) glDisable(GL_CULL_FACE); }
/************* * DESCRIPTION: Initialize Camera (MUST be called if parameters changed) * INPUT: none * OUTPUT: none *************/ void CAMERA::InitCamera() { float lookdist, magnitude; VECTOR dir; VecSub(&lookp, &pos, &dir); firstray = dir; lookdist = VecNormalize(&dir); VecNormCross(&dir, &vup, &scrni); VecNormCross(&scrni, &dir, &scrnj); magnitude = -2.f*lookdist * (float)tan(0.5f*hfov*PI_180)/xres; VecScale(magnitude, &scrni, &scrnx); magnitude = 2.f*lookdist * (float)tan(0.5f*vfov*PI_180)/yres; VecScale(magnitude, &scrnj, &scrny); firstray.x -= 0.5f*yres*scrny.x + 0.5f*xres*scrnx.x; firstray.y -= 0.5f*yres*scrny.y + 0.5f*xres*scrnx.y; firstray.z -= 0.5f*yres*scrny.z + 0.5f*xres*scrnx.z; DoFData.xres = xres; DoFData.yres = yres; DoFData.left = left; DoFData.top = top; DoFData.right = right; DoFData.bottom = bottom; DoFData.focaldist = focaldist; DoFData.hfov = hfov*PI/180.0f; DoFData.vfov = vfov*PI/180.0f; DoFData.aperture = 2*aperture; DoFData.samples = 7; DoFData.flags = 0; if ((flags & HIDDENAREA) == HIDDENAREA) DoFData.flags = DoFHidden; if ((flags & ACCELERATE) == ACCELERATE) DoFData.flags |= DoFAccelerate; DoF.Init(&DoFData); }
/************* * DESCRIPTION: Given a vector, find two additional vectors such that all three * are mutually perpendicular and uaxis X vaxis = vector. The given * vector need not be normalized. uaxis and vaxis are normalized. * INPUT: vector vector to find two vectors for * uaxis first found vector * vaxis second found vector * OUTPUT: none *************/ void VecCoordSys(VECTOR *vector, VECTOR *uaxis, VECTOR *vaxis) { uaxis->x = -vector->y; uaxis->y = vector->x; uaxis->z = 0.f; if (VecNormalize(uaxis) == 0.f) { uaxis->x = vector->z; uaxis->y = 0.f; uaxis->z = -vector->x; if (VecNormalize(uaxis) == 0.f) // Degenerate vector return; } VecNormCross(vector, uaxis, vaxis); }
void CylinderMapping( Mapping *map, Geom * /*obj*/, Vector *pos, Vector * /*norm*/, Vec2d *uv, Vector *dpdu, Vector *dpdv) { Vector vtmp; Float nx, ny, r; VecSub(*pos, map->center, &vtmp); nx = dotp(&map->uaxis, &vtmp); ny = dotp(&map->vaxis, &vtmp); uv->v = dotp(&map->norm, &vtmp); r = sqrt(nx*nx + ny*ny); if (r < EPSILON) { uv->u = 0.; return; } nx /= r; ny /= r; if (fabs(nx) > 1.) uv->u = 0.5; else uv->u = acos(nx) / TWOPI; if (ny < 0.) uv->u = 1. - uv->u; if (dpdv) *dpdv = map->norm; if (dpdu) (void)VecNormCross(&map->norm, pos, dpdu); }
void OpenGLDrawMesh(TRIANGLE *trias, EDGE *edges, VECTOR *points, VECTOR *normals, ULONG acttrias) { USHORT p1,p2,p3; ULONG i; #ifndef NORMAL VECTOR e1,e2,n; #endif // NORMAL glBegin(GL_TRIANGLES); for(i=0; i<acttrias; i++) { p1 = edges[trias->e[0]].p[0]; p2 = edges[trias->e[0]].p[1]; if((p1 != edges[trias->e[1]].p[0]) && (p2 != edges[trias->e[1]].p[0])) p3 = edges[trias->e[1]].p[0]; else p3 = edges[trias->e[1]].p[1]; #ifdef NORMAL glNormal3fv((GLfloat*)&normals[trias->n[0]]); glVertex3fv((GLfloat*)&points[p1]); glNormal3fv((GLfloat*)&normals[trias->n[1]]); glVertex3fv((GLfloat*)&points[p2]); glNormal3fv((GLfloat*)&normals[trias->n[2]]); glVertex3fv((GLfloat*)&points[p3]); #else // NORMAL VecSub(&points[p3], &points[p1], &e1); VecSub(&points[p3], &points[p2], &e2); VecNormCross(&e2, &e1, &n); glNormal3fv((GLfloat*)&n); glVertex3fv((GLfloat*)&points[p1]); glVertex3fv((GLfloat*)&points[p2]); glVertex3fv((GLfloat*)&points[p3]); #endif // NORMAL trias++; } glEnd(); }
/************* * DESCRIPTION: read faces of object * INPUT: pointer to chunk * OUTPUT: - *************/ static void ParseFaces(HANDLER_DATA *data, CHUNK *mainchunk) { CHUNK chunk; UWORD i, matcount, index, p1, p2, p3; VECTOR e1, e2; SURFACE *s; TRILIST *hp; char buf[80]; ReadWord(data, (WORD *)&data->facecount, 1); // read number of faces if (data->facecount == 0) return; data->face = new FACE3DS[data->facecount]; if (!data->face) { data->err = ERR_MEM; return; } if (!data->replacesurface) { data->material = (SURFACE **)malloc(sizeof(SURFACE *)*data->facecount); if (!data->material) { data->err = ERR_MEM; return; } } ReadWord(data, (WORD *)data->face, 4*data->facecount); // read faces if (data->link->type == LINK_RENDERER) { // do it for renderer only data->VertNorms = new VECTOR[data->pointcount]; if (!data->VertNorms) { data->err = ERR_MEM; return; } data->TriNorms = new VECTOR[data->facecount]; if (!data->TriNorms) { data->err = ERR_MEM; return; } memset(data->VertNorms, 0, sizeof(VECTOR)*data->pointcount); // Init normals data->TriSmooth = new UBYTE[data->facecount]; if (!data->TriSmooth) { data->err = ERR_MEM; return; } for (i = 0; i < data->facecount; i++) { if (data->replacesurface) data->material[i] = data->replacesurface; else data->material[i] = NULL; data->TriSmooth[i] = FALSE; // get three points for the triangle p1 = data->face[i].p1; p2 = data->face[i].p3; p3 = data->face[i].p2; hp = new TRILIST; if (!hp) { data->err = ERR_MEM; return; } hp->next = data->TriList[p1]; hp->tri = i; hp->flag = FALSE; data->TriList[p1] = hp; hp = new TRILIST; if (!hp) { data->err = ERR_MEM; return; } hp->next = data->TriList[p2]; hp->tri = i; hp->flag = FALSE; data->TriList[p2] = hp; hp = new TRILIST; if (!hp) { data->err = ERR_MEM; return; } hp->next = data->TriList[p3]; hp->tri = i; hp->flag = FALSE; data->TriList[p3] = hp; // calculate normal of triangle VecSub(&data->points[p3], &data->points[p1], &e1); VecSub(&data->points[p2], &data->points[p1], &e2); VecNormCross(&e1, &e2, &data->TriNorms[i]); } } do { BeginChunk(data, &chunk); switch (chunk.id) { case ID_MSHMATGROUP: if (!data->replacesurface) { ReadASCIIZ(data, buf); s = data->link->SurfaceGetByName(data->rc, buf); ReadWord(data, (WORD*)&matcount, 1); for (i = 0; i < matcount; i++) { ReadWord(data, (WORD*)&index, 1); data->material[index] = s; } } break; case ID_SMOOTHGROUP: // no info about this group break; } EndChunk(data, &chunk); } while (INCHUNK); }
/************* * DESCRIPTION: add a mesh and calculate normals * INPUT: srf surface * surfaces array of surface pointer, if the mesh has different surfaces (NULL else) * actor actor * points mesh points * edges mesh edges * edgecount amount of edges * mesh mesh triangles * triacount amount of triangles * matrix transform matrix * rotmatrix rotate matrix * nophong disable phong shading * brushcoords brush mapping coordinates * OUTPUT: first created triangle or NULL if failed *************/ TRIANGLE *CreateMesh(RSICONTEXT *rc, SURFACE *srf, SURFACE **surfs, ACTOR *actor, VECTOR *points, EDGE *edges, int edgecount, MESH *mesh, int triacount, MATRIX *matrix, MATRIX *rotmatrix, BOOL nophong, VECT2D *brushcoords) { int i; UWORD p1,p2,p3; UWORD *tmpedges, *te; VECTOR *tmpnorms, e1,e2; MESH *tria; TRIANGLE *triangle, *t; if(!nophong) { tmpnorms = new VECTOR[triacount]; if (!tmpnorms) return NULL; tmpedges = new UWORD[edgecount*2]; if (!tmpedges) { delete tmpnorms; return NULL; } memset(tmpedges, 0xFF, edgecount*sizeof(UWORD)*2); // calculate geometric normals // and generate edge index tria = mesh; for (i=0; i<triacount; i++) { // calculate normals of triangles p1 = edges[tria->e[0]].p[0]; p2 = edges[tria->e[0]].p[1]; if((p1 != edges[tria->e[1]].p[0]) && (p2 != edges[tria->e[1]].p[0])) { p3 = edges[tria->e[1]].p[0]; } else { p3 = edges[tria->e[1]].p[1]; } VecSub(&points[p2], &points[p1], &e1); VecSub(&points[p3], &points[p1], &e2); VecNormCross(&e1, &e2, &tmpnorms[i]); te = &tmpedges[tria->e[0]*2]; if(te[0] == 0xFFFF) te[0] = i; else te[1] = i; te = &tmpedges[tria->e[1]*2]; if(te[0] == 0xFFFF) te[0] = i; else te[1] = i; te = &tmpedges[tria->e[2]*2]; if(te[0] == 0xFFFF) te[0] = i; else te[1] = i; tria++; } } #ifndef __STORM__ // there is a bug in StormC which causes a crash if an array // is allocated when the destructor of the base class is virtual. // I have to test again if it works when a new version is available. // Do also change TriangleGetNext(). triangle = new TRIANGLE[triacount]; if(!triangle) { if(!nophong) { delete [ ] tmpedges; delete [ ] tmpnorms; } return NULL; } t = triangle; #else #endif for(i=0; i<triacount; i++) { #ifdef __STORM__ t = new TRIANGLE; if(!t) { if(!nophong) { delete [ ] tmpedges; delete [ ] tmpnorms; } return NULL; } #endif if(surfs) t->surf = surfs[i]; else t->surf = srf; t->actor = actor; t->flags |= OBJECT_INBLOCK; t->Insert(rc); #ifndef __STORM__ t++; #endif } #ifndef __STORM__ triangle->flags |= OBJECT_FIRSTBLOCK; #else triangle = t; #endif tria = mesh; t = triangle; for (i=0; i<triacount; i++) { p1 = edges[tria->e[0]].p[0]; p2 = edges[tria->e[0]].p[1]; if((p1 != edges[tria->e[1]].p[0]) && (p2 != edges[tria->e[1]].p[0])) { p3 = edges[tria->e[1]].p[0]; } else { p3 = edges[tria->e[1]].p[1]; } if(!nophong) { t->vnorm = new VECTOR[3]; if(!t->vnorm) { delete triangle; delete [ ] tmpedges; delete [ ] tmpnorms; return NULL; } t->vnorm[0] = tmpnorms[i]; t->vnorm[1] = tmpnorms[i]; t->vnorm[2] = tmpnorms[i]; GenerateNormal(i, &t->vnorm[0], tmpnorms, tmpedges, p1, edges, mesh); GenerateNormal(i, &t->vnorm[1], tmpnorms, tmpedges, p2, edges, mesh); GenerateNormal(i, &t->vnorm[2], tmpnorms, tmpedges, p3, edges, mesh); rotmatrix->MultVectMat(&t->vnorm[0]); rotmatrix->MultVectMat(&t->vnorm[1]); rotmatrix->MultVectMat(&t->vnorm[2]); } t->p[0] = points[p1]; matrix->MultVectMat(&t->p[0]); t->p[1] = points[p2]; matrix->MultVectMat(&t->p[1]); t->p[2] = points[p3]; matrix->MultVectMat(&t->p[2]); #ifdef __STORM__ t = (TRIANGLE*)t->GetNext(); #else t++; #endif tria++; } if(!nophong) { delete [ ] tmpedges; delete [ ] tmpnorms; } return triangle; }