From: curt Date: Tue, 25 Aug 1998 16:51:22 +0000 (+0000) Subject: Moved from ../Scenery X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=2f7b36a4af34464dd14792e8c240d3f205a72c30;p=flightgear.git Moved from ../Scenery --- diff --git a/Objects/Makefile.am b/Objects/Makefile.am new file mode 100644 index 000000000..b04d45d48 --- /dev/null +++ b/Objects/Makefile.am @@ -0,0 +1,9 @@ +noinst_LIBRARIES = libObjects.a + +libObjects_a_SOURCES = \ + fragment.cxx fragment.hxx \ + material.cxx material.hxx \ + obj.cxx obj.hxx \ + texload.c texload.h + +INCLUDES += -I$(top_builddir) -I$(top_builddir)/Lib -I$(top_builddir)/Simulator diff --git a/Objects/fragment.cxx b/Objects/fragment.cxx new file mode 100644 index 000000000..089ac15bc --- /dev/null +++ b/Objects/fragment.cxx @@ -0,0 +1,412 @@ +// fragment.cxx -- routines to handle "atomic" display objects +// +// Written by Curtis Olson, started August 1998. +// +// Copyright (C) 1998 Curtis L. Olson - curt@me.umn.edu +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id$ +// (Log is kept at end of this file) + + +#include +#include +#include +#include + +#include "fragment.hxx" + + +// return the sign of a value +#define FG_SIGN( x ) ((x) < 0 ? -1 : 1) + +// return min or max of two values +#define FG_MIN(A,B) ((A) < (B) ? (A) : (B)) +#define FG_MAX(A,B) ((A) > (B) ? (A) : (B)) + + +fgFACE :: fgFACE () : + n1(0), n2(0), n3(0) +{ +} + +fgFACE :: ~fgFACE() +{ +} + +fgFACE :: fgFACE( const fgFACE & image ) : + n1( image.n1), n2( image.n2), n3( image.n3) +{ +} + +bool fgFACE :: operator < (const fgFACE & rhs ) +{ + return ( n1 < rhs.n1 ? true : false); +} + +bool fgFACE :: operator == (const fgFACE & rhs ) +{ + return ((n1 == rhs.n1) && (n2 == rhs.n2) && ( n3 == rhs.n3)); +} + + +// Constructor +fgFRAGMENT::fgFRAGMENT ( void ) { +} + + +// Copy constructor +fgFRAGMENT :: fgFRAGMENT ( const fgFRAGMENT & rhs ) : + center ( rhs.center ), + bounding_radius( rhs.bounding_radius ), + material_ptr ( rhs.material_ptr ), + tile_ptr ( rhs.tile_ptr ), + display_list ( rhs.display_list ), + faces ( rhs.faces ), + num_faces ( rhs.num_faces ) +{ +} + +fgFRAGMENT & fgFRAGMENT :: operator = ( const fgFRAGMENT & rhs ) +{ + if(!(this == &rhs )) { + center = rhs.center; + bounding_radius = rhs.bounding_radius; + material_ptr = rhs.material_ptr; + tile_ptr = rhs.tile_ptr; + // display_list = rhs.display_list; + faces = rhs.faces; + } + return *this; +} + + +// Add a face to the face list +void fgFRAGMENT::add_face(int n1, int n2, int n3) { + fgFACE face; + + face.n1 = n1; + face.n2 = n2; + face.n3 = n3; + + faces.push_back(face); + num_faces++; +} + + +// return the minimum of the three values +static double fg_min3 (double a, double b, double c) +{ + return (a > b ? FG_MIN (b, c) : FG_MIN (a, c)); +} + + +// return the maximum of the three values +static double fg_max3 (double a, double b, double c) +{ + return (a < b ? FG_MAX (b, c) : FG_MAX (a, c)); +} + + +// test if line intesects with this fragment. p0 and p1 are the two +// line end points of the line. If side_flag is true, check to see +// that end points are on opposite sides of face. Returns 1 if it +// intersection found, 0 otherwise. If it intesects, result is the +// point of intersection + +int fgFRAGMENT::intersect( fgPoint3d *end0, fgPoint3d *end1, int side_flag, + fgPoint3d *result) +{ + fgTILE *t; + fgFACE face; + MAT3vec v1, v2, n, center; + double p1[3], p2[3], p3[3]; + double x, y, z; // temporary holding spot for result + double a, b, c, d; + double x0, y0, z0, x1, y1, z1, a1, b1, c1; + double t1, t2, t3; + double xmin, xmax, ymin, ymax, zmin, zmax; + double dx, dy, dz, min_dim, x2, y2, x3, y3, rx, ry; + int side1, side2; + list < fgFACE > :: iterator current; + list < fgFACE > :: iterator last; + + // find the associated tile + t = tile_ptr; + + // printf("Intersecting\n"); + + // traverse the face list for this fragment + current = faces.begin(); + last = faces.end(); + while ( current != last ) { + face = *current; + current++; + + // printf("."); + + // get face vertex coordinates + center[0] = t->center.x; + center[1] = t->center.y; + center[2] = t->center.z; + + MAT3_ADD_VEC(p1, t->nodes[face.n1], center); + MAT3_ADD_VEC(p2, t->nodes[face.n2], center); + MAT3_ADD_VEC(p3, t->nodes[face.n3], center); + + // printf("point 1 = %.2f %.2f %.2f\n", p1[0], p1[1], p1[2]); + // printf("point 2 = %.2f %.2f %.2f\n", p2[0], p2[1], p2[2]); + // printf("point 3 = %.2f %.2f %.2f\n", p3[0], p3[1], p3[2]); + + // calculate two edge vectors, and the face normal + MAT3_SUB_VEC(v1, p2, p1); + MAT3_SUB_VEC(v2, p3, p1); + MAT3cross_product(n, v1, v2); + + // calculate the plane coefficients for the plane defined by + // this face. If n is the normal vector, n = (a, b, c) and p1 + // is a point on the plane, p1 = (x0, y0, z0), then the + // equation of the line is a(x-x0) + b(y-y0) + c(z-z0) = 0 + a = n[0]; + b = n[1]; + c = n[2]; + d = a * p1[0] + b * p1[1] + c * p1[2]; + // printf("a, b, c, d = %.2f %.2f %.2f %.2f\n", a, b, c, d); + + // printf("p1(d) = %.2f\n", a * p1[0] + b * p1[1] + c * p1[2]); + // printf("p2(d) = %.2f\n", a * p2[0] + b * p2[1] + c * p2[2]); + // printf("p3(d) = %.2f\n", a * p3[0] + b * p3[1] + c * p3[2]); + + // calculate the line coefficients for the specified line + x0 = end0->x; x1 = end1->x; + y0 = end0->y; y1 = end1->y; + z0 = end0->z; z1 = end1->z; + + if ( fabs(x1 - x0) > FG_EPSILON ) { + a1 = 1.0 / (x1 - x0); + } else { + // we got a big divide by zero problem here + a1 = 0.0; + } + b1 = y1 - y0; + c1 = z1 - z0; + + // intersect the specified line with this plane + t1 = b * b1 * a1; + t2 = c * c1 * a1; + + // printf("a = %.2f t1 = %.2f t2 = %.2f\n", a, t1, t2); + + if ( fabs(a + t1 + t2) > FG_EPSILON ) { + x = (t1*x0 - b*y0 + t2*x0 - c*z0 + d) / (a + t1 + t2); + t3 = a1 * (x - x0); + y = b1 * t3 + y0; + z = c1 * t3 + z0; + // printf("result(d) = %.2f\n", a * x + b * y + c * z); + } else { + // no intersection point + continue; + } + + if ( side_flag ) { + // check to see if end0 and end1 are on opposite sides of + // plane + if ( (x - x0) > FG_EPSILON ) { + t1 = x; + t2 = x0; + t3 = x1; + } else if ( (y - y0) > FG_EPSILON ) { + t1 = y; + t2 = y0; + t3 = y1; + } else if ( (z - z0) > FG_EPSILON ) { + t1 = z; + t2 = z0; + t3 = z1; + } else { + // everything is too close together to tell the difference + // so the current intersection point should work as good + // as any + result->x = x; + result->y = y; + result->z = z; + return(1); + } + side1 = FG_SIGN (t1 - t2); + side2 = FG_SIGN (t1 - t3); + if ( side1 == side2 ) { + // same side, punt + continue; + } + } + + // check to see if intersection point is in the bounding + // cube of the face +#ifdef XTRA_DEBUG_STUFF + xmin = fg_min3 (p1[0], p2[0], p3[0]); + xmax = fg_max3 (p1[0], p2[0], p3[0]); + ymin = fg_min3 (p1[1], p2[1], p3[1]); + ymax = fg_max3 (p1[1], p2[1], p3[1]); + zmin = fg_min3 (p1[2], p2[2], p3[2]); + zmax = fg_max3 (p1[2], p2[2], p3[2]); + printf("bounding cube = %.2f,%.2f,%.2f %.2f,%.2f,%.2f\n", + xmin, ymin, zmin, xmax, ymax, zmax); +#endif + // punt if outside bouding cube + if ( x < (xmin = fg_min3 (p1[0], p2[0], p3[0])) ) { + continue; + } else if ( x > (xmax = fg_max3 (p1[0], p2[0], p3[0])) ) { + continue; + } else if ( y < (ymin = fg_min3 (p1[1], p2[1], p3[1])) ) { + continue; + } else if ( y > (ymax = fg_max3 (p1[1], p2[1], p3[1])) ) { + continue; + } else if ( z < (zmin = fg_min3 (p1[2], p2[2], p3[2])) ) { + continue; + } else if ( z > (zmax = fg_max3 (p1[2], p2[2], p3[2])) ) { + continue; + } + + // (finally) check to see if the intersection point is + // actually inside this face + + //first, drop the smallest dimension so we only have to work + //in 2d. + dx = xmax - xmin; + dy = ymax - ymin; + dz = zmax - zmin; + min_dim = fg_min3 (dx, dy, dz); + if ( fabs(min_dim - dx) <= FG_EPSILON ) { + // x is the smallest dimension + x1 = p1[1]; + y1 = p1[2]; + x2 = p2[1]; + y2 = p2[2]; + x3 = p3[1]; + y3 = p3[2]; + rx = y; + ry = z; + } else if ( fabs(min_dim - dy) <= FG_EPSILON ) { + // y is the smallest dimension + x1 = p1[0]; + y1 = p1[2]; + x2 = p2[0]; + y2 = p2[2]; + x3 = p3[0]; + y3 = p3[2]; + rx = x; + ry = z; + } else if ( fabs(min_dim - dz) <= FG_EPSILON ) { + // z is the smallest dimension + x1 = p1[0]; + y1 = p1[1]; + x2 = p2[0]; + y2 = p2[1]; + x3 = p3[0]; + y3 = p3[1]; + rx = x; + ry = y; + } else { + // all dimensions are really small so lets call it close + // enough and return a successful match + result->x = x; + result->y = y; + result->z = z; + return(1); + } + + // check if intersection point is on the same side of p1 <-> p2 as p3 + t1 = (y1 - y2) / (x1 - x2); + side1 = FG_SIGN (t1 * ((x3) - x2) + y2 - (y3)); + side2 = FG_SIGN (t1 * ((rx) - x2) + y2 - (ry)); + if ( side1 != side2 ) { + // printf("failed side 1 check\n"); + continue; + } + + // check if intersection point is on correct side of p2 <-> p3 as p1 + t1 = (y2 - y3) / (x2 - x3); + side1 = FG_SIGN (t1 * ((x1) - x3) + y3 - (y1)); + side2 = FG_SIGN (t1 * ((rx) - x3) + y3 - (ry)); + if ( side1 != side2 ) { + // printf("failed side 2 check\n"); + continue; + } + + // check if intersection point is on correct side of p1 <-> p3 as p2 + t1 = (y1 - y3) / (x1 - x3); + side1 = FG_SIGN (t1 * ((x2) - x3) + y3 - (y2)); + side2 = FG_SIGN (t1 * ((rx) - x3) + y3 - (ry)); + if ( side1 != side2 ) { + // printf("failed side 3 check\n"); + continue; + } + + // printf( "intersection point = %.2f %.2f %.2f\n", x, y, z); + result->x = x; + result->y = y; + result->z = z; + return(1); + } + + // printf("\n"); + + return(0); +} + + +// Destructor +fgFRAGMENT::~fgFRAGMENT ( void ) { + // Step through the face list deleting the items until the list is + // empty + + // printf("destructing a fragment with %d faces\n", faces.size()); + + while ( faces.size() ) { + // printf("emptying face list\n"); + faces.pop_front(); + } +} + + +// equality operator +bool fgFRAGMENT :: operator == ( const fgFRAGMENT & rhs) +{ + if(( center.x - rhs.center.x ) < FG_EPSILON) { + if(( center.y - rhs.center.y) < FG_EPSILON) { + if(( center.z - rhs.center.z) < FG_EPSILON) { + return true; + } + } + } + return false; +} + +// comparison operator +bool fgFRAGMENT :: operator < ( const fgFRAGMENT &rhs) +{ + // This is completely arbitrary. It satisfies RW's STL implementation + + return bounding_radius < rhs.bounding_radius; +} + + +// $Log$ +// Revision 1.1 1998/08/25 16:51:23 curt +// Moved from ../Scenery +// +// + diff --git a/Objects/fragment.hxx b/Objects/fragment.hxx new file mode 100644 index 000000000..4b1b3d2ba --- /dev/null +++ b/Objects/fragment.hxx @@ -0,0 +1,146 @@ +// fragment.hxx -- routines to handle "atomic" display objects +// +// Written by Curtis Olson, started August 1998. +// +// Copyright (C) 1998 Curtis L. Olson - curt@me.umn.edu +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id$ +// (Log is kept at end of this file) + + +#ifndef _FRAGMENT_HXX +#define _FRAGMENT_HXX + + +#ifndef __cplusplus +# error This library requires C++ +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_WINDOWS_H +# include +#endif + +#include +#include + +#if defined ( __sun__ ) +extern "C" void *memmove(void *, const void *, size_t); +extern "C" void *memset(void *, int, size_t); +#endif + +#include // STL list + +#include +#include +#include + +#ifdef NEEDNAMESPACESTD +using namespace std; +#endif + + +// Maximum nodes per tile +#define MAX_NODES 2000 + + +// Forward declarations +class fgTILE; +class fgMATERIAL; + + +class fgFACE { +public: + int n1, n2, n3; + + fgFACE(); + ~fgFACE(); + fgFACE( const fgFACE & image ); + bool operator < ( const fgFACE & rhs ); + bool operator == ( const fgFACE & rhs ); +}; + + +// Object fragment data class +class fgFRAGMENT { + +public: + // culling data for this object fragment (fine grain culling) + fgPoint3d center; + double bounding_radius; + + // variable offset data for this object fragment for this frame + // fgCartesianPoint3d tile_offset; + + // saved transformation matrix for this fragment (used by renderer) + // GLfloat matrix[16]; + + // tile_ptr & material_ptr are set so that when we traverse the + // list of fragments we can quickly reference back the tile or + // material property this fragment is assigned to. + + // material property pointer + fgMATERIAL *material_ptr; + + // tile pointer + fgTILE *tile_ptr; + + // OpenGL display list for fragment data + GLint display_list; + + // face list (this indexes into the master tile vertex list) + list < fgFACE > faces; + + // number of faces in this fragment + int num_faces; + + // Add a face to the face list + void add_face(int n1, int n2, int n3); + + // test if line intesects with this fragment. p0 and p1 are the + // two line end points of the line. If side_flag is true, check + // to see that end points are on opposite sides of face. Returns + // 1 if it intersection found, 0 otherwise. If it intesects, + // result is the point of intersection + int intersect( fgPoint3d *end0, fgPoint3d *end1, int side_flag, + fgPoint3d *result); + + // Constructors + fgFRAGMENT (); + fgFRAGMENT ( const fgFRAGMENT &image ); + + // Destructor + ~fgFRAGMENT ( ); + + // operators + fgFRAGMENT & operator = ( const fgFRAGMENT & rhs ); + bool operator == ( const fgFRAGMENT & rhs ); + bool operator < ( const fgFRAGMENT & rhs ); +}; + + +#endif // _FRAGMENT_HXX + + +// $Log$ +// Revision 1.1 1998/08/25 16:51:23 curt +// Moved from ../Scenery +// +// diff --git a/Objects/material.cxx b/Objects/material.cxx new file mode 100644 index 000000000..7912c4107 --- /dev/null +++ b/Objects/material.cxx @@ -0,0 +1,366 @@ +// material.cxx -- class to handle material properties +// +// Written by Curtis Olson, started May 1998. +// +// Copyright (C) 1998 Curtis L. Olson - curt@me.umn.edu +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id$ +// (Log is kept at end of this file) + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_WINDOWS_H +# include +#endif + +#include +#include + +#include + +#include +#include +#include
+ +#include "material.hxx" +#include "texload.h" + +// global material management class +fgMATERIAL_MGR material_mgr; + + +// Constructor +fgMATERIAL::fgMATERIAL ( void ) { +} + + +// Sorting routines +void fgMATERIAL::init_sort_list( void ) { +} + + +int fgMATERIAL::append_sort_list( fgFRAGMENT *object ) { + return(0); +} + + +// Destructor +fgMATERIAL::~fgMATERIAL ( void ) { +} + + +// Constructor +fgMATERIAL_MGR::fgMATERIAL_MGR ( void ) { +} + + +// Load a library of material properties +int fgMATERIAL_MGR::load_lib ( void ) { + fgMATERIAL m; + char material_name[256]; + char mpath[256], fg_mpath[256], tpath[256], fg_tpath[256]; + char line[256], *line_ptr, value[256]; + GLubyte *texbuf; + fgFile f; + int width, height; + int alpha; + + // build the path name to the material db + current_options.get_fg_root(mpath); + strcat(mpath, "/Scenery/"); + strcat(mpath, "Materials"); + strcpy(fg_mpath, mpath); + strcat(fg_mpath, ".gz"); + + // first try "path.gz" + if ( (f = fgopen(fg_mpath, "rb")) == NULL ) { + // next try "path" + if ( (f = fgopen(mpath, "rb")) == NULL ) { + fgPrintf(FG_GENERAL, FG_EXIT, "Cannot open file: %s\n", mpath); + } + } + + while ( fggets(f, line, 250) != NULL ) { + // printf("%s", line); + + // strip leading white space + line_ptr = line; + while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') ) && + (line_ptr[0] != '\n') ) { + line_ptr++; + + } + + if ( line_ptr[0] == '#' ) { + // ignore lines that start with '#' + } else if ( line_ptr[0] == '\n' ) { + // ignore blank lines + } else if ( strstr(line_ptr, "{") ) { + // start of record + alpha = 0; + m.ambient[0] = m.ambient[1] = m.ambient[2] = m.ambient[3] = 0.0; + m.diffuse[0] = m.diffuse[1] = m.diffuse[2] = m.diffuse[3] = 0.0; + m.specular[0] = m.specular[1] = m.specular[2] = m.specular[3] = 0.0; + m.emissive[0] = m.emissive[1] = m.emissive[2] = m.emissive[3] = 0.0; + + material_name[0] = '\0'; + sscanf(line_ptr, "%s", material_name); + if ( ! strlen(material_name) ) { + fgPrintf( FG_TERRAIN, FG_INFO, "Bad material name in '%s'\n", + line ); + } + printf(" Loading material = %s\n", material_name); + } else if ( strncmp(line_ptr, "alpha", 5) == 0 ) { + line_ptr += 5; + while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || + (line_ptr[0] == '=') ) && + (line_ptr[0] != '\n') ) { + line_ptr++; + } + sscanf(line_ptr, "%s\n", value); + if ( strcmp(value, "no") == 0 ) { + alpha = 0; + } else if ( strcmp(value, "yes") == 0 ) { + alpha = 1; + } else { + fgPrintf( FG_TERRAIN, FG_INFO, "Bad alpha value '%s'\n", line ); + } + } else if ( (strncmp(line_ptr, "texture", 7) == 0) && + !current_options.get_textures() ) { + // do nothing + } else if ( strncmp(line_ptr, "texture", 7) == 0 ) { + line_ptr += 7; + while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || + (line_ptr[0] == '=') ) && + (line_ptr[0] != '\n') ) { + line_ptr++; + } + // printf("texture name = %s\n", line_ptr); + sscanf(line_ptr, "%s\n", m.texture_name); + + // create the texture object and bind it +#ifdef GL_VERSION_1_1 + xglGenTextures(1, &m.texture_id); + xglBindTexture(GL_TEXTURE_2D, m.texture_id); +#elif GL_EXT_texture_object + xglGenTexturesEXT(1, &m.texture_id); + xglBindTextureEXT(GL_TEXTURE_2D, m.texture_id); +#else +# error port me +#endif + + // set the texture parameters for this texture + xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ) ; + xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ) ; + xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_LINEAR ); + // xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + // GL_NEAREST_MIPMAP_NEAREST ); + xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + /* GL_LINEAR */ + /* GL_NEAREST_MIPMAP_LINEAR */ + GL_LINEAR_MIPMAP_LINEAR ) ; + + /* load in the texture data */ + current_options.get_fg_root(tpath); + strcat(tpath, "/Textures/"); + strcat(tpath, m.texture_name); + strcat(tpath, ".rgb"); + + if ( alpha == 0 ) { + // load rgb texture + + // Try uncompressed + if ( (texbuf = read_rgb_texture(tpath, &width, &height)) + == NULL ) { + // Try compressed + strcpy(fg_tpath, tpath); + strcat(fg_tpath, ".gz"); + if ( (texbuf = read_rgb_texture(fg_tpath, &width, &height)) + == NULL ) { + fgPrintf( FG_GENERAL, FG_EXIT, + "Error in loading texture %s\n", tpath ); + return(0); + } + } + + /* xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, + GL_RGB, GL_UNSIGNED_BYTE, texbuf); */ + + gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGB, width, height, + GL_RGB, GL_UNSIGNED_BYTE, texbuf ); + } else if ( alpha == 1 ) { + // load rgba (alpha) texture + + // Try uncompressed + if ( (texbuf = read_alpha_texture(tpath, &width, &height)) + == NULL ) { + // Try compressed + strcpy(fg_tpath, tpath); + strcat(fg_tpath, ".gz"); + if ((texbuf = read_alpha_texture(fg_tpath, &width, &height)) + == NULL ) { + fgPrintf( FG_GENERAL, FG_EXIT, + "Error in loading texture %s\n", tpath ); + return(0); + } + } + + xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, texbuf); + } + + } else if ( strncmp(line_ptr, "ambient", 7) == 0 ) { + line_ptr += 7; + while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || + (line_ptr[0] == '=') ) && + (line_ptr[0] != '\n') ) { + line_ptr++; + } + sscanf( line_ptr, "%f %f %f %f", + &m.ambient[0], &m.ambient[1], &m.ambient[2], &m.ambient[3]); + } else if ( strncmp(line_ptr, "diffuse", 7) == 0 ) { + line_ptr += 7; + while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || + (line_ptr[0] == '=') ) && + (line_ptr[0] != '\n') ) { + line_ptr++; + } + sscanf( line_ptr, "%f %f %f %f", + &m.diffuse[0], &m.diffuse[1], &m.diffuse[2], &m.diffuse[3]); + } else if ( strncmp(line_ptr, "specular", 8) == 0 ) { + line_ptr += 8; + while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || + (line_ptr[0] == '=') ) && + (line_ptr[0] != '\n') ) { + line_ptr++; + } + sscanf( line_ptr, "%f %f %f %f", + &m.specular[0], &m.specular[1], + &m.specular[2], &m.specular[3]); + } else if ( strncmp(line_ptr, "emissive", 8) == 0 ) { + line_ptr += 8; + while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || + (line_ptr[0] == '=') ) && + (line_ptr[0] != '\n') ) { + line_ptr++; + } + sscanf( line_ptr, "%f %f %f %f", + &m.emissive[0], &m.emissive[1], + &m.emissive[2], &m.emissive[3]); + } else if ( line_ptr[0] == '}' ) { + // end of record, lets add this one to the list + material_mgr.material_map[material_name] = m; + } else { + fgPrintf(FG_TERRAIN, FG_INFO, + "Unknown line in material properties file\n"); + } + } + + fgclose(f); + + return(1); +} + + +// Initialize the transient list of fragments for each material property +void fgMATERIAL_MGR::init_transient_material_lists( void ) { + map < string, fgMATERIAL, less > :: iterator mapcurrent = + material_mgr.material_map.begin(); + map < string, fgMATERIAL, less > :: iterator maplast = + material_mgr.material_map.end(); + + while ( mapcurrent != maplast ) { + // (char *)key = (*mapcurrent).first; + // (fgMATERIAL)value = (*mapcurrent).second; + (*mapcurrent).second.list_size = 0; + + *mapcurrent++; + } +} + + +// Destructor +fgMATERIAL_MGR::~fgMATERIAL_MGR ( void ) { +} + + +// $Log$ +// Revision 1.1 1998/08/25 16:51:24 curt +// Moved from ../Scenery +// +// Revision 1.13 1998/08/24 20:11:39 curt +// Tweaks ... +// +// Revision 1.12 1998/08/12 21:41:27 curt +// Need to negate the test for textures so that textures aren't loaded when +// they are disabled rather than visa versa ... :-) +// +// Revision 1.11 1998/08/12 21:13:03 curt +// material.cxx: don't load textures if they are disabled +// obj.cxx: optimizations from Norman Vine +// tile.cxx: minor tweaks +// tile.hxx: addition of num_faces +// tilemgr.cxx: minor tweaks +// +// Revision 1.10 1998/07/24 21:42:06 curt +// material.cxx: whups, double method declaration with no definition. +// obj.cxx: tweaks to avoid errors in SGI's CC. +// tile.cxx: optimizations by Norman Vine. +// tilemgr.cxx: optimizations by Norman Vine. +// +// Revision 1.9 1998/07/13 21:01:57 curt +// Wrote access functions for current fgOPTIONS. +// +// Revision 1.8 1998/07/08 14:47:20 curt +// Fix GL_MODULATE vs. GL_DECAL problem introduced by splash screen. +// polare3d.h renamed to polar3d.hxx +// fg{Cartesian,Polar}Point3d consolodated. +// Added some initial support for calculating local current ground elevation. +// +// Revision 1.7 1998/07/04 00:54:28 curt +// Added automatic mipmap generation. +// +// When rendering fragments, use saved model view matrix from associated tile +// rather than recalculating it with push() translate() pop(). +// +// Revision 1.6 1998/06/27 16:54:59 curt +// Check for GL_VERSION_1_1 or GL_EXT_texture_object to decide whether to use +// "EXT" versions of texture management routines. +// +// Revision 1.5 1998/06/17 21:36:39 curt +// Load and manage multiple textures defined in the Materials library. +// Boost max material fagments for each material property to 800. +// Multiple texture support when rendering. +// +// Revision 1.4 1998/06/12 00:58:04 curt +// Build only static libraries. +// Declare memmove/memset for Sloaris. +// +// Revision 1.3 1998/06/05 22:39:53 curt +// Working on sorting by, and rendering by material properties. +// +// Revision 1.2 1998/06/01 17:56:20 curt +// Incremental additions to material.cxx (not fully functional) +// Tweaked vfc_ratio math to avoid divide by zero. +// +// Revision 1.1 1998/05/30 01:56:45 curt +// Added material.cxx material.hxx +// diff --git a/Objects/material.hxx b/Objects/material.hxx new file mode 100644 index 000000000..a9428eea4 --- /dev/null +++ b/Objects/material.hxx @@ -0,0 +1,164 @@ +// material.hxx -- class to handle material properties +// +// Written by Curtis Olson, started May 1998. +// +// Copyright (C) 1998 Curtis L. Olson - curt@me.umn.edu +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id$ +// (Log is kept at end of this file) + + +#ifndef _MATERIAL_HXX +#define _MATERIAL_HXX + + +#ifndef __cplusplus +# error This library requires C++ +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_WINDOWS_H +# include +#endif + +#include +#include + +#if defined ( __sun__ ) +extern "C" void *memmove(void *, const void *, size_t); +extern "C" void *memset(void *, int, size_t); +#endif + +#include // Standard C++ string library +#include // STL associative "array" + +#ifdef NEEDNAMESPACESTD +using namespace std; +#endif + +#include "fragment.hxx" + + +#define FG_MAX_MATERIAL_FRAGS 800 + + +// Material property class +class fgMATERIAL { + +public: + // OpenGL texture name + GLuint texture_id; + + // file name of texture + char texture_name[256]; + + // material properties + GLfloat ambient[4], diffuse[4], specular[4], emissive[4]; + GLint texture_ptr; + + // transient list of objects with this material type (used for sorting + // by material to reduce GL state changes when rendering the scene + fgFRAGMENT * list[FG_MAX_MATERIAL_FRAGS]; + int list_size; + + // Constructor + fgMATERIAL ( void ); + + // Sorting routines + void init_sort_list( void ); + int append_sort_list( fgFRAGMENT *object ); + + // Destructor + ~fgMATERIAL ( void ); +}; + + +// Material management class +class fgMATERIAL_MGR { + +public: + + // associative array of materials + map < string, fgMATERIAL, less > material_map; + + // Constructor + fgMATERIAL_MGR ( void ); + + // Load a library of material properties + int load_lib ( void ); + + // Initialize the transient list of fragments for each material property + void init_transient_material_lists( void ); + + // Destructor + ~fgMATERIAL_MGR ( void ); +}; + + +// global material management class +extern fgMATERIAL_MGR material_mgr; + + +#endif // _MATERIAL_HXX + + +// $Log$ +// Revision 1.1 1998/08/25 16:51:24 curt +// Moved from ../Scenery +// +// Revision 1.10 1998/07/24 21:42:06 curt +// material.cxx: whups, double method declaration with no definition. +// obj.cxx: tweaks to avoid errors in SGI's CC. +// tile.cxx: optimizations by Norman Vine. +// tilemgr.cxx: optimizations by Norman Vine. +// +// Revision 1.9 1998/07/06 21:34:33 curt +// Added using namespace std for compilers that support this. +// +// Revision 1.8 1998/06/17 21:36:39 curt +// Load and manage multiple textures defined in the Materials library. +// Boost max material fagments for each material property to 800. +// Multiple texture support when rendering. +// +// Revision 1.7 1998/06/12 00:58:04 curt +// Build only static libraries. +// Declare memmove/memset for Sloaris. +// +// Revision 1.6 1998/06/06 01:09:31 curt +// I goofed on the log message in the last commit ... now fixed. +// +// Revision 1.5 1998/06/06 01:07:17 curt +// Increased per material fragment list size from 100 to 400. +// Now correctly draw viewable fragments in per material order. +// +// Revision 1.4 1998/06/05 22:39:53 curt +// Working on sorting by, and rendering by material properties. +// +// Revision 1.3 1998/06/03 00:47:50 curt +// No .h for STL includes. +// Minor view culling optimizations. +// +// Revision 1.2 1998/06/01 17:56:20 curt +// Incremental additions to material.cxx (not fully functional) +// Tweaked vfc_ratio math to avoid divide by zero. +// +// Revision 1.1 1998/05/30 01:56:45 curt +// Added material.cxx material.hxx +// diff --git a/Objects/obj.cxx b/Objects/obj.cxx new file mode 100644 index 000000000..f51931bb1 --- /dev/null +++ b/Objects/obj.cxx @@ -0,0 +1,720 @@ +// obj.cxx -- routines to handle "sorta" WaveFront .obj format files. +// +// Written by Curtis Olson, started October 1997. +// +// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id$ +// (Log is kept at end of this file) + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_WINDOWS_H +# include +#endif + +#include +#include +#include +#include + +#if defined ( __sun__ ) +extern "C" void *memmove(void *, const void *, size_t); +extern "C" void *memset(void *, int, size_t); +#endif + +#include // Standard C++ library +#include // STL + +#ifdef NEEDNAMESPACESTD +using namespace std; +#endif + +#include +#include +#include +#include
+#include +#include +#include +#include + +#include "material.hxx" +#include "obj.hxx" + + +static double normals[MAX_NODES][3]; + + +// given three points defining a triangle, calculate the normal +static void calc_normal(double p1[3], double p2[3], + double p3[3], double normal[3]) +{ + double v1[3], v2[3]; + double temp; + + v1[0] = p2[0] - p1[0]; v1[1] = p2[1] - p1[1]; v1[2] = p2[2] - p1[2]; + v2[0] = p3[0] - p1[0]; v2[1] = p3[1] - p1[1]; v2[2] = p3[2] - p1[2]; + + MAT3cross_product(normal, v1, v2); + MAT3_NORMALIZE_VEC(normal,temp); + + // fgPrintf( FG_TERRAIN, FG_DEBUG, " Normal = %.2f %.2f %.2f\n", + // normal[0], normal[1], normal[2]); +} + + +#define FG_TEX_CONSTANT 128.0 + + +// Calculate texture coordinates for a given point. +fgPoint3d calc_tex_coords(double *node, fgPoint3d *ref) { + fgPoint3d cp; + fgPoint3d pp; + + cp.x = node[0] + ref->x; + cp.y = node[1] + ref->y; + cp.z = node[2] + ref->z; + + pp = fgCartToPolar3d(cp); + + pp.lon = fmod(RAD_TO_DEG * FG_TEX_CONSTANT * pp.lon, 25.0); + pp.lat = fmod(RAD_TO_DEG * FG_TEX_CONSTANT * pp.lat, 25.0); + + return(pp); +} + + +// Load a .obj file and build the GL fragment list +int fgObjLoad(char *path, fgTILE *t) { + fgFRAGMENT fragment; + fgPoint3d pp; + char fgpath[256], line[256], material[256]; + double approx_normal[3], normal[3], scale; + // double x, y, z, xmax, xmin, ymax, ymin, zmax, zmin; + // GLfloat sgenparams[] = { 1.0, 0.0, 0.0, 0.0 }; + GLint display_list; + fgFile f; + int shading; + int in_fragment, in_faces, vncount, n1, n2, n3, n4; + int last1, last2, odd; + double (*nodes)[3]; + fgPoint3d *center; + + // First try "path.gz" (compressed format) + strcpy(fgpath, path); + strcat(fgpath, ".gz"); + if ( (f = fgopen(fgpath, "rb")) == NULL ) { + // Next try "path" (uncompressed format) + strcpy(fgpath, path); + if ( (f = fgopen(fgpath, "rb")) == NULL ) { + // Next try "path.obj" (uncompressed format) + strcat(fgpath, ".gz"); + if ( (f = fgopen(fgpath, "rb")) == NULL ) { + strcpy(fgpath, path); + fgPrintf( FG_TERRAIN, FG_ALERT, + "Cannot open file: %s\n", fgpath ); + return(0); + } + } + } + + shading = current_options.get_shading(); + + in_fragment = 0; + t->ncount = 1; + vncount = 1; + t->bounding_radius = 0.0; + nodes = t->nodes; + center = &t->center; + + while ( fggets(f, line, 250) != NULL ) { + if ( line[0] == '#' ) { + // comment -- ignore + } else if ( line[0] == '\n' ) { + // empty line -- ignore + } else if ( strncmp(line, "gbs ", 4) == 0 ) { + // reference point (center offset) + sscanf(line, "gbs %lf %lf %lf %lf\n", + &t->center.x, &t->center.y, &t->center.z, + &t->bounding_radius); + } else if ( strncmp(line, "bs ", 3) == 0 ) { + // reference point (center offset) + sscanf(line, "bs %lf %lf %lf %lf\n", + &fragment.center.x, &fragment.center.y, &fragment.center.z, + &fragment.bounding_radius); + } else if ( strncmp(line, "v ", 2) == 0 ) { + // node (vertex) + if ( t->ncount < MAX_NODES ) { + // fgPrintf( FG_TERRAIN, FG_DEBUG, "vertex = %s", line); + sscanf(line, "v %lf %lf %lf\n", + &(t->nodes[t->ncount][0]), &(t->nodes[t->ncount][1]), + &(t->nodes[t->ncount][2])); + + t->ncount++; + + } else { + fgPrintf( FG_TERRAIN, FG_EXIT, + "Read too many nodes ... dying :-(\n"); + } + } else if ( strncmp(line, "vn ", 3) == 0 ) { + // vertex normal + if ( vncount < MAX_NODES ) { + // fgPrintf( FG_TERRAIN, FG_DEBUG, "vertex normal = %s", line); + sscanf(line, "vn %lf %lf %lf\n", + &normals[vncount][0], &normals[vncount][1], + &normals[vncount][2]); + vncount++; + } else { + fgPrintf( FG_TERRAIN, FG_EXIT, + "Read too many vertex normals ... dying :-(\n"); + } + } else if ( strncmp(line, "usemtl ", 7) == 0 ) { + // material property specification + + // this also signals the start of a new fragment + if ( in_fragment ) { + // close out the previous structure and start the next + xglEnd(); + xglEndList(); + + // update fragment + fragment.display_list = display_list; + + // push this fragment onto the tile's object list + t->fragment_list.push_back(fragment); + } else { + in_fragment = 1; + } + + display_list = xglGenLists(1); + xglNewList(display_list, GL_COMPILE); + in_faces = 0; + + // reset the existing face list + // printf("cleaning a fragment with %d faces\n", + // fragment.faces.size()); + while ( fragment.faces.size() ) { + // printf("emptying face list\n"); + fragment.faces.pop_front(); + } + + // scan the material line + sscanf(line, "usemtl %s\n", material); + + // give the fragment a pointer back to the tile + fragment.tile_ptr = t; + + // find this material in the properties list + map < string, fgMATERIAL, less > :: iterator myfind = + material_mgr.material_map.find(material); + if ( myfind == material_mgr.material_map.end() ) { + fgPrintf( FG_TERRAIN, FG_ALERT, + "Ack! unknown usemtl name = %s in %s\n", + material, path); + } else { + fragment.material_ptr = &((*myfind).second); + } + + // initialize the fragment transformation matrix + /* + for ( i = 0; i < 16; i++ ) { + fragment.matrix[i] = 0.0; + } + fragment.matrix[0] = fragment.matrix[5] = + fragment.matrix[10] = fragment.matrix[15] = 1.0; + */ + + // initialize fragment face counter + fragment.num_faces = 0; + + } else if ( line[0] == 't' ) { + // start a new triangle strip + + n1 = n2 = n3 = n4 = 0; + + // fgPrintf( FG_TERRAIN, FG_DEBUG, " new tri strip = %s", line); + sscanf(line, "t %d %d %d %d\n", &n1, &n2, &n3, &n4); + + fragment.add_face(n1, n2, n3); + + // fgPrintf( FG_TERRAIN, FG_DEBUG, "(t) = "); + + xglBegin(GL_TRIANGLE_STRIP); + + odd = 1; + scale = 1.0; + + if ( shading ) { + // Shading model is "GL_SMOOTH" so use precalculated + // (averaged) normals + MAT3_SCALE_VEC(normal, normals[n1], scale); + xglNormal3dv(normal); + pp = calc_tex_coords(nodes[n1], center); + xglTexCoord2f(pp.lon, pp.lat); + // xglVertex3d(t->nodes[n1][0],t->nodes[n1][1],t->nodes[n1][2]); + xglVertex3dv(nodes[n1]); + + MAT3_SCALE_VEC(normal, normals[n2], scale); + xglNormal3dv(normal); + pp = calc_tex_coords(nodes[n2], center); + xglTexCoord2f(pp.lon, pp.lat); + //xglVertex3d(t->nodes[n2][0],t->nodes[n2][1],t->nodes[n2][2]); + xglVertex3dv(nodes[n2]); + + MAT3_SCALE_VEC(normal, normals[n3], scale); + xglNormal3dv(normal); + pp = calc_tex_coords(nodes[n3], center); + xglTexCoord2f(pp.lon, pp.lat); + // xglVertex3d(t->nodes[n3][0],t->nodes[n3][1],t->nodes[n3][2]); + xglVertex3dv(nodes[n3]); + } else { + // Shading model is "GL_FLAT" so calculate per face + // normals on the fly. + if ( odd ) { + calc_normal(nodes[n1], nodes[n2], + nodes[n3], approx_normal); + } else { + calc_normal(nodes[n2], nodes[n1], + nodes[n3], approx_normal); + } + MAT3_SCALE_VEC(normal, approx_normal, scale); + xglNormal3dv(normal); + + pp = calc_tex_coords(nodes[n1], center); + xglTexCoord2f(pp.lon, pp.lat); + // xglVertex3d(t->nodes[n1][0],t->nodes[n1][1],t->nodes[n1][2]); + xglVertex3dv(nodes[n1]); + + pp = calc_tex_coords(nodes[n2], center); + xglTexCoord2f(pp.lon, pp.lat); + // xglVertex3d(t->nodes[n2][0],t->nodes[n2][1],t->nodes[n2][2]); + xglVertex3dv(nodes[n2]); + + pp = calc_tex_coords(nodes[n3], center); + xglTexCoord2f(pp.lon, pp.lat); + // xglVertex3d(t->nodes[n3][0],t->nodes[n3][1],t->nodes[n3][2]); + xglVertex3dv(nodes[n3]); + } + + odd = 1 - odd; + last1 = n2; + last2 = n3; + + if ( n4 > 0 ) { + fragment.add_face(n3, n2, n4); + + if ( shading ) { + // Shading model is "GL_SMOOTH" + MAT3_SCALE_VEC(normal, normals[n4], scale); + } else { + // Shading model is "GL_FLAT" + calc_normal(nodes[n3], nodes[n2], nodes[n4], + approx_normal); + MAT3_SCALE_VEC(normal, approx_normal, scale); + } + xglNormal3dv(normal); + pp = calc_tex_coords(nodes[n4], center); + xglTexCoord2f(pp.lon, pp.lat); + // xglVertex3d(t->nodes[n4][0],t->nodes[n4][1],t->nodes[n4][2]); + xglVertex3dv(nodes[n4]); + + odd = 1 - odd; + last1 = n3; + last2 = n4; + } + } else if ( line[0] == 'f' ) { + // unoptimized face + + if ( !in_faces ) { + xglBegin(GL_TRIANGLES); + in_faces = 1; + } + + // fgPrintf( FG_TERRAIN, FG_DEBUG, "new triangle = %s", line);*/ + sscanf(line, "f %d %d %d\n", &n1, &n2, &n3); + + fragment.add_face(n1, n2, n3); + + // xglNormal3d(normals[n1][0], normals[n1][1], normals[n1][2]); + xglNormal3dv(normals[n1]); + pp = calc_tex_coords(nodes[n1], center); + xglTexCoord2f(pp.lon, pp.lat); + // xglVertex3d(t->nodes[n1][0], t->nodes[n1][1], t->nodes[n1][2]); + xglVertex3dv(nodes[n1]); + + // xglNormal3d(normals[n2][0], normals[n2][1], normals[n2][2]); + xglNormal3dv(normals[n2]); + pp = calc_tex_coords(nodes[n2], center); + xglTexCoord2f(pp.lon, pp.lat); + // xglVertex3d(t->nodes[n2][0], t->nodes[n2][1], t->nodes[n2][2]); + xglVertex3dv(nodes[n2]); + + // xglNormal3d(normals[n3][0], normals[n3][1], normals[n3][2]); + xglNormal3dv(normals[n3]); + pp = calc_tex_coords(nodes[n3], center); + xglTexCoord2f(pp.lon, pp.lat); + // xglVertex3d(t->nodes[n3][0], t->nodes[n3][1], t->nodes[n3][2]); + xglVertex3dv(nodes[n3]); + } else if ( line[0] == 'q' ) { + // continue a triangle strip + n1 = n2 = 0; + + // fgPrintf( FG_TERRAIN, FG_DEBUG, "continued tri strip = %s ", + // line); + sscanf(line, "q %d %d\n", &n1, &n2); + // fgPrintf( FG_TERRAIN, FG_DEBUG, "read %d %d\n", n1, n2); + + if ( odd ) { + fragment.add_face(last1, last2, n1); + } else { + fragment.add_face(last2, last1, n1); + } + + if ( shading ) { + // Shading model is "GL_SMOOTH" + MAT3_SCALE_VEC(normal, normals[n1], scale); + xglNormal3dv(normal); + } else { + // Shading model is "GL_FLAT" + if ( odd ) { + calc_normal(nodes[last1], nodes[last2], nodes[n1], + approx_normal); + } else { + calc_normal(nodes[last2], nodes[last1], nodes[n1], + approx_normal); + } + MAT3_SCALE_VEC(normal, approx_normal, scale); + xglNormal3dv(normal); + } + + pp = calc_tex_coords(nodes[n1], center); + xglTexCoord2f(pp.lon, pp.lat); + // xglVertex3d(t->nodes[n1][0], t->nodes[n1][1], t->nodes[n1][2]); + xglVertex3dv(nodes[n1]); + + odd = 1 - odd; + last1 = last2; + last2 = n1; + + if ( n2 > 0 ) { + // fgPrintf( FG_TERRAIN, FG_DEBUG, " (cont)\n"); + + if ( odd ) { + fragment.add_face(last1, last2, n2); + } else { + fragment.add_face(last2, last1, n2); + } + + if ( shading ) { + // Shading model is "GL_SMOOTH" + MAT3_SCALE_VEC(normal, normals[n2], scale); + xglNormal3dv(normal); + } else { + // Shading model is "GL_FLAT" + if ( odd ) { + calc_normal(nodes[last1], nodes[last2], + nodes[n2], approx_normal); + } else { + calc_normal(nodes[last2], nodes[last1], + nodes[n2], approx_normal); + } + MAT3_SCALE_VEC(normal, approx_normal, scale); + xglNormal3dv(normal); + } + + pp = calc_tex_coords(nodes[n2], center); + xglTexCoord2f(pp.lon, pp.lat); + // xglVertex3d(t->nodes[n2][0],t->nodes[n2][1],t->nodes[n2][2]); + xglVertex3dv(nodes[n2]); + + odd = 1 -odd; + last1 = last2; + last2 = n2; + } + } else { + fgPrintf( FG_TERRAIN, FG_WARN, "Unknown line in %s = %s\n", + path, line); + } + } + + if ( in_fragment ) { + // close out the previous structure and start the next + xglEnd(); + xglEndList(); + + // update fragment + fragment.display_list = display_list; + + // push this fragment onto the tile's object list + t->fragment_list.push_back(fragment); + } + + // Draw normal vectors (for visually verifying normals) + /* + xglBegin(GL_LINES); + xglColor3f(0.0, 0.0, 0.0); + for ( i = 0; i < t->ncount; i++ ) { + xglVertex3d(t->nodes[i][0], + t->nodes[i][1] , + t->nodes[i][2]); + xglVertex3d(t->nodes[i][0] + 500*normals[i][0], + t->nodes[i][1] + 500*normals[i][1], + t->nodes[i][2] + 500*normals[i][2]); + } + xglEnd(); + */ + + fgclose(f); + + return(1); +} + + +// $Log$ +// Revision 1.1 1998/08/25 16:51:25 curt +// Moved from ../Scenery +// +// Revision 1.23 1998/08/20 15:16:43 curt +// obj.cxx: use more explicit parenthases. +// texload.[ch]: use const in function definitions where appropriate. +// +// Revision 1.22 1998/08/20 15:12:03 curt +// Used a forward declaration of classes fgTILE and fgMATERIAL to eliminate +// the need for "void" pointers and casts. +// Quick hack to count the number of scenery polygons that are being drawn. +// +// Revision 1.21 1998/08/12 21:13:04 curt +// material.cxx: don't load textures if they are disabled +// obj.cxx: optimizations from Norman Vine +// tile.cxx: minor tweaks +// tile.hxx: addition of num_faces +// tilemgr.cxx: minor tweaks +// +// Revision 1.20 1998/07/24 21:42:07 curt +// material.cxx: whups, double method declaration with no definition. +// obj.cxx: tweaks to avoid errors in SGI's CC. +// tile.cxx: optimizations by Norman Vine. +// tilemgr.cxx: optimizations by Norman Vine. +// +// Revision 1.19 1998/07/13 21:01:58 curt +// Wrote access functions for current fgOPTIONS. +// +// Revision 1.18 1998/07/12 03:18:27 curt +// Added ground collision detection. This involved: +// - saving the entire vertex list for each tile with the tile records. +// - saving the face list for each fragment with the fragment records. +// - code to intersect the current vertical line with the proper face in +// an efficient manner as possible. +// Fixed a bug where the tiles weren't being shifted to "near" (0,0,0) +// +// Revision 1.17 1998/07/08 14:47:21 curt +// Fix GL_MODULATE vs. GL_DECAL problem introduced by splash screen. +// polare3d.h renamed to polar3d.hxx +// fg{Cartesian,Polar}Point3d consolodated. +// Added some initial support for calculating local current ground elevation. +// +// Revision 1.16 1998/07/06 21:34:33 curt +// Added using namespace std for compilers that support this. +// +// Revision 1.15 1998/07/04 00:54:28 curt +// Added automatic mipmap generation. +// +// When rendering fragments, use saved model view matrix from associated tile +// rather than recalculating it with push() translate() pop(). +// +// Revision 1.14 1998/06/17 21:36:40 curt +// Load and manage multiple textures defined in the Materials library. +// Boost max material fagments for each material property to 800. +// Multiple texture support when rendering. +// +// Revision 1.13 1998/06/12 00:58:05 curt +// Build only static libraries. +// Declare memmove/memset for Sloaris. +// +// Revision 1.12 1998/06/08 17:57:54 curt +// Working first pass at material proporty sorting. +// +// Revision 1.11 1998/06/06 01:09:31 curt +// I goofed on the log message in the last commit ... now fixed. +// +// Revision 1.10 1998/06/06 01:07:17 curt +// Increased per material fragment list size from 100 to 400. +// Now correctly draw viewable fragments in per material order. +// +// Revision 1.9 1998/06/05 22:39:54 curt +// Working on sorting by, and rendering by material properties. +// +// Revision 1.8 1998/06/05 18:19:18 curt +// Recognize file, file.gz, and file.obj as scenery object files. +// +// Revision 1.7 1998/05/24 02:49:09 curt +// Implimented fragment level view frustum culling. +// +// Revision 1.6 1998/05/23 14:09:20 curt +// Added tile.cxx and tile.hxx. +// Working on rewriting the tile management system so a tile is just a list +// fragments, and the fragment record contains the display list for that +// fragment. +// +// Revision 1.5 1998/05/20 20:53:53 curt +// Moved global ref point and radius (bounding sphere info, and offset) to +// data file rather than calculating it on the fly. +// Fixed polygon winding problem in scenery generation stage rather than +// compensating for it on the fly. +// Made a fgTILECACHE class. +// +// Revision 1.4 1998/05/16 13:09:57 curt +// Beginning to add support for view frustum culling. +// Added some temporary code to calculate bouding radius, until the +// scenery generation tools and scenery can be updated. +// +// Revision 1.3 1998/05/03 00:48:01 curt +// Updated texture coordinate fmod() parameter. +// +// Revision 1.2 1998/05/02 01:52:14 curt +// Playing around with texture coordinates. +// +// Revision 1.1 1998/04/30 12:35:28 curt +// Added a command line rendering option specify smooth/flat shading. +// +// Revision 1.35 1998/04/28 21:43:26 curt +// Wrapped zlib calls up so we can conditionally comment out zlib support. +// +// Revision 1.34 1998/04/28 01:21:42 curt +// Tweaked texture parameter calculations to keep the number smaller. This +// avoids the "swimming" problem. +// Type-ified fgTIME and fgVIEW. +// +// Revision 1.33 1998/04/27 15:58:15 curt +// Screwing around with texture coordinate generation ... still needs work. +// +// Revision 1.32 1998/04/27 03:30:13 curt +// Minor transformation adjustments to try to keep scenery tiles closer to +// (0, 0, 0) GLfloats run out of precision at the distances we need to model +// the earth, but we can do a bunch of pre-transformations using double math +// and then cast to GLfloat once everything is close in where we have less +// precision problems. +// +// Revision 1.31 1998/04/25 15:09:57 curt +// Changed "r" to "rb" in gzopen() options. This fixes bad behavior in win32. +// +// Revision 1.30 1998/04/24 14:21:08 curt +// Added "file.obj.gz" support. +// +// Revision 1.29 1998/04/24 00:51:07 curt +// Wrapped "#include " in "#ifdef HAVE_CONFIG_H" +// Tweaked the scenery file extentions to be "file.obj" (uncompressed) +// or "file.obz" (compressed.) +// +// Revision 1.28 1998/04/22 13:22:44 curt +// C++ - ifing the code a bit. +// +// Revision 1.27 1998/04/18 04:13:17 curt +// Added zlib on the fly decompression support for loading scenery objects. +// +// Revision 1.26 1998/04/03 22:11:36 curt +// Converting to Gnu autoconf system. +// +// Revision 1.25 1998/03/14 00:30:50 curt +// Beginning initial terrain texturing experiments. +// +// Revision 1.24 1998/02/09 21:30:18 curt +// Fixed a nagging problem with terrain tiles not "quite" matching up perfectly. +// +// Revision 1.23 1998/02/09 15:07:52 curt +// Minor tweaks. +// +// Revision 1.22 1998/02/01 03:39:54 curt +// Minor tweaks. +// +// Revision 1.21 1998/01/31 00:43:25 curt +// Added MetroWorks patches from Carmen Volpe. +// +// Revision 1.20 1998/01/29 00:51:39 curt +// First pass at tile cache, dynamic tile loading and tile unloading now works. +// +// Revision 1.19 1998/01/27 03:26:42 curt +// Playing with new fgPrintf command. +// +// Revision 1.18 1998/01/19 19:27:16 curt +// Merged in make system changes from Bob Kuehne +// This should simplify things tremendously. +// +// Revision 1.17 1998/01/13 00:23:10 curt +// Initial changes to support loading and management of scenery tiles. Note, +// there's still a fair amount of work left to be done. +// +// Revision 1.16 1997/12/30 23:09:40 curt +// Worked on winding problem without luck, so back to calling glFrontFace() +// 3 times for each scenery area. +// +// Revision 1.15 1997/12/30 20:47:51 curt +// Integrated new event manager with subsystem initializations. +// +// Revision 1.14 1997/12/30 01:38:46 curt +// Switched back to per vertex normals and smooth shading for terrain. +// +// Revision 1.13 1997/12/18 23:32:36 curt +// First stab at sky dome actually starting to look reasonable. :-) +// +// Revision 1.12 1997/12/17 23:13:47 curt +// Began working on rendering the sky. +// +// Revision 1.11 1997/12/15 23:55:01 curt +// Add xgl wrappers for debugging. +// Generate terrain normals on the fly. +// +// Revision 1.10 1997/12/12 21:41:28 curt +// More light/material property tweaking ... still a ways off. +// +// Revision 1.9 1997/12/12 19:52:57 curt +// Working on lightling and material properties. +// +// Revision 1.8 1997/12/10 01:19:51 curt +// Tweaks for verion 0.15 release. +// +// Revision 1.7 1997/12/08 22:51:17 curt +// Enhanced to handle ccw and cw tri-stripe winding. This is a temporary +// admission of defeat. I will eventually go back and get all the stripes +// wound the same way (ccw). +// +// Revision 1.6 1997/11/25 19:25:35 curt +// Changes to integrate Durk's moon/sun code updates + clean up. +// +// Revision 1.5 1997/11/15 18:16:39 curt +// minor tweaks. +// +// Revision 1.4 1997/11/14 00:26:49 curt +// Transform scenery coordinates earlier in pipeline when scenery is being +// created, not when it is being loaded. Precalculate normals for each node +// as average of the normals of each containing polygon so Garoude shading is +// now supportable. +// +// Revision 1.3 1997/10/31 04:49:12 curt +// Tweaking vertex orders. +// +// Revision 1.2 1997/10/30 12:38:45 curt +// Working on new scenery subsystem. +// +// Revision 1.1 1997/10/28 21:14:54 curt +// Initial revision. + + diff --git a/Objects/obj.hxx b/Objects/obj.hxx new file mode 100644 index 000000000..96c6aedfd --- /dev/null +++ b/Objects/obj.hxx @@ -0,0 +1,112 @@ +// obj.hxx -- routines to handle WaveFront .obj-ish format files. +// +// Written by Curtis Olson, started October 1997. +// +// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// $Id$ +// (Log is kept at end of this file) + + +#ifndef _OBJ_HXX +#define _OBJ_HXX + + +#ifndef __cplusplus +# error This library requires C++ +#endif + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_WINDOWS_H +# include +#endif + +#include + +#include + +#include + + +// Load a .obj file and build the GL fragment list +int fgObjLoad(char *path, fgTILE *tile); + + +#endif // _OBJ_HXX + + +// $Log$ +// Revision 1.1 1998/08/25 16:51:26 curt +// Moved from ../Scenery +// +// Revision 1.4 1998/05/24 02:49:10 curt +// Implimented fragment level view frustum culling. +// +// Revision 1.3 1998/05/23 14:09:21 curt +// Added tile.cxx and tile.hxx. +// Working on rewriting the tile management system so a tile is just a list +// fragments, and the fragment record contains the display list for that +// fragment. +// +// Revision 1.2 1998/05/02 01:52:15 curt +// Playing around with texture coordinates. +// +// Revision 1.1 1998/04/30 12:35:29 curt +// Added a command line rendering option specify smooth/flat shading. +// +// Revision 1.11 1998/04/25 22:06:31 curt +// Edited cvs log messages in source files ... bad bad bad! +// +// Revision 1.10 1998/04/24 00:51:07 curt +// Wrapped "#include " in "#ifdef HAVE_CONFIG_H" +// Tweaked the scenery file extentions to be "file.obj" (uncompressed) +// or "file.obz" (compressed.) +// +// Revision 1.9 1998/04/22 13:22:45 curt +// C++ - ifing the code a bit. +// +// Revision 1.8 1998/04/21 17:02:43 curt +// Prepairing for C++ integration. +// +// Revision 1.7 1998/04/03 22:11:37 curt +// Converting to Gnu autoconf system. +// +// Revision 1.6 1998/01/31 00:43:25 curt +// Added MetroWorks patches from Carmen Volpe. +// +// Revision 1.5 1998/01/27 00:48:03 curt +// Incorporated Paul Bleisch's new debug message +// system and commandline/config file processing code. +// +// Revision 1.4 1998/01/22 02:59:41 curt +// Changed #ifdef FILE_H to #ifdef _FILE_H +// +// Revision 1.3 1998/01/19 19:27:17 curt +// Merged in make system changes from Bob Kuehne +// This should simplify things tremendously. +// +// Revision 1.2 1998/01/13 00:23:10 curt +// Initial changes to support loading and management of scenery tiles. Note, +// there's still a fair amount of work left to be done. +// +// Revision 1.1 1997/10/28 21:14:55 curt +// Initial revision. + diff --git a/Objects/texload.c b/Objects/texload.c new file mode 100644 index 000000000..e6ebbb137 --- /dev/null +++ b/Objects/texload.c @@ -0,0 +1,273 @@ + +/* texture.c - by David Blythe, SGI */ + +/* texload is a simplistic routine for reading an SGI .rgb image file. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_WINDOWS_H +# include +#endif + +#include +#include +#include + +#include + +#include "texload.h" + +typedef struct _ImageRec { + unsigned short imagic; + unsigned short type; + unsigned short dim; + unsigned short xsize, ysize, zsize; + unsigned int min, max; + unsigned int wasteBytes; + char name[80]; + unsigned long colorMap; + fgFile file; + unsigned char *tmp; + unsigned long rleEnd; + unsigned int *rowStart; + int *rowSize; +} ImageRec; + +void +rgbtorgb(unsigned char *r,unsigned char *g,unsigned char *b,unsigned char *l,int n) { + while(n--) { + l[0] = r[0]; + l[1] = g[0]; + l[2] = b[0]; + l += 3; r++; g++; b++; + } +} + +static void +ConvertShort(unsigned short *array, unsigned int length) { + unsigned short b1, b2; + unsigned char *ptr; + + ptr = (unsigned char *)array; + while (length--) { + b1 = *ptr++; + b2 = *ptr++; + *array++ = (b1 << 8) | (b2); + } +} + +static void +ConvertUint(unsigned *array, unsigned int length) { + unsigned int b1, b2, b3, b4; + unsigned char *ptr; + + ptr = (unsigned char *)array; + while (length--) { + b1 = *ptr++; + b2 = *ptr++; + b3 = *ptr++; + b4 = *ptr++; + *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4); + } +} + +static ImageRec *ImageOpen(const char *fileName) +{ + union { + int testWord; + char testByte[4]; + } endianTest; + + ImageRec *image; + int swapFlag; + int x; + + endianTest.testWord = 1; + if (endianTest.testByte[0] == 1) { + swapFlag = 1; + } else { + swapFlag = 0; + } + + image = (ImageRec *)malloc(sizeof(ImageRec)); + if (image == NULL) { + fprintf(stderr, "Out of memory!\n"); + exit(1); + } + if ((image->file = fgopen(fileName, "rb")) == NULL) { + return NULL; + } + + // fread(image, 1, 12, image->file); + fgread(image->file, image, 12); + + if (swapFlag) { + ConvertShort(&image->imagic, 6); + } + + image->tmp = (unsigned char *)malloc(image->xsize*256); + if (image->tmp == NULL) { + fprintf(stderr, "\nOut of memory!\n"); + exit(1); + } + + if ((image->type & 0xFF00) == 0x0100) { + x = image->ysize * image->zsize * (int) sizeof(unsigned); + image->rowStart = (unsigned *)malloc(x); + image->rowSize = (int *)malloc(x); + if (image->rowStart == NULL || image->rowSize == NULL) { + fprintf(stderr, "\nOut of memory!\n"); + exit(1); + } + image->rleEnd = 512 + (2 * x); + fgseek(image->file, 512, SEEK_SET); + // fread(image->rowStart, 1, x, image->file); + fgread(image->file, image->rowStart, x); + // fread(image->rowSize, 1, x, image->file); + fgread(image->file, image->rowSize, x); + if (swapFlag) { + ConvertUint(image->rowStart, x/(int) sizeof(unsigned)); + ConvertUint((unsigned *)image->rowSize, x/(int) sizeof(int)); + } + } + return image; +} + +static void +ImageClose(ImageRec *image) { + fgclose(image->file); + free(image->tmp); + free(image); +} + +static void +ImageGetRow(ImageRec *image, unsigned char *buf, int y, int z) { + unsigned char *iPtr, *oPtr, pixel; + int count; + + if ((image->type & 0xFF00) == 0x0100) { + fgseek(image->file, (long) image->rowStart[y+z*image->ysize], SEEK_SET); + // fread(image->tmp, 1, (unsigned int)image->rowSize[y+z*image->ysize], + // image->file); + fgread(image->file, image->tmp, + (unsigned int)image->rowSize[y+z*image->ysize]); + + iPtr = image->tmp; + oPtr = buf; + for (;;) { + pixel = *iPtr++; + count = (int)(pixel & 0x7F); + if (!count) { + return; + } + if (pixel & 0x80) { + while (count--) { + *oPtr++ = *iPtr++; + } + } else { + pixel = *iPtr++; + while (count--) { + *oPtr++ = pixel; + } + } + } + } else { + fgseek(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize), + SEEK_SET); + // fread(buf, 1, image->xsize, image->file); + fgread(image->file, buf, image->xsize); + } +} + +GLubyte * +read_alpha_texture(const char *name, int *width, int *height) +{ + unsigned char *base, *lptr; + ImageRec *image; + int y; + + image = ImageOpen(name); + if(!image) { + return NULL; + } + + (*width)=image->xsize; + (*height)=image->ysize; + + printf("image->zsize = %d\n", image->zsize); + + if (image->zsize != 1) { + ImageClose(image); + return NULL; + } + + base = (unsigned char *)malloc(image->xsize*image->ysize*sizeof(unsigned char)); + lptr = base; + for(y=0; yysize; y++) { + ImageGetRow(image,lptr,y,0); + lptr += image->xsize; + } + ImageClose(image); + + return (unsigned char *) base; +} + +GLubyte * +read_rgb_texture(const char *name, int *width, int *height) +{ + unsigned char *base, *ptr; + unsigned char *rbuf, *gbuf, *bbuf, *abuf; + ImageRec *image; + int y; + + image = ImageOpen(name); + + if(!image) + return NULL; + (*width)=image->xsize; + (*height)=image->ysize; + if (image->zsize != 3 && image->zsize != 4) { + ImageClose(image); + return NULL; + } + + base = (unsigned char*)malloc(image->xsize*image->ysize*sizeof(unsigned int)*3); + rbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char)); + gbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char)); + bbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char)); + abuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char)); + if(!base || !rbuf || !gbuf || !bbuf || !abuf) { + if (base) free(base); + if (rbuf) free(rbuf); + if (gbuf) free(gbuf); + if (bbuf) free(bbuf); + if (abuf) free(abuf); + return NULL; + } + ptr = base; + for(y=0; yysize; y++) { + if(image->zsize == 4) { + ImageGetRow(image,rbuf,y,0); + ImageGetRow(image,gbuf,y,1); + ImageGetRow(image,bbuf,y,2); + ImageGetRow(image,abuf,y,3); /* Discard. */ + rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize); + ptr += (image->xsize * 3); + } else { + ImageGetRow(image,rbuf,y,0); + ImageGetRow(image,gbuf,y,1); + ImageGetRow(image,bbuf,y,2); + rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize); + ptr += (image->xsize * 3); + } + } + ImageClose(image); + free(rbuf); + free(gbuf); + free(bbuf); + free(abuf); + + return (GLubyte *) base; +} diff --git a/Objects/texload.h b/Objects/texload.h new file mode 100644 index 000000000..e15e025cf --- /dev/null +++ b/Objects/texload.h @@ -0,0 +1,30 @@ + +/* Copyright (c) Mark J. Kilgard, 1997. */ + +/* This program is freely distributable without licensing fees + and is provided without guarantee or warrantee expressed or + implied. This program is -not- in the public domain. */ + + +#ifndef _TEXLOAD_H +#define _TEXLOAD_H + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +extern GLubyte *read_alpha_texture(const char *name, int *width, int *height); +extern GLubyte * read_rgb_texture(const char *name, int *width, int *height); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _TEXLOAD_H */