├── LICENSE ├── Manifest.txt ├── NFF.TXT ├── README.md ├── Readme.txt ├── docs ├── NFF.TXT ├── balls.gif ├── balls.png ├── gears.gif ├── gears.png ├── havran_stats_grids.txt ├── havran_stats_octrees.txt ├── index.html ├── jenkins.jpg ├── mount.gif ├── mount.png ├── new.jpg ├── old.jpg ├── rings.gif ├── rings.png ├── teapot.gif ├── teapot.png ├── tetra.gif ├── tetra.png ├── tree.gif └── tree.png └── src ├── balls.c ├── def.h ├── drv.h ├── drv_dos.c ├── drv_hp.c ├── drv_mac.c ├── drv_null.c ├── drv_x11.c ├── gears.c ├── jacks.c ├── lattice.c ├── lib.h ├── libdmp.c ├── libinf.c ├── libini.c ├── libply.c ├── libpr1.c ├── libpr2.c ├── libpr3.c ├── libtx.c ├── libvec.c ├── libvec.h ├── makefile ├── makefile.dj ├── makefile.dos ├── makefile.hp ├── makefile.nul ├── makefile.x11 ├── mount.c ├── nff2rad.c ├── nurbtst.c ├── readdxf.c ├── readnff.c ├── readobj.c ├── rings.c ├── sample.c ├── shells.c ├── sombrero.c ├── spd.sl ├── teapot.c ├── tetra.c ├── tree.c └── view.dat /LICENSE: -------------------------------------------------------------------------------- 1 | This code is in the public domain using the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication, https://creativecommons.org/publicdomain/zero/1.0/, as shown here: 2 | 3 | The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. 4 | 5 | You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. 6 | 7 | * In no way are the patent or trademark rights of any person affected by CC0, nor are the rights that other persons may have in the work or in how the work is used, such as publicity or privacy rights. 8 | * Unless expressly stated otherwise, the person who associated a work with this deed makes no warranties about the work, and disclaims liability for all uses of the work, to the fullest extent permitted by applicable law. 9 | * When using or citing the work, you should not imply endorsement by the author or the affirmer. 10 | 11 | 12 | 13 | If this license does not apply in a country or is otherwise unrecognized, then the 14 | code is licensed under the MIT license, https://opensource.org/licenses/MIT. See the logic for this: http://www.realtimerendering.com/blog/cc0-public-domain-for-the-world/. That is: 15 | 16 | 17 | 18 | 19 | The MIT License (MIT) 20 | 21 | Copyright (c) 2015 Eric Haines 22 | 23 | Permission is hereby granted, free of charge, to any person obtaining a copy 24 | of this software and associated documentation files (the "Software"), to deal 25 | in the Software without restriction, including without limitation the rights 26 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 27 | copies of the Software, and to permit persons to whom the Software is 28 | furnished to do so, subject to the following conditions: 29 | 30 | The above copyright notice and this permission notice shall be included in all 31 | copies or substantial portions of the Software. 32 | 33 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 34 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 35 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 36 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 37 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 38 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 39 | SOFTWARE. 40 | 41 | -------------------------------------------------------------------------------- /Manifest.txt: -------------------------------------------------------------------------------- 1 | The SPD distribution contains the following files: 2 | 3 | Manifest.txt - what you are now reading 4 | Readme.txt - readme file for what the SPD is about 5 | NFF.txt - a description of the Neutral File Format used in the SPD 6 | /docs - the web page at http://www.realtimerendering.com/resources/SPD/ 7 | 8 | makefile - generic makefile (no display possible), same as null makefile 9 | makefile.dj - IBM PC DJGPP+GRX makefile 10 | makefile.dos - IBM PC DOS generic makefile 11 | makefile.hp - Hewlett Packard HPUX makefile (includes X11 displayer) 12 | makefile.nul - null makefile (default generic) 13 | makefile.x11 - X11R6 makefile 14 | 15 | def.h - some useful "C" definitions 16 | lib.h - globals and conversion/output library routine declarations 17 | libdmp.c - library of post-process dump routines 18 | libinf.c - library of info routines 19 | libini.c - library of initialization routines 20 | libply.c - library of polygon face routines 21 | libpr1.c - library of general shape primitive routines, basic support 22 | libpr2.c - library of general shape primitive routines, simple 23 | libpr3.c - library of general shape primitive routines, more complex 24 | libtx.c - library of texturing support routines 25 | libvec.c - library of vector & matrix routines 26 | libvec.h - vector & matrix library defines and routine declarations 27 | 28 | nff2rad.c - NFF to Radiance format converter by Greg Ward 29 | 30 | balls.c - fractal ball object (a.k.a. sphereflake) generator 31 | gears.c - 3D array of interlocking gears generator 32 | mount.c - fractal mountain and 4 glass ball generator 33 | rings.c - pyramid of dodecahedral rings generator 34 | teapot.c - the famous teapot on a checkerboard generator 35 | tetra.c - recursive tetrahedra generator 36 | tree.c - tree generator 37 | 38 | drv.h - display driver definitions 39 | drv_hp.c - HP Starbase/X11 display driver 40 | drv_ibm.c - IBM PC VGA display driver 41 | drv_mac.c - Macintosh display driver 42 | drv_null.c - generic driver template (usable, but does not display) 43 | drv_x11.c - X11R6 graphics display driver 44 | 45 | readdxf.c - DXF file reader/displayer/converter 46 | readnff.c - NFF file reader/displayer/converter 47 | readobj.c - Wavefront OBJ file reader/displayer/converter 48 | view.dat - view for DXF and OBJ displayer 49 | spd.sl - material for RIB export 50 | 51 | sample.c - an example file showing a simple scene 52 | lattice.c - cubic lattice generator 53 | shells.c - "shell" generator (but don't try to look inside!) 54 | sombrero.c - hat function heightfield output example 55 | jacks.c - recursive jacks 56 | nurbtst.c - NURBS routine tester 57 | 58 | [end] 59 | -------------------------------------------------------------------------------- /NFF.TXT: -------------------------------------------------------------------------------- 1 | Neutral File Format, 2 | by Eric Haines, Autodesk, 1050 Craft Road, Ithaca, NY 14850 3 | email: erich@acm.org 4 | 5 | Draft #1, 10/3/88 6 | Version 2.7, as of 5/22/90 - added information on hither, light color 7 | Version 3.0, 12/17/90 - minor information changes 8 | Version 3.1, 11/2/92 - more minor information changes 9 | Version 3.9, 12/4/96 - minor changes in introduction 10 | 11 | The NFF (Neutral File Format) is designed as a minimal scene description 12 | language. The language was designed in order to test various rendering 13 | algorithms and efficiency schemes. It is meant to describe the geometry and 14 | basic surface characteristics of objects, the placement of lights, and the 15 | viewing frustum for the eye. Some additional information is provided for 16 | aesthetic reasons (such as the color of the objects, which is not strictly 17 | necessary for testing the efficiency of rendering algorithms). 18 | 19 | At present the NFF file format is used in conjunction with the SPD (Standard 20 | Procedural Database) software, a package designed to create a variety of 21 | databases for testing rendering schemes. For more information about SPD see 22 | "A Proposal for Standard Graphics Environments," IEEE Computer Graphics and 23 | Applications, vol. 7, no. 11, November 1987, pp. 3-5. See IEEE CG&A, vol. 8, 24 | no. 1, January 1988, p. 18 for the correct image of the tree database (the 25 | only difference is that the sky is blue, not orange). 26 | 27 | The SPD package (along with images of the databases) is available from: 28 | 29 | http://www.acm.org/tog/resources/SPD/ 30 | 31 | NFF is meant for testing efficiency schemes and so has minimal support for 32 | lighting and shading. For a reasonable scene description language, see VRML. 33 | 34 | By providing a minimal interface, NFF is meant to act as a simple format to 35 | allow the programmer to quickly write filters to move from NFF to the 36 | local file format. Presently the following entities are supported: 37 | A simple perspective frustum 38 | A background color description 39 | A positional (vs. directional) light source description 40 | A surface properties description 41 | Polygon, polygonal patch, cylinder/cone, and sphere descriptions 42 | 43 | Files are output as lines of text. For each entity, the first field defines 44 | its type. The rest of the line and possibly other lines contain further 45 | information about the entity. Entities include: 46 | 47 | "v" - viewing vectors and angles 48 | "b" - background color 49 | "l" - positional light location 50 | "f" - object material properties 51 | "c" - cone or cylinder primitive 52 | "s" - sphere primitive 53 | "p" - polygon primitive 54 | "pp" - polygonal patch primitive 55 | 56 | 57 | These are explained in depth below. 58 | 59 | -------- 60 | 61 | Viewpoint location. Description: 62 | "v" 63 | "from" Fx Fy Fz 64 | "at" Ax Ay Az 65 | "up" Ux Uy Uz 66 | "angle" angle 67 | "hither" hither 68 | "resolution" xres yres 69 | 70 | Format: 71 | 72 | v 73 | from %g %g %g 74 | at %g %g %g 75 | up %g %g %g 76 | angle %g 77 | hither %g 78 | resolution %d %d 79 | 80 | The parameters are: 81 | 82 | From: the eye location in XYZ. 83 | At: a position to be at the center of the image, in XYZ world 84 | coordinates. A.k.a. "lookat". 85 | Up: a vector defining which direction is up, as an XYZ vector. 86 | Angle: in degrees, defined as from the center of top pixel row to 87 | bottom pixel row and left column to right column. 88 | Hither: distance of the hither plane (if any) from the eye. Mostly 89 | needed for hidden surface algorithms. 90 | Resolution: in pixels, in x and in y. 91 | 92 | Note that no assumptions are made about normalizing the data (e.g. the 93 | from-at distance does not have to be 1). Also, vectors are not 94 | required to be perpendicular to each other. 95 | 96 | For all databases some viewing parameters are always the same: 97 | Yon is "at infinity." 98 | Aspect ratio is 1.0. 99 | 100 | A view entity must be defined before any objects are defined (this 101 | requirement is so that NFF files can be displayed on the fly by hidden 102 | surface machines). 103 | 104 | -------- 105 | 106 | Background color. A color is simply RGB with values between 0 and 1: 107 | "b" R G B 108 | 109 | Format: 110 | b %g %g %g 111 | 112 | If no background color is set, assume RGB = {0,0,0}. 113 | 114 | -------- 115 | 116 | Positional light. A light is defined by XYZ position. Description: 117 | "l" X Y Z [R G B] 118 | 119 | Format: 120 | l %g %g %g [%g %g %g] 121 | 122 | All light entities must be defined before any objects are defined (this 123 | requirement is so that NFF files can be used by hidden surface machines). 124 | Lights have a non-zero intensity of no particular value, if not specified 125 | (i.e. the program can determine a useful intensity as desired); the 126 | red/green/blue color of the light can optionally be specified. 127 | 128 | -------- 129 | 130 | Fill color and shading parameters. Description: 131 | "f" red green blue Kd Ks Shine T index_of_refraction 132 | 133 | Format: 134 | f %g %g %g %g %g %g %g %g 135 | 136 | RGB is in terms of 0.0 to 1.0. 137 | 138 | Kd is the diffuse component, Ks the specular, Shine is the Phong cosine 139 | power for highlights, T is transmittance (fraction of contribution of the 140 | transmitting ray). Usually, 0 <= Kd <= 1 and 0 <= Ks <= 1, though it is 141 | not required that Kd + Ks == 1. Note that transmitting objects ( T > 0 ) 142 | are considered to have two sides for algorithms that need these (normally 143 | objects have one side). 144 | 145 | The fill color is used to color the objects following it until a new color 146 | is assigned. 147 | 148 | -------- 149 | 150 | Objects: all objects are considered one-sided, unless the second side is 151 | needed for transmittance calculations (e.g. you cannot throw out the second 152 | intersection of a transparent sphere in ray tracing). 153 | 154 | Cylinder or cone. A cylinder is defined as having a radius and an axis 155 | defined by two points, which also define the top and bottom edge of the 156 | cylinder. A cone is defined similarly, the difference being that the apex 157 | and base radii are different. The apex radius is defined as being smaller 158 | than the base radius. Note that the surface exists without endcaps. The 159 | cone or cylinder description: 160 | 161 | "c" 162 | base.x base.y base.z base_radius 163 | apex.x apex.y apex.z apex_radius 164 | 165 | Format: 166 | c 167 | %g %g %g %g 168 | %g %g %g %g 169 | 170 | A negative value for both radii means that only the inside of the object is 171 | visible (objects are normally considered one sided, with the outside 172 | visible). Note that the base and apex cannot be coincident for a cylinder 173 | or cone. Making them coincident could be used to define endcaps, but none 174 | of the SPD scenes currently make use of this definition. 175 | 176 | -------- 177 | 178 | Sphere. A sphere is defined by a radius and center position: 179 | "s" center.x center.y center.z radius 180 | 181 | Format: 182 | s %g %g %g %g 183 | 184 | If the radius is negative, then only the sphere's inside is visible 185 | (objects are normally considered one sided, with the outside visible). 186 | Currently none of the SPD scenes make use of negative radii. 187 | 188 | -------- 189 | 190 | Polygon. A polygon is defined by a set of vertices. With these databases, 191 | a polygon is defined to have all points coplanar. A polygon has only 192 | one side, with the order of the vertices being counterclockwise as you 193 | face the polygon (right-handed coordinate system). The first two edges 194 | must form a non-zero convex angle, so that the normal and side visibility 195 | can be determined by using just the first three vertices. Description: 196 | 197 | "p" total_vertices 198 | vert1.x vert1.y vert1.z 199 | [etc. for total_vertices vertices] 200 | 201 | Format: 202 | p %d 203 | [ %g %g %g ] <-- for total_vertices vertices 204 | 205 | -------- 206 | 207 | Polygonal patch. A patch is defined by a set of vertices and their normals. 208 | With these databases, a patch is defined to have all points coplanar. 209 | A patch has only one side, with the order of the vertices being 210 | counterclockwise as you face the patch (right-handed coordinate system). 211 | The first two edges must form a non-zero convex angle, so that the normal 212 | and side visibility can be determined. Description: 213 | 214 | "pp" total_vertices 215 | vert1.x vert1.y vert1.z norm1.x norm1.y norm1.z 216 | [etc. for total_vertices vertices] 217 | 218 | Format: 219 | pp %d 220 | [ %g %g %g %g %g %g ] <-- for total_vertices vertices 221 | 222 | -------- 223 | 224 | Comment. Description: 225 | "#" [ string ] 226 | 227 | Format: 228 | # [ string ] 229 | 230 | As soon as a "#" character is detected, the rest of the line is considered 231 | a comment. 232 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # StandardProceduralDatabases 2 | This software is meant to act as a set of basic test images for ray tracing algorithms. 3 | 4 | See [this page](http://www.realtimerendering.com/resources/SPD/) for more information. 5 | 6 | License 7 | ------- 8 | 9 | This code is in the public domain using the [CC0 1.0 Universal (CC0 1.0) Public Domain Dedication](https://creativecommons.org/publicdomain/zero/1.0/), as shown here: 10 | 11 | > The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. 12 | > 13 | > You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. 14 | > 15 | > * In no way are the patent or trademark rights of any person affected by CC0, nor are the rights that other persons may have in the work or in how the work is used, such as publicity or privacy rights. 16 | > * Unless expressly stated otherwise, the person who associated a work with this deed makes no warranties about the work, and disclaims liability for all uses of the work, to the fullest extent permitted by applicable law. 17 | > * When using or citing the work, you should not imply endorsement by the author or the affirmer. 18 | 19 | If this license does not apply in a country or is otherwise unrecognized, then the 20 | code is licensed under the [MIT license](https://opensource.org/licenses/MIT) (see [the logic for this](http://www.realtimerendering.com/blog/cc0-public-domain-for-the-world/)). That is: 21 | 22 | > Copyright (c) 2015 Eric Haines 23 | > 24 | > Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 25 | > 26 | > The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 27 | > 28 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /docs/NFF.TXT: -------------------------------------------------------------------------------- 1 | Neutral File Format, 2 | by Eric Haines, Autodesk, 1050 Craft Road, Ithaca, NY 14850 3 | email: erich@acm.org 4 | 5 | Draft #1, 10/3/88 6 | Version 2.7, as of 5/22/90 - added information on hither, light color 7 | Version 3.0, 12/17/90 - minor information changes 8 | Version 3.1, 11/2/92 - more minor information changes 9 | Version 3.9, 12/4/96 - minor changes in introduction 10 | 11 | The NFF (Neutral File Format) is designed as a minimal scene description 12 | language. The language was designed in order to test various rendering 13 | algorithms and efficiency schemes. It is meant to describe the geometry and 14 | basic surface characteristics of objects, the placement of lights, and the 15 | viewing frustum for the eye. Some additional information is provided for 16 | aesthetic reasons (such as the color of the objects, which is not strictly 17 | necessary for testing the efficiency of rendering algorithms). 18 | 19 | At present the NFF file format is used in conjunction with the SPD (Standard 20 | Procedural Database) software, a package designed to create a variety of 21 | databases for testing rendering schemes. For more information about SPD see 22 | "A Proposal for Standard Graphics Environments," IEEE Computer Graphics and 23 | Applications, vol. 7, no. 11, November 1987, pp. 3-5. See IEEE CG&A, vol. 8, 24 | no. 1, January 1988, p. 18 for the correct image of the tree database (the 25 | only difference is that the sky is blue, not orange). 26 | 27 | The SPD package (along with images of the databases) is available from: 28 | 29 | http://www.acm.org/tog/resources/SPD/ 30 | 31 | NFF is meant for testing efficiency schemes and so has minimal support for 32 | lighting and shading. For a reasonable scene description language, see VRML. 33 | 34 | By providing a minimal interface, NFF is meant to act as a simple format to 35 | allow the programmer to quickly write filters to move from NFF to the 36 | local file format. Presently the following entities are supported: 37 | A simple perspective frustum 38 | A background color description 39 | A positional (vs. directional) light source description 40 | A surface properties description 41 | Polygon, polygonal patch, cylinder/cone, and sphere descriptions 42 | 43 | Files are output as lines of text. For each entity, the first field defines 44 | its type. The rest of the line and possibly other lines contain further 45 | information about the entity. Entities include: 46 | 47 | "v" - viewing vectors and angles 48 | "b" - background color 49 | "l" - positional light location 50 | "f" - object material properties 51 | "c" - cone or cylinder primitive 52 | "s" - sphere primitive 53 | "p" - polygon primitive 54 | "pp" - polygonal patch primitive 55 | 56 | 57 | These are explained in depth below. 58 | 59 | -------- 60 | 61 | Viewpoint location. Description: 62 | "v" 63 | "from" Fx Fy Fz 64 | "at" Ax Ay Az 65 | "up" Ux Uy Uz 66 | "angle" angle 67 | "hither" hither 68 | "resolution" xres yres 69 | 70 | Format: 71 | 72 | v 73 | from %g %g %g 74 | at %g %g %g 75 | up %g %g %g 76 | angle %g 77 | hither %g 78 | resolution %d %d 79 | 80 | The parameters are: 81 | 82 | From: the eye location in XYZ. 83 | At: a position to be at the center of the image, in XYZ world 84 | coordinates. A.k.a. "lookat". 85 | Up: a vector defining which direction is up, as an XYZ vector. 86 | Angle: in degrees, defined as from the center of top pixel row to 87 | bottom pixel row and left column to right column. 88 | Hither: distance of the hither plane (if any) from the eye. Mostly 89 | needed for hidden surface algorithms. 90 | Resolution: in pixels, in x and in y. 91 | 92 | Note that no assumptions are made about normalizing the data (e.g. the 93 | from-at distance does not have to be 1). Also, vectors are not 94 | required to be perpendicular to each other. 95 | 96 | For all databases some viewing parameters are always the same: 97 | Yon is "at infinity." 98 | Aspect ratio is 1.0. 99 | 100 | A view entity must be defined before any objects are defined (this 101 | requirement is so that NFF files can be displayed on the fly by hidden 102 | surface machines). 103 | 104 | -------- 105 | 106 | Background color. A color is simply RGB with values between 0 and 1: 107 | "b" R G B 108 | 109 | Format: 110 | b %g %g %g 111 | 112 | If no background color is set, assume RGB = {0,0,0}. 113 | 114 | -------- 115 | 116 | Positional light. A light is defined by XYZ position. Description: 117 | "l" X Y Z [R G B] 118 | 119 | Format: 120 | l %g %g %g [%g %g %g] 121 | 122 | All light entities must be defined before any objects are defined (this 123 | requirement is so that NFF files can be used by hidden surface machines). 124 | Lights have a non-zero intensity of no particular value, if not specified 125 | (i.e. the program can determine a useful intensity as desired); the 126 | red/green/blue color of the light can optionally be specified. 127 | 128 | -------- 129 | 130 | Fill color and shading parameters. Description: 131 | "f" red green blue Kd Ks Shine T index_of_refraction 132 | 133 | Format: 134 | f %g %g %g %g %g %g %g %g 135 | 136 | RGB is in terms of 0.0 to 1.0. 137 | 138 | Kd is the diffuse component, Ks the specular, Shine is the Phong cosine 139 | power for highlights, T is transmittance (fraction of contribution of the 140 | transmitting ray). Usually, 0 <= Kd <= 1 and 0 <= Ks <= 1, though it is 141 | not required that Kd + Ks == 1. Note that transmitting objects ( T > 0 ) 142 | are considered to have two sides for algorithms that need these (normally 143 | objects have one side). 144 | 145 | The fill color is used to color the objects following it until a new color 146 | is assigned. 147 | 148 | -------- 149 | 150 | Objects: all objects are considered one-sided, unless the second side is 151 | needed for transmittance calculations (e.g. you cannot throw out the second 152 | intersection of a transparent sphere in ray tracing). 153 | 154 | Cylinder or cone. A cylinder is defined as having a radius and an axis 155 | defined by two points, which also define the top and bottom edge of the 156 | cylinder. A cone is defined similarly, the difference being that the apex 157 | and base radii are different. The apex radius is defined as being smaller 158 | than the base radius. Note that the surface exists without endcaps. The 159 | cone or cylinder description: 160 | 161 | "c" 162 | base.x base.y base.z base_radius 163 | apex.x apex.y apex.z apex_radius 164 | 165 | Format: 166 | c 167 | %g %g %g %g 168 | %g %g %g %g 169 | 170 | A negative value for both radii means that only the inside of the object is 171 | visible (objects are normally considered one sided, with the outside 172 | visible). Note that the base and apex cannot be coincident for a cylinder 173 | or cone. Making them coincident could be used to define endcaps, but none 174 | of the SPD scenes currently make use of this definition. 175 | 176 | -------- 177 | 178 | Sphere. A sphere is defined by a radius and center position: 179 | "s" center.x center.y center.z radius 180 | 181 | Format: 182 | s %g %g %g %g 183 | 184 | If the radius is negative, then only the sphere's inside is visible 185 | (objects are normally considered one sided, with the outside visible). 186 | Currently none of the SPD scenes make use of negative radii. 187 | 188 | -------- 189 | 190 | Polygon. A polygon is defined by a set of vertices. With these databases, 191 | a polygon is defined to have all points coplanar. A polygon has only 192 | one side, with the order of the vertices being counterclockwise as you 193 | face the polygon (right-handed coordinate system). The first two edges 194 | must form a non-zero convex angle, so that the normal and side visibility 195 | can be determined by using just the first three vertices. Description: 196 | 197 | "p" total_vertices 198 | vert1.x vert1.y vert1.z 199 | [etc. for total_vertices vertices] 200 | 201 | Format: 202 | p %d 203 | [ %g %g %g ] <-- for total_vertices vertices 204 | 205 | -------- 206 | 207 | Polygonal patch. A patch is defined by a set of vertices and their normals. 208 | With these databases, a patch is defined to have all points coplanar. 209 | A patch has only one side, with the order of the vertices being 210 | counterclockwise as you face the patch (right-handed coordinate system). 211 | The first two edges must form a non-zero convex angle, so that the normal 212 | and side visibility can be determined. Description: 213 | 214 | "pp" total_vertices 215 | vert1.x vert1.y vert1.z norm1.x norm1.y norm1.z 216 | [etc. for total_vertices vertices] 217 | 218 | Format: 219 | pp %d 220 | [ %g %g %g %g %g %g ] <-- for total_vertices vertices 221 | 222 | -------- 223 | 224 | Comment. Description: 225 | "#" [ string ] 226 | 227 | Format: 228 | # [ string ] 229 | 230 | As soon as a "#" character is detected, the rest of the line is considered 231 | a comment. 232 | -------------------------------------------------------------------------------- /docs/balls.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/balls.gif -------------------------------------------------------------------------------- /docs/balls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/balls.png -------------------------------------------------------------------------------- /docs/gears.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/gears.gif -------------------------------------------------------------------------------- /docs/gears.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/gears.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/index.html -------------------------------------------------------------------------------- /docs/jenkins.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/jenkins.jpg -------------------------------------------------------------------------------- /docs/mount.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/mount.gif -------------------------------------------------------------------------------- /docs/mount.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/mount.png -------------------------------------------------------------------------------- /docs/new.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/new.jpg -------------------------------------------------------------------------------- /docs/old.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/old.jpg -------------------------------------------------------------------------------- /docs/rings.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/rings.gif -------------------------------------------------------------------------------- /docs/rings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/rings.png -------------------------------------------------------------------------------- /docs/teapot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/teapot.gif -------------------------------------------------------------------------------- /docs/teapot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/teapot.png -------------------------------------------------------------------------------- /docs/tetra.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/tetra.gif -------------------------------------------------------------------------------- /docs/tetra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/tetra.png -------------------------------------------------------------------------------- /docs/tree.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/tree.gif -------------------------------------------------------------------------------- /docs/tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erich666/StandardProceduralDatabases/5c860e209aec43392e44a2defb272b287a6e85a5/docs/tree.png -------------------------------------------------------------------------------- /src/balls.c: -------------------------------------------------------------------------------- 1 | /* 2 | * balls.c - Also known as "sphereflake". Create a set of shiny spheres, with 3 | * each sphere blooming sets of 9 more spheres with 1/3rd radius. 4 | * A square floor polygon is added. Three light sources. 5 | * 6 | * Author: Eric Haines 7 | * 8 | * size_factor determines the number of objects output. 9 | * Total spheres = sum of n=0,SF of (9**SF). 10 | * 11 | * size_factor # spheres # squares 12 | * 1 10 1 13 | * 2 91 1 14 | * 3 820 1 15 | * 16 | * 4 7381 1 17 | */ 18 | 19 | #include 20 | #include 21 | #include /* atoi */ 22 | #include "def.h" 23 | #include "drv.h" /* display_close() */ 24 | #include "lib.h" 25 | 26 | /* These may be read from the command line */ 27 | static int size_factor = 4; 28 | static int raytracer_format = OUTPUT_RT_DEFAULT; 29 | static int output_format = OUTPUT_CURVES; 30 | 31 | 32 | #ifdef OUTPUT_TO_FILE 33 | static FILE * stdout_file = NULL; 34 | #else 35 | #define stdout_file stdout 36 | #endif /* OUTPUT_TO_FILE */ 37 | 38 | static COORD4 objset[9] ; 39 | 40 | /* 41 | * Output the parent sphere, then output the children of the sphere. 42 | * Uses global 'objset'. 43 | */ 44 | static void 45 | output_object(depth, center, direction) 46 | int depth; 47 | COORD4 center, direction; 48 | { 49 | double angle; 50 | COORD4 axis, z_axis; 51 | COORD4 child_pt, child_dir; 52 | MATRIX mx; 53 | long num_vert; 54 | double scale; 55 | 56 | PLATFORM_MULTITASK(); 57 | 58 | /* output sphere at location & radius defined by center */ 59 | lib_output_sphere(center, output_format); 60 | 61 | /* check if children should be generated */ 62 | if (depth > 0) { 63 | --depth ; 64 | 65 | /* rotation matrix to new axis from +Z axis */ 66 | /* If direction is (almost) identical to the Z axis, no rotation needed. */ 67 | /* We test with an epsilon built in here because child_dir, below, 68 | may be slightly less than 1.0 in length. */ 69 | if ( direction[Z] >= 0.9999 ) { 70 | /* identity matrix */ 71 | lib_create_identity_matrix(mx); 72 | } 73 | /* If direction is (almost) identical to the -Z axis, rotate 180 degrees. */ 74 | else if ( direction[Z] <= -0.9999 ) { 75 | lib_create_rotate_matrix(mx, Y_AXIS, PI); 76 | } 77 | else { 78 | SET_COORD3(z_axis, 0.0, 0.0, 1.0); 79 | CROSS(axis, z_axis, direction); 80 | lib_normalize_vector(axis); 81 | angle = acos((double)DOT_PRODUCT(z_axis, direction)); 82 | lib_create_axis_rotate_matrix(mx, axis, angle); 83 | } 84 | 85 | /* scale down location of new spheres */ 86 | scale = center[W] * (1.0 + direction[W]); 87 | 88 | for ( num_vert = 0 ; num_vert < 9 ; ++num_vert ) { 89 | /* only do progress for top-level objects of recursion */ 90 | if (depth==size_factor-1) 91 | PLATFORM_PROGRESS(0, num_vert, 8); 92 | lib_transform_coord(child_pt, objset[num_vert], mx); 93 | child_pt[X] = child_pt[X] * scale + center[X]; 94 | child_pt[Y] = child_pt[Y] * scale + center[Y]; 95 | child_pt[Z] = child_pt[Z] * scale + center[Z]; 96 | /* scale down radius */ 97 | child_pt[W] = center[W] * direction[W]; 98 | SUB3_COORD3( child_dir, child_pt, center); 99 | child_dir[X] /= scale; 100 | child_dir[Y] /= scale; 101 | child_dir[Z] /= scale; 102 | child_dir[W] = direction[W]; 103 | output_object(depth, child_pt, child_dir); 104 | } 105 | } 106 | } 107 | 108 | /* Create the set of 9 vectors needed to generate the sphere set. */ 109 | /* Uses global 'objset' */ 110 | static void 111 | create_objset() 112 | { 113 | COORD4 axis, temp_pt, trio_dir[3]; 114 | double dist; 115 | MATRIX mx; 116 | long num_set, num_vert; 117 | 118 | dist = 1.0 / sqrt((double)2.0); 119 | 120 | SET_COORD4(trio_dir[0], dist, dist, 0.0, 0.0); 121 | SET_COORD4(trio_dir[1], dist, 0.0, -dist, 0.0); 122 | SET_COORD4(trio_dir[2], 0.0, dist, -dist, 0.0); 123 | 124 | SET_COORD3(axis, 1.0, -1.0, 0.0); 125 | lib_normalize_vector(axis); 126 | lib_create_axis_rotate_matrix(mx, axis, 127 | asin((double)(2.0/sqrt((double)6.0)))); 128 | 129 | for (num_vert=0;num_vert<3;++num_vert) { 130 | lib_transform_coord(temp_pt, trio_dir[num_vert], mx); 131 | COPY_COORD4(trio_dir[num_vert], temp_pt); 132 | } 133 | 134 | for (num_set=0;num_set<3;++num_set) { 135 | lib_create_rotate_matrix(mx, Z_AXIS, num_set*2.0*PI/3.0); 136 | for (num_vert=0;num_vert<3;++num_vert) { 137 | lib_transform_coord(objset[num_set*3+num_vert], 138 | trio_dir[num_vert], mx); 139 | } 140 | } 141 | } 142 | 143 | int 144 | main(argc,argv) 145 | int argc ; 146 | char *argv[] ; 147 | { 148 | COORD3 back_color, obj_color; 149 | COORD3 backg[5], bvec; 150 | COORD3 from, at, up; 151 | COORD4 light; 152 | COORD4 center_pt, direction; 153 | double radius, lscale; 154 | 155 | PLATFORM_INIT(SPD_BALLS); 156 | 157 | /* Start by defining which raytracer we will be using */ 158 | if ( lib_gen_get_opts( argc, argv, 159 | &size_factor, &raytracer_format, &output_format ) ) { 160 | return EXIT_FAIL; 161 | } 162 | 163 | if ( lib_open( raytracer_format, "Balls" ) ) { 164 | return EXIT_FAIL; 165 | } 166 | 167 | /* set radius of sphere which would enclose entire object */ 168 | radius = 1.0 ; 169 | 170 | /* output background color - UNC sky blue */ 171 | /* NOTE: Do this BEFORE lib_output_viewpoint(), for display_init() */ 172 | SET_COORD3(back_color, 0.078, 0.361, 0.753); 173 | lib_output_background_color(back_color); 174 | 175 | /* output viewpoint */ 176 | SET_COORD3(from, 2.1, 1.3, 1.7); 177 | SET_COORD3(at, 0.0, 0.0, 0.0); 178 | SET_COORD3(up, 0.0, 0.0, 1.0); 179 | lib_output_viewpoint(from, at, up, 45.0, 1.0, 0.01, 512, 512); 180 | 181 | /* 182 | * For raytracers that don't scale the light intensity, 183 | * we will do it for them 184 | */ 185 | #define NUM_LIGHTS 3 186 | lscale = ( ((raytracer_format==OUTPUT_NFF) || (raytracer_format==OUTPUT_RTRACE)) 187 | ? 1.0 : 1.0 / sqrt(NUM_LIGHTS)); 188 | 189 | /* output light sources */ 190 | SET_COORD4(light, 4.0, 3.0, 2.0, lscale); 191 | lib_output_light(light); 192 | SET_COORD4(light, 1.0, -4.0, 4.0, lscale); 193 | lib_output_light(light); 194 | SET_COORD4(light, -3.0, 1.0, 5.0, lscale); 195 | lib_output_light(light); 196 | 197 | /* output floor polygon - beige */ 198 | SET_COORD3(back_color, 1.0, 0.75, 0.33); 199 | lib_output_color(NULL, back_color, 0.2, 0.8, 0.0, 0.0, 0.0, 0.0, 1.0); 200 | SET_COORD3(bvec, 12.0 * radius, 12.0 * radius, -radius / 2.0); 201 | SET_COORD3(backg[0], bvec[X], bvec[Y], bvec[Z]); 202 | SET_COORD3(backg[1], -bvec[X], bvec[Y], bvec[Z]); 203 | SET_COORD3(backg[2], -bvec[X], -bvec[Y], bvec[Z]); 204 | SET_COORD3(backg[3], bvec[X], -bvec[Y], bvec[Z]); 205 | SET_COORD3(backg[4], bvec[X], bvec[Y], bvec[Z]); 206 | lib_output_polygon(4, backg); 207 | 208 | /* set up object color - mirrored */ 209 | SET_COORD3(obj_color, 1.0, 0.9, 0.7); 210 | lib_output_color(NULL, obj_color, 0.0, 0.5, 0.5, 0.5, 37.0, 0.0, 1.0); 211 | 212 | /* create set of spawned points */ 213 | create_objset(); 214 | 215 | /* compute and output object */ 216 | SET_COORD4(center_pt, 0.0, 0.0, 0.0, radius / 2.0); 217 | SET_COORD4(direction, 0.0, 0.0, 1.0, 1.0/3.0); 218 | output_object(size_factor, center_pt, direction); 219 | 220 | lib_close(); 221 | 222 | PLATFORM_SHUTDOWN(); 223 | return EXIT_SUCCESS; 224 | } 225 | -------------------------------------------------------------------------------- /src/def.h: -------------------------------------------------------------------------------- 1 | /* 2 | * def.h contains some useful definitions for "C" programs. 3 | * 4 | * Author: Eric Haines 5 | * 6 | * Modified: 1 October 1992 7 | * Alexander R. Enzmann 8 | * Modified: 14 December 1992 - Better Mac (MPW) compatibility 9 | * Eduard [esp] Schwan 10 | * Modified: 2 August 1993 - More ANSI C & Mac compatibility fixes 11 | * Eduard [esp] Schwan 12 | * Modified: 4 September 1993 - Added one more generator (LATTICE) 13 | * Antonio [acc] Costa 14 | * Modified: 6 September 1993 - Changed LATTICE to GENERIC, other renames 15 | * Eric Haines 16 | * Modified: 16 September 1993 - Added SPD_LATTICE & SPD_SHELLS defines 17 | * Eduard [esp] Schwan 18 | * Modified: 27 July 1994 - Added __MWERKS__ define for Metrowerks compiler 19 | * Eduard [esp] Schwan 20 | * Modified: 2 November 1994 - Added COMB_COORD 21 | * Alexander R. Enzmann 22 | * Modified: 6 January 1998 - Added PLATFORM_PROGRESS and ANSI_FN_DEF 23 | * Eduard [esp] Schwan 24 | * 25 | */ 26 | 27 | #ifndef DEF_H 28 | #define DEF_H 29 | 30 | #if __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | /* 35 | * Each data base/program is defined here. These are used as 36 | * parameters to the PLATFORM_INIT() macro, in case the programs 37 | * need to behave differently based on the type of db run. For 38 | * example, the Macintosh version must prompt the user for input 39 | * parameters instead of getting them on the command line. This 40 | * allows the Mac to use a different dialog box for each program. 41 | */ 42 | #define SPD_MIN 1 43 | #define SPD_BALLS 1 44 | #define SPD_GEARS 2 45 | #define SPD_MOUNT 3 46 | #define SPD_RINGS 4 47 | #define SPD_TEAPOT 5 48 | #define SPD_TETRA 6 49 | #define SPD_TREE 7 50 | #define SPD_READDXF 8 51 | #define SPD_LATTICE 9 52 | #define SPD_SHELLS 10 53 | #define SPD_READNFF 11 54 | #define SPD_READOBJ 12 55 | #define SPD_JACKS 13 56 | #define SPD_SOMBRERO 14 57 | #define SPD_NURBTST 15 58 | #define SPD_GENERIC 16 59 | #define SPD_MAX SPD_GENERIC 60 | 61 | 62 | /* ---- Macintosh-specific definitions here ---- */ 63 | 64 | #if defined(applec) || defined(THINK_C) || defined(__MWERKS__) 65 | // insert ANSI prototypes in function forward decls. 66 | #define PARAMS(x) x 67 | // Use ANSI function definitions, not K&R style 68 | #define ANSI_FN_DEF 1 69 | 70 | /* If OUTPUT_TO_FILE is defined, output goes to new text file, not to stdout */ 71 | #define OUTPUT_TO_FILE true 72 | 73 | #define PLATFORM_INIT(spdType) MacInit(&argc, &argv, spdType) 74 | #define PLATFORM_PROGRESS(STARTVAL,CURRVAL,ENDVAL) MacProgress(STARTVAL,CURRVAL,ENDVAL) 75 | #define PLATFORM_MULTITASK() MacMultiTask() 76 | #define PLATFORM_SHUTDOWN() MacShutDown() 77 | 78 | #define EPSILON 1.0e-15 79 | #define EPSILON2 1.0e-7 80 | 81 | #if defined(__MWERKS__) 82 | // Stupid bug in CW6 where Apple headers declare NULL as "0", 83 | // and Metrowerks sometimes just pushes a short instead of a long 84 | // onto the stack where the K&R function expects a long! 85 | #undef NULL 86 | #define NULL ((void*)0L) 87 | 88 | // If Metrowerks, ignore the old K&R style function prototypes in the code, 89 | // since some horrible CW parse errors occur otherwise! 90 | #if defined (__MWERKS__) 91 | #pragma ignore_oldstyle on 92 | #endif // CodeWarrior 93 | 94 | #endif 95 | 96 | #if defined(applec) 97 | #include 98 | #define PI pi() 99 | #endif /* applec */ 100 | 101 | 102 | /* 103 | * declared in drv_mac.c 104 | */ 105 | extern void MacInit(int *argcp, char ***argvp, int spdType); 106 | extern void MacProgress(int STARTVAL,int CURRVAL,int ENDVAL); 107 | extern void MacMultiTask(void); 108 | extern void MacShutDown(void); 109 | #endif /* applec || THINK_C */ 110 | 111 | 112 | 113 | /* Use "PARAMS(x) ()" above if your compiler can't handle function prototyping, 114 | * "PARAMS(x) x" if it can use ANSI headers. 115 | */ 116 | #ifndef PARAMS 117 | 118 | /* check if ANSI headers should be available */ 119 | #if __STDC__ || defined(__cplusplus) 120 | /* yes, ANSI headers */ 121 | #define PARAMS(x) x 122 | #else 123 | /* no, no ANSI headers */ 124 | #define PARAMS(x) () 125 | #endif 126 | 127 | #endif 128 | 129 | 130 | /* 131 | * PLATFORM_xxx macros are used to allow different OS platforms 132 | * hooks to do their own initialization, periodic tasks, and 133 | * shutdown cleanup, if needed. [esp] 134 | */ 135 | 136 | #ifndef PLATFORM_INIT 137 | #define PLATFORM_INIT(spdType) 138 | #endif /* PLATFORM_INIT */ 139 | 140 | #ifndef PLATFORM_MULTITASK 141 | #define PLATFORM_MULTITASK() 142 | #endif /* PLATFORM_MULTITASK */ 143 | 144 | /* Allows percent-complete progress indicator during generation */ 145 | #ifndef PLATFORM_PROGRESS 146 | #define PLATFORM_PROGRESS(STARTVAL,CURRVAL,ENDVAL) 147 | #endif /* PLATFORM_PROGRESS */ 148 | 149 | #ifndef PLATFORM_SHUTDOWN 150 | #define PLATFORM_SHUTDOWN() 151 | #endif /* PLATFORM_SHUTDOWN */ 152 | 153 | 154 | /* exit codes - define as you wish */ 155 | #define EXIT_SUCCESS 0 156 | #define EXIT_FAIL 1 157 | 158 | #ifndef EPSILON 159 | #define EPSILON 1.0e-8 160 | #endif 161 | 162 | #ifndef EPSILON2 163 | #define EPSILON2 1.0e-6 164 | #endif 165 | 166 | #ifndef FALSE 167 | #define FALSE 0 168 | #endif 169 | 170 | #ifndef NULL 171 | #define NULL 0 172 | #endif 173 | 174 | #ifndef TRUE 175 | #define TRUE 1 176 | #endif 177 | 178 | #ifndef PI 179 | #define PI 3.141592653589793 180 | #endif 181 | 182 | typedef double MATRIX[4][4]; /* row major form */ 183 | 184 | typedef double COORD3[3]; 185 | typedef double COORD4[4]; 186 | 187 | /* COORD3/COORD4 indices */ 188 | #define X 0 189 | #define Y 1 190 | #define Z 2 191 | #define W 3 192 | 193 | /* COORD3 (color) indices */ 194 | #define R_COLOR 0 195 | #define G_COLOR 1 196 | #define B_COLOR 2 197 | 198 | #define POW(A,B) ( (A) == 0.0 ? 0.0 : ( (B) == 0.0 ? 1.0 : pow(A, B) ) ) 199 | #define SGN(A) ( (A) < 0.0 ? -1.0 : ( (A) > 0.0 ? 1.0 : 0.0) ) 200 | #define ABSOLUTE(A) ( (A) < 0 ? -(A) : (A) ) 201 | #define FRACTION(A) ( (A) - (int)(A) ) 202 | #define MAX(A,B) ( (A) > (B) ? (A) : (B) ) 203 | #define MIN(A,B) ( (A) < (B) ? (A) : (B) ) 204 | #define SQR(A) ( (A) * (A) ) 205 | #define IS_VAL_ALMOST_ZERO(A,E) ( ABSOLUTE(A) <= (E) ) 206 | 207 | #define ADD2_COORD3(r,a) { (r)[X] += (a)[X]; (r)[Y] += (a)[Y];\ 208 | (r)[Z] += (a)[Z]; } 209 | #define ADD3_COORD3(r,a,b) { (r)[X] = (a)[X] + (b)[X];\ 210 | (r)[Y] = (a)[Y] + (b)[Y];\ 211 | (r)[Z] = (a)[Z] + (b)[Z]; } 212 | #define COPY_COORD3(r,a) { (r)[X] = (a)[X];\ 213 | (r)[Y] = (a)[Y];\ 214 | (r)[Z] = (a)[Z];} 215 | #define COPY_COORD4(r,a) { (r)[X] = (a)[X];\ 216 | (r)[Y] = (a)[Y];\ 217 | (r)[Z] = (a)[Z];\ 218 | (r)[W] = (a)[W]; } 219 | #define CROSS(r,a,b) { (r)[X] = (a)[Y] * (b)[Z] - (a)[Z] * (b)[Y];\ 220 | (r)[Y] = (a)[Z] * (b)[X] - (a)[X] * (b)[Z];\ 221 | (r)[Z] = (a)[X] * (b)[Y] - (a)[Y] * (b)[X]; } 222 | #define DOT_PRODUCT(a,b) ( (a)[X] * (b)[X] +\ 223 | (a)[Y] * (b)[Y] +\ 224 | (a)[Z] * (b)[Z] ) 225 | #define DOT4(a,b) ( (a)[X] * (b)[X] +\ 226 | (a)[Y] * (b)[Y] +\ 227 | (a)[Z] * (b)[Z] +\ 228 | (a)[W] * (b)[W] ) 229 | #define IS_COORD3_ALMOST_ZERO(a,E) (\ 230 | IS_VAL_ALMOST_ZERO( (a)[X], (E) )\ 231 | && IS_VAL_ALMOST_ZERO( (a)[Y], (E) )\ 232 | && IS_VAL_ALMOST_ZERO( (a)[Z], (E) ) ) 233 | #define SET_COORD3(r,A,B,C) { (r)[X] = (A); (r)[Y] = (B); (r)[Z] = (C); } 234 | #define SET_COORD4(r,A,B,C,D) { (r)[X] = (A); (r)[Y] = (B); (r)[Z] = (C);\ 235 | (r)[W] = (D); } 236 | #define SUB2_COORD3(r,a) { (r)[X] -= (a)[X]; (r)[Y] -= (a)[Y];\ 237 | (r)[Z] -= (a)[Z]; } 238 | #define SUB3_COORD3(r,a,b) { (r)[X] = (a)[X] - (b)[X];\ 239 | (r)[Y] = (a)[Y] - (b)[Y];\ 240 | (r)[Z] = (a)[Z] - (b)[Z]; } 241 | #define LERP_COORD(r, a, b, u) { (r)[X] = (a)[X] + (u) * ((b)[X] - (a)[X]);\ 242 | (r)[Y] = (a)[Y] + (u) * ((b)[Y] - (a)[Y]);\ 243 | (r)[Z] = (a)[Z] + (u) * ((b)[Z] - (a)[Z]); } 244 | #define COMB_COORD(r, a, b, u, v) { (r)[X] = (a)[X] * (u) + (b)[X] * (v);\ 245 | (r)[Y] = (a)[Y] * (u) + (b)[X] * (v);\ 246 | (r)[Z] = (a)[Z] * (u) + (b)[X] * (v); } 247 | #define RAD2DEG(x) (180.0*(x)/3.1415926535897932384626) 248 | #define DEG2RAD(x) (3.1415926535897932384626*(x)/180.0) 249 | 250 | #if __cplusplus 251 | } 252 | #endif 253 | 254 | 255 | #endif /* DEF_H */ 256 | -------------------------------------------------------------------------------- /src/drv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Modified: 17 Mar 1993 3 | * Eduard [esp] Schwan 4 | * Passed bg_color to display_init 5 | * (unfortunate side-effect is you should now call 6 | * lib_output_background_color BEFORE lib_output_viewpoint.) 7 | * 8 | * Modified: 2 August 1993 - More ANSI C & Mac compatibility fixes 9 | * Eduard [esp] Schwan 10 | * 11 | */ 12 | 13 | #ifndef DISP_H 14 | #define DISP_H 15 | 16 | #include "def.h" 17 | 18 | 19 | void display_init PARAMS((int xres, int yres, COORD3 bk_color)); 20 | void display_close PARAMS((int wait_flag)); 21 | void display_clear PARAMS((void)); 22 | void display_plot PARAMS((int x, int y, COORD3 color)); 23 | void display_line PARAMS((int x0, int y0, int x1, int y1, COORD3 color)); 24 | int kbhit PARAMS((void)); 25 | 26 | 27 | #endif /* DISP_H */ 28 | -------------------------------------------------------------------------------- /src/drv_hp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * drv_hp.c - a budget displayer for HP workstations, by Eric Haines 3 | * 4 | * A real kludge, I admit - do want you want in gopen(). 5 | * 6 | * I assume you're in X windows and start with a graphics window: 7 | xwcreate -depth 24 -g 480x512+0+0 GraphWin 8 | */ 9 | 10 | #include 11 | #include 12 | #include "drv.h" 13 | 14 | #define ClrList(c) (float)((c)[0]), (float)((c)[1]), (float)((c)[2]) 15 | static int FD = -1 ; 16 | static double X_res, Y_res ; 17 | 18 | void 19 | display_clear() 20 | { 21 | /* Insert code to clear the graphics display here */ 22 | clear_control( FD, CLEAR_VDC_EXTENT ) ; 23 | clear_view_surface( FD ) ; 24 | } 25 | 26 | void 27 | display_init(xres, yres, bk_color) 28 | int xres, yres; 29 | COORD3 bk_color; 30 | { 31 | /* Insert code to open/initialize the graphics display here */ 32 | if ( -1 == ( FD = 33 | gopen( "/dev/screen/GraphWin", OUTINDEV, NULL, INIT|ACCELERATED) ) ) { 34 | 35 | fprintf( stderr, "could not open device for output!\n" ) ; 36 | return ; 37 | } 38 | shade_mode( FD, CMAP_FULL|INIT, FALSE ) ; 39 | mapping_mode( FD, TRUE ) ; 40 | background_color( FD, ClrList( bk_color ) ) ; 41 | display_clear() ; 42 | X_res = xres ; 43 | Y_res = yres ; 44 | } 45 | 46 | void 47 | display_close(wait_flag) 48 | int wait_flag ; 49 | { 50 | /* Insert code to close the graphics display here */ 51 | gclose( FD ) ; 52 | } 53 | 54 | /* currently not used for anything, so you don't have to implement */ 55 | void 56 | display_plot(x, y, color) 57 | int x, y; 58 | COORD3 color; 59 | { 60 | float clist[2] ; 61 | 62 | /* Insert code to plot a single pixel here */ 63 | marker_color( FD, ClrList( color ) ) ; 64 | clist[0] = (float)x/X_res ; 65 | clist[1] = (float)y/Y_res ; 66 | polymarker2d( FD, clist, 1, FALSE ) ; 67 | } 68 | 69 | /* weirdly enough, x and y are centered around the origin */ 70 | void 71 | display_line(x0, y0, x1, y1, color) 72 | int x0, y0, x1, y1; 73 | COORD3 color; 74 | { 75 | /* Insert line drawing code here */ 76 | line_color( FD, ClrList( color ) ) ; 77 | move2d( FD, (float)(((double)x0)/X_res), 78 | (float)(((double)-y0+Y_res)/Y_res) ) ; 79 | draw2d( FD, (float)(((double)x1)/X_res), 80 | (float)(((double)-y1+Y_res)/Y_res) ) ; 81 | } 82 | 83 | int 84 | kbhit() 85 | { 86 | /* Insert keyboard hit (i.e. interrupt operation) test code here */ 87 | 88 | /* currently always no interrupt */ 89 | return( 0 ) ; 90 | } 91 | -------------------------------------------------------------------------------- /src/drv_null.c: -------------------------------------------------------------------------------- 1 | /* 2 | * drv_null.c - generic graphics driver (stubs - outputs no images) 3 | */ 4 | 5 | #include "drv.h" 6 | 7 | void 8 | display_clear() 9 | { 10 | /* Insert code to clear the graphics display here */ 11 | } 12 | 13 | void 14 | display_init(xres, yres, bk_color) 15 | int xres, yres; 16 | COORD3 bk_color; 17 | { 18 | /* Insert code to open/initialize the graphics display here */ 19 | } 20 | 21 | void 22 | display_close(wait_flag) 23 | int wait_flag ; 24 | { 25 | /* Insert code to close the graphics display here */ 26 | } 27 | 28 | /* currently not used for anything, so you don't have to implement */ 29 | void 30 | display_plot(x, y, color) 31 | int x, y; 32 | COORD3 color; 33 | { 34 | /* Insert code to plot a single pixel here */ 35 | } 36 | 37 | /* weirdly enough, x and y are centered around the origin - see hp.c for a 38 | * way to offset these coordinates to a [0 to resolution-1] type of scale. 39 | */ 40 | void 41 | display_line(x0, y0, x1, y1, color) 42 | int x0, y0, x1, y1; 43 | COORD3 color; 44 | { 45 | /* Insert line drawing code here */ 46 | } 47 | 48 | int 49 | kbhit() 50 | { 51 | /* Insert keyboard hit (i.e. interrupt operation) test code here */ 52 | 53 | /* currently always no interrupt */ 54 | return( 0 ) ; 55 | } 56 | -------------------------------------------------------------------------------- /src/drv_x11.c: -------------------------------------------------------------------------------- 1 | /* 2 | * drv_X11.c - A simple X11 graphics driver for SPD. 3 | * Bob Kozdemba (koz@sgi.com), 3/8/97 4 | * 5 | * This driver requires an 8-bit PseudoColor Visual and has no 6 | * support for redrawing caused by exposure events. 7 | * 8 | * drv_x11.c is written using Xlib calls based on the X11R6 distribution. A 9 | * sample makefile, makefile.x11 is provided. If your X11 distribution is in 10 | * the standard directories the c compiler looks in, things should build by 11 | * doing 'make -f makefile.x11'. If not, you will need to tell the c compiler 12 | * where the X11 distribution is located. 13 | * 14 | * Here are some examples you might make to the makefile. 15 | * 16 | * CC=cc -O -I/usr/local/include/X11 -L/usr/local/lib/X11 17 | * 18 | * CFLAGS=-O -I/usr/local/include/X11 19 | * LDFLAGS=-L/usr/local/lib/X11 20 | * 21 | * To test things out try 'balls -r 0'. 22 | * 23 | * 24 | * X11 Server Visual Support 25 | * ------------------------- 26 | * 27 | * The drv_x11 only works with 8-bit PseudoColor visuals which are very 28 | * common on unix workstations or PC's running Linux and the XF86 SVGA X server. 29 | * Adding support for Monochrome or 4-bit Visuals is easy but I wanted to 30 | * keep the code as simple as possible. If you need one, send me some email. 31 | * 32 | * Enjoy, 33 | * Koz 34 | * koz@sgi.com 35 | */ 36 | 37 | #include "drv.h" 38 | #include 39 | #include 40 | #include 41 | 42 | /* Globals for X11 */ 43 | Display *display; 44 | unsigned int screen; 45 | Window window; 46 | GC gc; 47 | 48 | /* Window sizes */ 49 | unsigned int width = 512; 50 | unsigned int height = 512; 51 | unsigned int depth = 8; 52 | 53 | void 54 | display_clear() 55 | { 56 | /* Insert code to clear the graphics display here */ 57 | XClearArea( display, window, 0, 0, width, height, False ); 58 | } 59 | 60 | void 61 | display_init(xres, yres, bk_color) 62 | int xres, yres; 63 | COORD3 bk_color; 64 | { 65 | int i; 66 | int r, g, b; 67 | int done = 0; 68 | XEvent event; 69 | Colormap colormap; 70 | XSetWindowAttributes wAttr; 71 | XVisualInfo *pVisInfo,visInfo; 72 | int retVal; 73 | XGCValues gc_vals; 74 | XColor xcolor; 75 | unsigned int mask; 76 | unsigned long bk_pixel; 77 | 78 | /* Insert code to open/initialize the graphics display here */ 79 | display = XOpenDisplay( NULL ); 80 | if ( display == NULL ) { 81 | fprintf( stderr, "Error opening %s !\n", getenv("DISPLAY") ); 82 | exit( 1 ); 83 | } 84 | 85 | screen = DefaultScreen( display ); 86 | 87 | visInfo.screen = 0; 88 | visInfo.depth = depth; 89 | visInfo.class = PseudoColor; 90 | mask = VisualScreenMask | VisualDepthMask | VisualClassMask; 91 | 92 | pVisInfo = XGetVisualInfo(display, mask, &visInfo, &retVal); 93 | 94 | if (!retVal) { 95 | fprintf(stderr,"Could not get an 8-bit PseudoColor visual !\n"); 96 | exit(1); 97 | } 98 | 99 | colormap= XCreateColormap(display, 100 | RootWindowOfScreen(ScreenOfDisplay(display,0)), 101 | pVisInfo->visual, AllocAll); 102 | 103 | if (!colormap){ 104 | fprintf(stderr,"Could not create color map\n"); 105 | exit(1); 106 | } 107 | 108 | 109 | /* Store the colors, 16 bits/component */ 110 | i = 0; 111 | for(r=0; r<8; r+= 1) { 112 | for(g=0; g<8; g+= 1) { 113 | for(b=0; b<4; b+= 1) { 114 | xcolor.pixel = i; 115 | xcolor.red = (float) (r/7.0 ) * 65535; 116 | xcolor.green = (float) (g/7.0 ) * 65535; 117 | xcolor.blue = (float) (b/3.0 ) * 65535; 118 | xcolor.flags = DoRed | DoGreen | DoBlue; 119 | if (XStoreColor(display, colormap, &xcolor) == BadAccess ) 120 | printf("Pixel %d, Could not alloc color cell !\n", i); 121 | i += 1; 122 | } 123 | } 124 | 125 | } 126 | 127 | /* Calculate the background pixel */ 128 | bk_pixel = ( (unsigned long) (bk_color[0] * 7.0) ) << 5; 129 | bk_pixel += ( (unsigned long) (bk_color[1] * 7.0) ) << 2; 130 | bk_pixel += ( (unsigned long) (bk_color[2] * 3.0) ); 131 | 132 | wAttr.event_mask = ExposureMask; 133 | wAttr.border_pixel = BlackPixel( display, screen ); 134 | wAttr.background_pixel = bk_pixel; 135 | wAttr.colormap = colormap; 136 | XFlush(display); 137 | window = XCreateWindow(display, 138 | RootWindowOfScreen(ScreenOfDisplay(display,0)), 139 | 0, 0, 140 | width, height, 141 | 0, depth, CopyFromParent, 142 | pVisInfo->visual, 143 | CWBackPixel | CWColormap | 144 | CWBorderPixel | CWEventMask, 145 | &wAttr); 146 | if (!window) { 147 | fprintf(stderr,"Could not create a window\n"); 148 | exit(1); 149 | } 150 | 151 | XStoreName( display, window, "SPD X11 Driver" ); 152 | 153 | gc_vals.foreground = 0; 154 | gc_vals.background = bk_pixel; 155 | gc = XCreateGC( display, window, 156 | (GCForeground| GCBackground), &gc_vals ); 157 | 158 | 159 | XMapWindow( display, window ); 160 | XFlush( display ); 161 | 162 | XSelectInput( display, window, ExposureMask | ButtonPressMask 163 | | KeyPressMask ); 164 | 165 | /* Wait for the window to be exposed. */ 166 | done = 0; 167 | do { 168 | XNextEvent( display, &event); 169 | switch (event.type) 170 | { 171 | case(Expose): 172 | done = 1; 173 | continue; 174 | break; 175 | } 176 | } while(!done); 177 | 178 | } 179 | 180 | void 181 | display_close(wait_flag) 182 | int wait_flag ; 183 | { 184 | /* Insert code to close the graphics display here */ 185 | XEvent event; 186 | int done = 0; 187 | 188 | /* Wait for a mouse button or key press event, then exit. */ 189 | do { 190 | XNextEvent( display, &event); 191 | switch (event.type) 192 | { 193 | case( ButtonPress ): 194 | case( KeyPress ): 195 | done = 1; 196 | continue; 197 | break; 198 | } 199 | } while(!done); 200 | 201 | XCloseDisplay( display ); 202 | 203 | } 204 | 205 | /* currently not used for anything, so you don't have to implement */ 206 | void 207 | display_plot(x, y, color) 208 | int x, y; 209 | COORD3 color; 210 | { 211 | /* Insert code to plot a single pixel here */ 212 | } 213 | 214 | /* weirdly enough, x and y are centered around the origin - see hp.c for a 215 | * way to offset these coordinates to a [0 to resolution-1] type of scale. 216 | */ 217 | void 218 | display_line(x0, y0, x1, y1, color) 219 | int x0, y0, x1, y1; 220 | COORD3 color; 221 | { 222 | unsigned long c; 223 | 224 | /* Convert (snap) the RGB color to one of 256 colors. */ 225 | /* This probably slows things down a bit ! */ 226 | c = ( (unsigned long) (color[0] * 7.0) ) << 5; 227 | c += ( (unsigned long) (color[1] * 7.0) ) << 2; 228 | c += ( (unsigned long) (color[2] * 3.0) ); 229 | 230 | XSetForeground( display, gc, c ); 231 | /* Insert line drawing code here */ 232 | XDrawLine( display, window, gc, x0, y0, x1, y1 ); 233 | 234 | } 235 | 236 | int 237 | kbhit() 238 | { 239 | /* Insert keyboard hit (i.e. interrupt operation) test code here */ 240 | 241 | /* currently always no interrupt */ 242 | return( 0 ) ; 243 | } 244 | -------------------------------------------------------------------------------- /src/gears.c: -------------------------------------------------------------------------------- 1 | /* 2 | * gears.c - Create a set of gears. Each gear face has 144 vertices, and 3 | * contains concavities. Note that the first 3 vertices of all polygons 4 | * define the two edges of a convex section of the polygon. Background 5 | * square ground is reflective. Some gears are clipped. 6 | * Five light sources. 7 | * 8 | * Version: 2.2 (11/17/87) 9 | * Author: Eric Haines 10 | * 11 | * size_factor determines the number of polygons output. 12 | * Total gears = SF**3: concave polygons = 2 * SF**3 13 | * rectangles = 4*TEETH * SF**3 14 | * 15 | * size_factor # gears # gear faces # rectangles 16 | * 1 1 2 144 17 | * 2 8 16 1152 18 | * 3 27 54 3888 19 | * 4 64 128 9216 20 | */ 21 | 22 | #include 23 | #include 24 | #include /* atoi */ 25 | #include "def.h" 26 | #include "drv.h" /* display_close() */ 27 | #include "lib.h" 28 | 29 | /* These may be read from the command line */ 30 | static int size_factor = 4; 31 | static int raytracer_format = OUTPUT_RT_DEFAULT; 32 | static int output_format = OUTPUT_CURVES; 33 | 34 | #ifdef OUTPUT_TO_FILE 35 | static FILE * stdout_file = NULL; 36 | #else 37 | #define stdout_file stdout 38 | #endif /* OUTPUT_TO_FILE */ 39 | 40 | /* define number of teeth on a gear - must be a multiple of 4 */ 41 | #define TEETH 36 42 | /* define ratio of radius taken up by teeth and the gear thickness */ 43 | /* the outer radius is made slightly smaller that the full radius to create 44 | * a finite separation between intermeshing gears. This gets rid of the bug 45 | * of having two surfaces occupy exactly the same space. Note that if these 46 | * are changed, the gears may interpenetrate. 47 | */ 48 | #define OUTER_EDGE_RATIO 0.995 49 | #define INNER_EDGE_RATIO 0.9 50 | #define EDGE_DIFF ( 1.0 - INNER_EDGE_RATIO ) 51 | 52 | /* ratio of width of gear to thickness */ 53 | #define DEPTH_RATIO 0.1 54 | 55 | /* Create gear tooth */ 56 | static void 57 | create_tooth(gear_angle, tooth_angle, center, outer_pt, inner_pt, edge_pts) 58 | double gear_angle, tooth_angle; 59 | COORD3 center, outer_pt, inner_pt; 60 | COORD3 edge_pts[]; 61 | { 62 | MATRIX mx; 63 | 64 | lib_create_rotate_matrix(mx, Z_AXIS, gear_angle - 0.19 * tooth_angle); 65 | lib_transform_vector(edge_pts[0], outer_pt, mx); 66 | ADD2_COORD3( edge_pts[0], center); 67 | lib_create_rotate_matrix(mx, Z_AXIS, gear_angle + 0.19 * tooth_angle); 68 | lib_transform_vector(edge_pts[1], outer_pt, mx); 69 | ADD2_COORD3(edge_pts[1], center); 70 | lib_create_rotate_matrix(mx, Z_AXIS, gear_angle + 0.3 * tooth_angle); 71 | lib_transform_vector(edge_pts[2], inner_pt, mx); 72 | ADD2_COORD3(edge_pts[2], center); 73 | lib_create_rotate_matrix(mx, Z_AXIS, gear_angle + 0.7 * tooth_angle); 74 | lib_transform_vector(edge_pts[3], inner_pt, mx); 75 | ADD2_COORD3(edge_pts[3], center); 76 | } 77 | 78 | /* Create gear */ 79 | static void 80 | create_gear(center, offset_angle, outer_radius, inner_radius, thickness) 81 | COORD3 center; 82 | double offset_angle, outer_radius, inner_radius, thickness; 83 | { 84 | int next_side, num_side, num_teeth ; 85 | double gear_angle, tooth_angle ; 86 | COORD3 side_pts[4], gear_pts[4*TEETH], outer_pt, inner_pt ; 87 | 88 | PLATFORM_MULTITASK(); 89 | 90 | SET_COORD3( outer_pt, outer_radius, 0.0, 0.0 ) ; 91 | SET_COORD3( inner_pt, inner_radius, 0.0, 0.0 ) ; 92 | 93 | tooth_angle = 2.0 * PI / (double)TEETH ; 94 | 95 | /* output gear top */ 96 | for (num_teeth=0;num_teeth 13 | #include 14 | #include /* atoi */ 15 | #include "def.h" 16 | #include "drv.h" /* display_close() */ 17 | #include "lib.h" 18 | 19 | 20 | /* These may be read from the command line */ 21 | static int size_factor = 1; 22 | static int raytracer_format = OUTPUT_RT_DEFAULT; 23 | static int output_format = OUTPUT_CURVES; 24 | 25 | #ifdef OUTPUT_TO_FILE 26 | static FILE * stdout_file = NULL; 27 | #else 28 | #define stdout_file stdout 29 | #endif /* OUTPUT_TO_FILE */ 30 | 31 | /* Some basic colors */ 32 | static COORD3 Pink = { 0.737, 0.561, 0.561}; 33 | static COORD3 DarkPurple = {0.2, 0.05, 0.2}; 34 | 35 | /* Create a single copy of our recursive object. The general 36 | sizing and placement of the object are maintained by the 37 | recursive routine make_rec_jack. This routine does the 38 | actual geometry building */ 39 | static void 40 | make_jack_obj() 41 | { 42 | COORD3 scale; 43 | COORD4 center, base, apex; 44 | 45 | /* Save the current transformation */ 46 | lib_tx_push(); 47 | 48 | /* Scale the object down to prevent overlaps */ 49 | SET_COORD3(scale, 0.75, 0.75, 0.75); 50 | lib_tx_scale(scale); 51 | 52 | /* Now create the object - three intersecting cylinders 53 | * with spheres at both ends 54 | */ 55 | 56 | /* Cylinders on each axis */ 57 | SET_COORD4(base, -1, 0, 0, 0.1); 58 | SET_COORD4(apex, 1, 0, 0, 0.1); 59 | lib_output_cylcone(base, apex, output_format); 60 | SET_COORD4(base, 0, -1, 0, 0.1); 61 | SET_COORD4(apex, 0, 1, 0, 0.1); 62 | lib_output_cylcone(base, apex, output_format); 63 | SET_COORD4(base, 0, 0, -1, 0.1); 64 | SET_COORD4(apex, 0, 0, 1, 0.1); 65 | lib_output_cylcone(base, apex, output_format); 66 | 67 | /* Spheres at the ends of the cylinders */ 68 | SET_COORD4(center, 1, 0, 0, 0.2); 69 | lib_output_sphere(center, output_format); 70 | SET_COORD4(center, 0, 1, 0, 0.2); 71 | lib_output_sphere(center, output_format); 72 | SET_COORD4(center, 0, 0, 1, 0.2); 73 | lib_output_sphere(center, output_format); 74 | SET_COORD4(center,-1, 0, 0, 0.2); 75 | lib_output_sphere(center, output_format); 76 | SET_COORD4(center, 0,-1, 0, 0.2); 77 | lib_output_sphere(center, output_format); 78 | SET_COORD4(center, 0, 0,-1, 0.2); 79 | lib_output_sphere(center, output_format); 80 | 81 | /* Restore the transform to what it was prior to 82 | * entering this routine. 83 | */ 84 | lib_tx_pop(); 85 | } 86 | 87 | /* Create a jack shaped object, then put a smaller copy in 88 | each of the octants defined by the arms of the jack. 89 | This process is repeated until depth reaches max_depth. */ 90 | static void 91 | make_rec_jack(depth, max_depth) 92 | { 93 | double i, j, k; 94 | COORD3 scale, trans; 95 | 96 | make_jack_obj(); 97 | 98 | if (depth < max_depth) { 99 | SET_COORD3(scale, 0.5, 0.5, 0.5); 100 | for (i=-0.5;i<=0.5;i+=1) 101 | for (j=-0.5;j<=0.5;j+=1) 102 | for (k=-0.5;k<=0.5;k+=1) { 103 | if (depth==1) 104 | PLATFORM_PROGRESS(0, 4+i*4+j*2+k, 7); 105 | lib_tx_push(); 106 | SET_COORD3(trans, i, j, k); 107 | lib_tx_translate(trans); 108 | lib_tx_scale(scale); 109 | make_rec_jack(depth+1, max_depth); 110 | lib_tx_pop(); 111 | } 112 | } 113 | } 114 | 115 | int 116 | main(argc, argv) 117 | int argc; 118 | char *argv[]; 119 | { 120 | COORD4 from, at, up; 121 | COORD4 center; 122 | double lscale; 123 | 124 | PLATFORM_INIT(SPD_JACKS); 125 | 126 | /* Start by defining which raytracer we will be using */ 127 | if (lib_gen_get_opts(argc, argv, &size_factor, 128 | &raytracer_format, &output_format)) 129 | return EXIT_FAIL; 130 | 131 | /* Set the output file */ 132 | if (lib_open(raytracer_format, "Jacks")) 133 | return EXIT_FAIL; 134 | 135 | lib_set_polygonalization(2, 2); 136 | 137 | /* output background color - Light Grey */ 138 | /* NOTE: Do this BEFORE lib_output_viewpoint(), for display_init() */ 139 | lib_output_background_color(DarkPurple); 140 | 141 | /* Viewpoint */ 142 | SET_COORD3(from, 0, 0, -8); 143 | SET_COORD3(at, 0, 0, 0); 144 | SET_COORD3(up, 0, 1, 0); 145 | lib_output_viewpoint(from, at, up, 25.0, 1.0, 0.001, 256, 256); 146 | 147 | /* 148 | * For raytracers that don't scale the light intensity, 149 | * we will do it for them 150 | */ 151 | #define NUM_LIGHTS 1 152 | lscale = ( ((raytracer_format==OUTPUT_NFF) || (raytracer_format==OUTPUT_RTRACE)) 153 | ? 1.0 : 1.0 / sqrt(NUM_LIGHTS)); 154 | 155 | SET_COORD4(center, -10, 3, -20, lscale); 156 | lib_output_light(center); 157 | 158 | #if 0 159 | /* Declare all the textures we will be using - this way we only 160 | * need to have one set of declarations, rather than creating 161 | * a new texture for every single object 162 | */ 163 | allocate_textures(); 164 | #endif 165 | 166 | /* Save the root transformation */ 167 | lib_tx_push(); 168 | 169 | /* Rotate everything about the x and y axes */ 170 | lib_tx_rotate(X_AXIS,-30 * PI / 180.0); 171 | lib_tx_rotate(Y_AXIS,-20 * PI / 180.0); 172 | 173 | lib_output_color(NULL, Pink, 0.1, 0.7, 0.7, 0.4, 20.0, 0.0, 1.0); 174 | make_rec_jack(1, size_factor); 175 | 176 | /* Back to where we started */ 177 | lib_tx_pop(); 178 | 179 | lib_close(); 180 | 181 | PLATFORM_SHUTDOWN(); 182 | return EXIT_SUCCESS; 183 | } 184 | -------------------------------------------------------------------------------- /src/lattice.c: -------------------------------------------------------------------------------- 1 | /* 2 | * lattice.c - Create a set of shiny spheres, with each sphere connected to 3 | * its neighbors by matte cylinders, forming a cubic lattice. 4 | * Six light sources. 5 | * 6 | * Author: Antonio Costa, INESC-Norte. 7 | * Version: 3.1 (04/09/93) 8 | * 9 | * SizeFactor determines the number of objects output. 10 | * Total spheres = (SF+1)**3. 11 | * Total cylinders = 3*(SF**3)+... 12 | * 13 | * SizeFactor # spheres # cylinders 14 | * 1 8 12 15 | * 2 27 54 16 | * 3 64 144 17 | * 18 | * 5 216 540 19 | * 20 | * 12 2197 6084 21 | */ 22 | 23 | #include 24 | #include 25 | #include /* atoi */ 26 | #include "def.h" 27 | #include "drv.h" /* display_close() */ 28 | #include "lib.h" 29 | 30 | /* These may be read from the command line */ 31 | static int size_factor = 12; 32 | static int raytracer_format = OUTPUT_RT_DEFAULT; 33 | static int output_format = OUTPUT_CURVES; 34 | 35 | #ifdef OUTPUT_TO_FILE 36 | static FILE * stdout_file = NULL; 37 | #else 38 | #define stdout_file stdout 39 | #endif /* OUTPUT_TO_FILE */ 40 | 41 | #define RADIUS1 (1.0 / 4.0) 42 | #define RADIUS2 (1.0 / 16.0) 43 | 44 | #define inv_factor (1.0 / (double) size_factor) 45 | #define radius1 ((double) RADIUS1 / (double) size_factor) 46 | #define radius2 ((double) RADIUS2 / (double) size_factor) 47 | 48 | main(argc, argv) 49 | int argc; 50 | char *argv[]; 51 | { 52 | COORD4 back_color, obj_color; 53 | COORD4 light; 54 | COORD4 from, at, up; 55 | COORD4 center, center1, center2; 56 | long x, y, z; 57 | double delta, x0, y0, z0, lscale; 58 | 59 | PLATFORM_INIT(SPD_LATTICE); 60 | 61 | /* Start by defining which raytracer we will be using */ 62 | if ( lib_gen_get_opts( argc, argv, 63 | &size_factor, &raytracer_format, &output_format ) ) { 64 | return EXIT_FAIL; 65 | } 66 | if ( lib_open( raytracer_format, "Lattice" ) ) { 67 | return EXIT_FAIL; 68 | } 69 | 70 | delta = 71 | (radius1 * (1.0 - sqrt((double) RADIUS2 / (double) RADIUS1))) * 0.99; 72 | 73 | /* output background color - UNC sky blue */ 74 | /* NOTE: Do this BEFORE lib_output_viewpoint(), for display_init() */ 75 | SET_COORD3(back_color, 0.078, 0.361, 0.753); 76 | lib_output_background_color(back_color); 77 | 78 | /* output viewpoint */ 79 | SET_COORD3(from, ((double) (size_factor >> 1) + 0.5) * inv_factor, 1.0, 80 | 1.0 - 1.0 / (double) (size_factor << 1)); 81 | SET_COORD3(at, ((double) (size_factor >> 1) + 0.5) * inv_factor, -1.0, 82 | -1.0 - 1.0 / (double) (size_factor << 1)); 83 | SET_COORD3(up, 0.2, 1.0, 0.0); 84 | lib_output_viewpoint(from, at, up, 60.0, 1.0, 0.0, 512, 512); 85 | 86 | /* output light sources */ 87 | lscale = 1.0 / sqrt(6.0); 88 | 89 | SET_COORD4(light, 2.0, 0.5, 0.5, lscale); 90 | lib_output_light(light); 91 | SET_COORD4(light, -1.0, 0.5, 0.5, lscale); 92 | lib_output_light(light); 93 | SET_COORD4(light, 0.5, 2.0, 0.5, lscale); 94 | lib_output_light(light); 95 | SET_COORD4(light, 0.5, -1.0, 0.5, lscale); 96 | lib_output_light(light); 97 | SET_COORD4(light, 0.5, 0.5, 2.0, lscale); 98 | lib_output_light(light); 99 | SET_COORD4(light, 0.5, 0.5, -1.0, lscale); 100 | lib_output_light(light); 101 | 102 | for (x = 0; x <= size_factor; x++) { 103 | x0 = (double) x / (double) size_factor; 104 | for (y = 0; y <= size_factor; y++) { 105 | PLATFORM_PROGRESS(0, x*(size_factor+1)+y, (size_factor+1)*(size_factor+1)); 106 | y0 = (double) y / (double) size_factor; 107 | for (z = 0; z <= size_factor; z++) { 108 | 109 | PLATFORM_MULTITASK(); 110 | 111 | z0 = (double) z / (double) size_factor; 112 | 113 | SET_COORD3(obj_color, 0.9, 0.9, 0.9); 114 | lib_output_color(NULL, obj_color, 115 | 0.0, 0.5, 0.5, 0.5, 37.0, 0.0, 0.0); 116 | 117 | SET_COORD4(center, x0, y0, z0, radius1); 118 | lib_output_sphere(center, output_format); 119 | 120 | if (x != size_factor) { 121 | SET_COORD3(obj_color, 0.9, 0.1, 0.1); 122 | lib_output_color(NULL, obj_color, 123 | 0.1, 0.99, 0.0, 0.0, 0.0, 0.0, 0.0); 124 | 125 | SET_COORD4(center1, x0 + delta, y0, z0, radius2); 126 | SET_COORD4(center2, x0 + inv_factor - delta, y0, z0, 127 | radius2); 128 | lib_output_cylcone(center1, center2, output_format); 129 | } 130 | if (y != size_factor) { 131 | SET_COORD3(obj_color, 0.1, 0.9, 0.1); 132 | lib_output_color(NULL, obj_color, 133 | 0.1, 0.99, 0.0, 0.0, 0.0, 0.0, 0.0); 134 | 135 | SET_COORD4(center1, x0, y0 + delta, z0, radius2); 136 | SET_COORD4(center2, x0, y0 + inv_factor - delta, z0, 137 | radius2); 138 | lib_output_cylcone(center1, center2, output_format); 139 | } 140 | if (z != size_factor) 141 | { 142 | SET_COORD3(obj_color, 0.1, 0.1, 0.9); 143 | lib_output_color(NULL, obj_color, 144 | 0.1, 0.99, 0.0, 0.0, 0.0, 0.0, 0.0); 145 | 146 | SET_COORD4(center1, x0, y0, z0 + delta, radius2); 147 | SET_COORD4(center2, x0, y0, z0 + inv_factor - delta, 148 | radius2); 149 | lib_output_cylcone(center1, center2, output_format); 150 | } 151 | } 152 | } 153 | } 154 | 155 | lib_close(); 156 | 157 | PLATFORM_SHUTDOWN(); 158 | return EXIT_SUCCESS; 159 | } 160 | -------------------------------------------------------------------------------- /src/libdmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * lib.c - a library of deferred object output routines. 3 | * 4 | * Author: Eric Haines 5 | * 6 | */ 7 | 8 | /*-----------------------------------------------------------------*/ 9 | /* include section */ 10 | /*-----------------------------------------------------------------*/ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "lib.h" 18 | #include "drv.h" 19 | 20 | 21 | /*-----------------------------------------------------------------*/ 22 | /* defines/constants section */ 23 | /*-----------------------------------------------------------------*/ 24 | 25 | 26 | /*-----------------------------------------------------------------*/ 27 | void 28 | dump_plg_file PARAMS((void)) 29 | { 30 | object_ptr temp_obj; 31 | int i; 32 | unsigned int fcnt, vcnt; 33 | 34 | fcnt = 0; 35 | vcnt = 0; 36 | for (temp_obj = gPolygon_stack; 37 | temp_obj != NULL; 38 | temp_obj = temp_obj->next_object) { 39 | fcnt++; 40 | vcnt += temp_obj->object_data.polygon.tot_vert; 41 | } 42 | 43 | fprintf(gOutfile, "objx %d %d\n", vcnt, fcnt); 44 | 45 | /* Dump all vertices */ 46 | for (temp_obj = gPolygon_stack; 47 | temp_obj != NULL; 48 | temp_obj = temp_obj->next_object) { 49 | 50 | PLATFORM_MULTITASK(); 51 | for (i=0;i<(int)temp_obj->object_data.polygon.tot_vert;i++) { 52 | fprintf(gOutfile, "%g %g %g\n", 53 | temp_obj->object_data.polygon.vert[i][X], 54 | temp_obj->object_data.polygon.vert[i][Y], 55 | temp_obj->object_data.polygon.vert[i][Z]); 56 | } 57 | } 58 | 59 | /* Dump all faces */ 60 | vcnt = 0; 61 | for (temp_obj = gPolygon_stack; 62 | temp_obj != NULL; 63 | temp_obj = temp_obj->next_object) { 64 | 65 | PLATFORM_MULTITASK(); 66 | fprintf(gOutfile, "0x11ff %d ", temp_obj->object_data.polygon.tot_vert); 67 | for (i=0;i<(int)temp_obj->object_data.polygon.tot_vert;i++) 68 | fprintf(gOutfile, "%d ", vcnt + i); 69 | fprintf(gOutfile, "\n"); 70 | vcnt += i; 71 | } 72 | } 73 | 74 | /*-----------------------------------------------------------------*/ 75 | void 76 | dump_obj_file PARAMS((void)) 77 | { 78 | object_ptr temp_obj; 79 | int i; 80 | unsigned int vcnt; 81 | 82 | /* Dump all vertices */ 83 | for (temp_obj = gPolygon_stack; 84 | temp_obj != NULL; 85 | temp_obj = temp_obj->next_object) { 86 | 87 | PLATFORM_MULTITASK(); 88 | for (i=0;i<(int)temp_obj->object_data.polygon.tot_vert;i++) { 89 | fprintf(gOutfile, "v %g %g %g\n", 90 | temp_obj->object_data.polygon.vert[i][X], 91 | temp_obj->object_data.polygon.vert[i][Y], 92 | temp_obj->object_data.polygon.vert[i][Z]); 93 | } 94 | } 95 | 96 | /* Dump all faces */ 97 | vcnt = 0; 98 | for (temp_obj = gPolygon_stack; 99 | temp_obj != NULL; 100 | temp_obj = temp_obj->next_object) { 101 | 102 | PLATFORM_MULTITASK(); 103 | fprintf(gOutfile, "%d ", temp_obj->object_data.polygon.tot_vert); 104 | for (i=0;i<(int)temp_obj->object_data.polygon.tot_vert;i++) { 105 | fprintf(gOutfile, "%d", vcnt + i + 1); 106 | if (i < (int)temp_obj->object_data.polygon.tot_vert - 1) 107 | fprintf(gOutfile, " "); 108 | } 109 | fprintf(gOutfile, "\n"); 110 | vcnt += i; 111 | } 112 | } 113 | 114 | /*-----------------------------------------------------------------*/ 115 | void 116 | dump_all_objects PARAMS((void)) 117 | { 118 | object_ptr temp_obj; 119 | 120 | if (gRT_out_format == OUTPUT_RTRACE) 121 | fprintf(gOutfile, "Objects\n"); 122 | 123 | /* Step through all objects dumping them as we go. */ 124 | for (temp_obj = gLib_objects, gObject_count = 0; 125 | temp_obj != NULL; 126 | temp_obj = temp_obj->next_object, gObject_count++) { 127 | 128 | PLATFORM_MULTITASK(); 129 | lookup_surface_stats(temp_obj->surf_index, &gTexture_count, 130 | &gTexture_ior); 131 | if (temp_obj->tx != NULL) { 132 | /* Set the active transform to what it was at the time 133 | * the object was created 134 | */ 135 | lib_tx_push(); 136 | lib_set_current_tx(*temp_obj->tx); 137 | } 138 | switch (temp_obj->object_type) { 139 | case BOX_OBJ: 140 | lib_output_box(temp_obj->object_data.box.point1, 141 | temp_obj->object_data.box.point2); 142 | break; 143 | case CONE_OBJ: 144 | lib_output_cylcone(temp_obj->object_data.cone.base_pt, 145 | temp_obj->object_data.cone.apex_pt, 146 | temp_obj->curve_format); 147 | break; 148 | case DISC_OBJ: 149 | lib_output_disc(temp_obj->object_data.disc.center, 150 | temp_obj->object_data.disc.normal, 151 | temp_obj->object_data.disc.iradius, 152 | temp_obj->object_data.disc.oradius, 153 | temp_obj->curve_format); 154 | break; 155 | case HEIGHT_OBJ: 156 | lib_output_height(temp_obj->object_data.height.filename, 157 | temp_obj->object_data.height.data, 158 | temp_obj->object_data.height.height, 159 | temp_obj->object_data.height.width, 160 | temp_obj->object_data.height.x0, 161 | temp_obj->object_data.height.x1, 162 | temp_obj->object_data.height.y0, 163 | temp_obj->object_data.height.y1, 164 | temp_obj->object_data.height.z0, 165 | temp_obj->object_data.height.z1); 166 | break; 167 | case POLYGON_OBJ: 168 | lib_output_polygon(temp_obj->object_data.polygon.tot_vert, 169 | temp_obj->object_data.polygon.vert); 170 | break; 171 | case POLYPATCH_OBJ: 172 | lib_output_polypatch(temp_obj->object_data.polypatch.tot_vert, 173 | temp_obj->object_data.polypatch.vert, 174 | temp_obj->object_data.polypatch.norm); 175 | break; 176 | case SPHERE_OBJ: 177 | lib_output_sphere(temp_obj->object_data.sphere.center_pt, 178 | temp_obj->curve_format); 179 | break; 180 | case SUPERQ_OBJ: 181 | lib_output_sq_sphere(temp_obj->object_data.superq.center_pt, 182 | temp_obj->object_data.superq.a1, 183 | temp_obj->object_data.superq.a2, 184 | temp_obj->object_data.superq.a3, 185 | temp_obj->object_data.superq.n, 186 | temp_obj->object_data.superq.e, 187 | temp_obj->curve_format); 188 | break; 189 | case TORUS_OBJ: 190 | lib_output_torus(temp_obj->object_data.torus.center, 191 | temp_obj->object_data.torus.normal, 192 | temp_obj->object_data.torus.iradius, 193 | temp_obj->object_data.torus.oradius, 194 | temp_obj->curve_format); 195 | break; 196 | default: 197 | fprintf(gOutfile, "Bad object type: %d\n", 198 | temp_obj->object_type); 199 | exit(1); 200 | } 201 | if (temp_obj->tx != NULL) { 202 | /* Reset the active transform */ 203 | lib_tx_pop(); 204 | } 205 | } 206 | 207 | if (gRT_out_format == OUTPUT_RTRACE) 208 | fprintf(gOutfile, "\n"); 209 | } 210 | 211 | /*-----------------------------------------------------------------*/ 212 | void 213 | dump_reorder_surfaces PARAMS((void)) 214 | { 215 | surface_ptr temp_ptr, head_ptr = NULL; 216 | 217 | while (gLib_surfaces != NULL) { 218 | temp_ptr = gLib_surfaces; 219 | gLib_surfaces = gLib_surfaces->next; 220 | temp_ptr->next = head_ptr; 221 | head_ptr = temp_ptr; 222 | } 223 | 224 | gLib_surfaces = head_ptr; 225 | } 226 | 227 | /*-----------------------------------------------------------------*/ 228 | void 229 | dump_all_lights PARAMS((void)) 230 | { 231 | light_ptr temp_ptr = gLib_lights; 232 | 233 | if (gRT_out_format == OUTPUT_RTRACE) 234 | fprintf(gOutfile, "Lights\n"); 235 | 236 | while (temp_ptr != NULL) { 237 | lib_output_light(temp_ptr->center_pt); 238 | temp_ptr = temp_ptr->next; 239 | } 240 | 241 | if (gRT_out_format == OUTPUT_RTRACE) 242 | fprintf(gOutfile, "\n"); 243 | } 244 | 245 | /*-----------------------------------------------------------------*/ 246 | void 247 | dump_all_surfaces PARAMS((void)) 248 | { 249 | surface_ptr temp_ptr = gLib_surfaces; 250 | 251 | if (gRT_out_format == OUTPUT_RTRACE) 252 | fprintf(gOutfile, "Surfaces\n"); 253 | 254 | while (temp_ptr != NULL) { 255 | lib_output_color(temp_ptr->surf_name, temp_ptr->color, temp_ptr->ka, 256 | temp_ptr->kd, temp_ptr->ks, temp_ptr->ks_spec, 257 | temp_ptr->ang, temp_ptr->kt, temp_ptr->ior); 258 | temp_ptr = temp_ptr->next; 259 | } 260 | 261 | if (gRT_out_format == OUTPUT_RTRACE) 262 | fprintf(gOutfile, "\n"); 263 | } 264 | 265 | -------------------------------------------------------------------------------- /src/libinf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libinf.c - general info routines. 3 | * 4 | * Author: Eric Haines 5 | * 6 | */ 7 | 8 | /*-----------------------------------------------------------------*/ 9 | /* include section */ 10 | /*-----------------------------------------------------------------*/ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "lib.h" 18 | #include "drv.h" 19 | 20 | 21 | /*-----------------------------------------------------------------*/ 22 | /* defines/constants section */ 23 | /*-----------------------------------------------------------------*/ 24 | 25 | #ifdef OUTPUT_TO_FILE 26 | FILE * gStdout_file = NULL; 27 | #endif /* OUTPUT_TO_FILE */ 28 | 29 | 30 | /*-----------------------------------------------------------------*/ 31 | /* Here are some local variables that are used to control things like 32 | the current output file, current texture, ... */ 33 | FILE *gOutfile; 34 | char *gTexture_name = NULL; 35 | int gTexture_count = 0; 36 | int gObject_count = 0; 37 | double gTexture_ior = 1.0; 38 | int gRT_out_format = OUTPUT_NFF; 39 | int gRT_orig_format = OUTPUT_NFF; 40 | int gU_resolution = OUTPUT_RESOLUTION; 41 | int gV_resolution = OUTPUT_RESOLUTION; 42 | COORD3 gBkgnd_color = {0.0, 0.0, 0.0}; 43 | COORD3 gFgnd_color = {0.0, 0.0, 0.0}; 44 | double gView_bounds[2][3]; 45 | int gView_init_flag = 0; 46 | char *gLib_version_str = LIB_VERSION; 47 | 48 | surface_ptr gLib_surfaces = NULL; 49 | object_ptr gLib_objects = NULL; 50 | light_ptr gLib_lights = NULL; 51 | viewpoint gViewpoint = { 52 | {0, 0, -10}, 53 | {0, 0, 0}, 54 | {0, 1, 0}, 55 | 45, 1, 1.0e-3, 10, 128, 128, 56 | { {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1} } 57 | }; 58 | 59 | /* Globals for tracking indentation level of output file */ 60 | int gTab_width = 4; 61 | int gTab_level = 0; 62 | 63 | 64 | 65 | /*-----------------------------------------------------------------*/ 66 | void tab_indent PARAMS((void)) 67 | { 68 | int k; 69 | /* Q&D way to do it... */ 70 | for (k=0; k OUTPUT_DELAYED) { 140 | fprintf(stderr, "Unknown renderer index: %d\n", default_tracer); 141 | exit(1); 142 | } 143 | gRT_out_format = default_tracer; 144 | } 145 | 146 | /*-----------------------------------------------------------------*/ 147 | #ifdef ANSI_FN_DEF 148 | void lib_set_polygonalization(int u_steps, int v_steps) 149 | #else 150 | void lib_set_polygonalization(u_steps, v_steps) 151 | int u_steps, v_steps; 152 | #endif 153 | { 154 | if ((u_steps > 0) && (v_steps > 0)) { 155 | gU_resolution = u_steps; 156 | gV_resolution = v_steps; 157 | } 158 | } 159 | 160 | /*-----------------------------------------------------------------*/ 161 | #ifdef ANSI_FN_DEF 162 | void lookup_surface_stats(int index, int *tcount, double *tior) 163 | #else 164 | void lookup_surface_stats(index, tcount, tior) 165 | int index, *tcount; 166 | double *tior; 167 | #endif 168 | { 169 | surface_ptr temp_ptr = gLib_surfaces; 170 | 171 | while (temp_ptr != NULL && (int)temp_ptr->surf_index != index) 172 | temp_ptr = temp_ptr->next; 173 | if (temp_ptr != NULL) { 174 | *tior = temp_ptr->ior; 175 | if (*tior < 1.0) *tior = 1.0; 176 | *tcount = temp_ptr->surf_index; 177 | } 178 | else { 179 | *tior = 1.0; 180 | *tcount = 0; 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/libtx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libtx.c - a library of transformation tracking routines. 3 | * 4 | * Author: Alexander Enzmann 5 | * 6 | */ 7 | 8 | 9 | /*-----------------------------------------------------------------*/ 10 | /* include section */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "lib.h" 17 | #include "drv.h" 18 | 19 | 20 | /*-----------------------------------------------------------------*/ 21 | /* defines/constants section */ 22 | 23 | typedef struct tx_struct *tx_ptr; 24 | struct tx_struct { 25 | MATRIX tx; 26 | tx_ptr next; 27 | }; 28 | 29 | 30 | /*-----------------------------------------------------------------*/ 31 | MATRIX IdentityTx = 32 | {{1, 0, 0, 0}, 33 | {0, 1, 0, 0}, 34 | {0, 0, 1, 0}, 35 | {0, 0, 0, 1}}; 36 | static MATRIX CurrentTx = 37 | {{1, 0, 0, 0}, 38 | {0, 1, 0, 0}, 39 | {0, 0, 1, 0}, 40 | {0, 0, 0, 1}}; 41 | static tx_ptr TxStack = NULL; 42 | 43 | /* Return 1 if there is an active transformation, 0 if not */ 44 | int lib_tx_active() 45 | { 46 | int i, j; 47 | for (i=0;i<4;i++) 48 | for (j=0;j<4;j++) 49 | if (fabs(CurrentTx[i][j] - (i == j ? 1.0 : 0.0)) > EPSILON) 50 | return 1; 51 | return 0; 52 | } 53 | 54 | /* Copy the current transform into mat */ 55 | #ifdef ANSI_FN_DEF 56 | void lib_get_current_tx(MATRIX mat) 57 | #else 58 | void lib_get_current_tx(mat) 59 | MATRIX mat; 60 | #endif 61 | { 62 | memcpy(mat, CurrentTx, sizeof(MATRIX)); 63 | } 64 | 65 | /* Copy matrix mat into the current transform */ 66 | #ifdef ANSI_FN_DEF 67 | void lib_set_current_tx(MATRIX mat) 68 | #else 69 | void lib_set_current_tx(mat) 70 | MATRIX mat; 71 | #endif 72 | { 73 | memcpy(CurrentTx, mat, sizeof(MATRIX)); 74 | } 75 | 76 | #ifdef _DEBUG 77 | #ifdef ANSI_FN_DEF 78 | static void show_matrix(MATRIX mat) 79 | #else 80 | static void show_matrix(mat) 81 | MATRIX mat; 82 | #endif 83 | { 84 | int i, j; 85 | for (i=0;i<4;i++) { 86 | for (j=0;j<4;j++) 87 | fprintf(stderr, "%7.4g ", mat[i][j]); 88 | fprintf(stderr, "\n"); 89 | } 90 | } 91 | 92 | /* Show what the transform looks like */ 93 | static void lib_tx_status() 94 | { 95 | double trans[16]; 96 | 97 | #if 0 98 | fprintf(stderr, "Current tx:\n"); 99 | show_matrix(CurrentTx); 100 | #endif 101 | 102 | if (lib_tx_active()) { 103 | if (lib_tx_unwind(CurrentTx, trans)) { 104 | fprintf(stderr, "Tx: scale <%g,%g,%g>\n", 105 | trans[U_SCALEX], trans[U_SCALEY], trans[U_SCALEZ]); 106 | fprintf(stderr, " rotate <%g,%g,%g>\n", 107 | trans[U_ROTATEX], trans[U_ROTATEY], trans[U_ROTATEZ]); 108 | fprintf(stderr, " translate <%g,%g,%g>\n", 109 | trans[U_TRANSX], trans[U_TRANSY], trans[U_TRANSZ]); 110 | } 111 | else 112 | fprintf(stderr, "Tx: failed to unwind\n"); 113 | } 114 | else 115 | fprintf(stderr, "Tx: Identity\n"); 116 | } 117 | #endif 118 | 119 | /* Turn a transformation matrix into the appropriate sequence of 120 | translate/rotate/scale instructions */ 121 | void 122 | lib_output_tx_sequence() 123 | { 124 | MATRIX txmat; 125 | double trans[16]; 126 | int i, j, tflag, rflag, sflag; 127 | COORD3 rotang; 128 | COORD4 axis; 129 | 130 | lib_get_current_tx(txmat); 131 | 132 | if (!lib_tx_unwind(txmat, trans)) { 133 | fprintf(stderr, "Tx: failed to unwind\n"); 134 | return; 135 | } 136 | if (fabs(trans[U_SCALEX] - 1.0) > EPSILON || 137 | fabs(trans[U_SCALEY] - 1.0) > EPSILON || 138 | fabs(trans[U_SCALEZ] - 1.0) > EPSILON) 139 | sflag = 1; 140 | else 141 | sflag = 0; 142 | if (fabs(trans[U_ROTATEX]) > EPSILON || 143 | fabs(trans[U_ROTATEY]) > EPSILON || 144 | fabs(trans[U_ROTATEZ]) > EPSILON) { 145 | if ((gRT_out_format != OUTPUT_3DMF) && 146 | (gRT_out_format != OUTPUT_VRML1) && 147 | (gRT_out_format != OUTPUT_VRML2)) { 148 | /* 3DMF & VRML2 seem to be the only ones that don't use degrees */ 149 | trans[U_ROTATEX] = RAD2DEG(trans[U_ROTATEX]); 150 | trans[U_ROTATEY] = RAD2DEG(trans[U_ROTATEY]); 151 | trans[U_ROTATEZ] = RAD2DEG(trans[U_ROTATEZ]); 152 | } 153 | rflag = 1; 154 | } 155 | else 156 | rflag = 0; 157 | if (fabs(trans[U_TRANSX]) > EPSILON || 158 | fabs(trans[U_TRANSY]) > EPSILON || 159 | fabs(trans[U_TRANSZ]) > EPSILON) 160 | tflag = 1; 161 | else 162 | tflag = 0; 163 | if (!sflag && !rflag && !tflag) 164 | return; 165 | switch (gRT_out_format) { 166 | case OUTPUT_VIDEO: 167 | case OUTPUT_DELAYED: 168 | case OUTPUT_DXF: 169 | case OUTPUT_PLG: 170 | case OUTPUT_NFF: 171 | case OUTPUT_OBJ: 172 | case OUTPUT_QRT: 173 | case OUTPUT_RAWTRI: 174 | /* Can't do inline transforms in these renderers, the 175 | code does the transformations on the shapes 176 | themselves. */ 177 | break; 178 | 179 | case OUTPUT_RTRACE: 180 | fprintf(gOutfile, "65 %ld ", gObject_count+1); 181 | for (i=0;i<4;i++) 182 | for (j=0;j<4;j++) 183 | fprintf(gOutfile, "%g ", txmat[j][i]); 184 | fprintf(gOutfile, "\n"); 185 | break; 186 | 187 | case OUTPUT_RWX: 188 | /* Transforms are possible in RWX, 189 | this code needs to be finished... */ 190 | if (tflag) { 191 | tab_indent(); 192 | fprintf(gOutfile, "Translate %g %g %g\n", 193 | trans[U_TRANSX], trans[U_TRANSY], trans[U_TRANSZ]); 194 | } 195 | if (rflag) { 196 | tab_indent(); 197 | fprintf(gOutfile, "Rotate 0 0 1 %g\n", 198 | trans[U_ROTATEZ]); 199 | tab_indent(); 200 | fprintf(gOutfile, "Rotate 0 1 0 %g\n", 201 | trans[U_ROTATEY]); 202 | tab_indent(); 203 | fprintf(gOutfile, "Rotate 1 0 0 %g\n", 204 | trans[U_ROTATEX]); 205 | } 206 | if (sflag) { 207 | tab_indent(); 208 | fprintf(gOutfile, "Scale %g %g %g\n", 209 | trans[U_SCALEX], trans[U_SCALEY], trans[U_SCALEZ]); 210 | } 211 | break; 212 | 213 | case OUTPUT_RIB: 214 | if (sflag) { 215 | tab_indent(); 216 | fprintf(gOutfile, "Scale %#g %#g %#g\n", 217 | trans[U_SCALEX], trans[U_SCALEY], trans[U_SCALEZ]); 218 | } 219 | if (rflag) { 220 | tab_indent(); 221 | fprintf(gOutfile, "Rotate %#g 1 0 0\n", 222 | trans[U_ROTATEX]); 223 | tab_indent(); 224 | fprintf(gOutfile, "Rotate %#g 0 1 0\n", 225 | trans[U_ROTATEY]); 226 | tab_indent(); 227 | fprintf(gOutfile, "Rotate %#g 0 0 1\n", 228 | trans[U_ROTATEZ]); 229 | } 230 | if (tflag) { 231 | tab_indent(); 232 | fprintf(gOutfile, "Translate %#g %#g %#g\n", 233 | trans[U_TRANSX], trans[U_TRANSY], trans[U_TRANSZ]); 234 | } 235 | break; 236 | 237 | case OUTPUT_VIVID: 238 | tab_inc(); 239 | if (sflag) { 240 | tab_indent(); 241 | fprintf(gOutfile, "scale %g\n", trans[U_SCALEX]); 242 | } 243 | tab_dec(); 244 | if (rflag) { 245 | tab_indent(); 246 | fprintf(gOutfile, "rotate %g %g %g\n", 247 | trans[U_ROTATEX], trans[U_ROTATEY], trans[U_ROTATEZ]); 248 | } 249 | if (tflag) { 250 | tab_indent(); 251 | fprintf(gOutfile, "translate %g %g %g\n", 252 | trans[U_TRANSX], trans[U_TRANSY], trans[U_TRANSZ]); 253 | } 254 | break; 255 | 256 | case OUTPUT_RAYSHADE: 257 | if (sflag) { 258 | fprintf(gOutfile, " scale %g %g %g", 259 | trans[U_SCALEX], trans[U_SCALEY], trans[U_SCALEZ]); 260 | } 261 | if (rflag) { 262 | fprintf(gOutfile, " rotate 1 0 0 %g", 263 | trans[U_ROTATEX]); 264 | tab_indent(); 265 | fprintf(gOutfile, " rotate 0 1 0 %g", 266 | trans[U_ROTATEY]); 267 | tab_indent(); 268 | fprintf(gOutfile, " rotate 0 0 1 %g", 269 | trans[U_ROTATEZ]); 270 | } 271 | if (tflag) { 272 | fprintf(gOutfile, " translate %g %g %g", 273 | trans[U_TRANSX], trans[U_TRANSY], trans[U_TRANSZ]); 274 | } 275 | break; 276 | 277 | case OUTPUT_POVRAY_10: 278 | if (sflag) { 279 | fprintf(gOutfile, " scale %g %g %g", 280 | trans[U_SCALEX], trans[U_SCALEY], trans[U_SCALEZ]); 281 | } 282 | if (rflag) { 283 | fprintf(gOutfile, " rotate %g %g %g", 284 | trans[U_ROTATEX], trans[U_ROTATEY], trans[U_ROTATEZ]); 285 | } 286 | if (tflag) { 287 | fprintf(gOutfile, " translate %g %g %g", 288 | trans[U_TRANSX], trans[U_TRANSY], trans[U_TRANSZ]); 289 | } 290 | break; 291 | 292 | case OUTPUT_POVRAY_20: 293 | case OUTPUT_POVRAY_30: 294 | case OUTPUT_POLYRAY: 295 | if (sflag) { 296 | fprintf(gOutfile, " scale <%g, %g, %g>", 297 | trans[U_SCALEX], trans[U_SCALEY], trans[U_SCALEZ]); 298 | } 299 | if (rflag) { 300 | tab_indent(); 301 | fprintf(gOutfile, " rotate <%g, %g, %g>", 302 | trans[U_ROTATEX], trans[U_ROTATEY], trans[U_ROTATEZ]); 303 | } 304 | if (tflag) { 305 | tab_indent(); 306 | fprintf(gOutfile, " translate <%g, %g, %g>", 307 | trans[U_TRANSX], trans[U_TRANSY], trans[U_TRANSZ]); 308 | } 309 | break; 310 | 311 | case OUTPUT_ART: 312 | if (sflag) { 313 | tab_indent(); 314 | fprintf(gOutfile, "scale(%g, %g, %g)\n", 315 | trans[U_SCALEX], trans[U_SCALEY], trans[U_SCALEZ]); 316 | } 317 | if (rflag) { 318 | tab_indent(); 319 | fprintf(gOutfile, "rotate(%g, x)\n", 320 | trans[U_ROTATEX]); 321 | tab_indent(); 322 | fprintf(gOutfile, "rotate(%g, y)\n", 323 | trans[U_ROTATEY]); 324 | tab_indent(); 325 | fprintf(gOutfile, "rotate(%g, z)\n", 326 | trans[U_ROTATEZ]); 327 | } 328 | if (tflag) { 329 | tab_indent(); 330 | fprintf(gOutfile, "translate(%g, %g, %g)\n", 331 | trans[U_TRANSX], trans[U_TRANSY], trans[U_TRANSZ]); 332 | } 333 | break; 334 | 335 | case OUTPUT_3DMF: 336 | if (tflag) { 337 | tab_indent(); 338 | fprintf(gOutfile, "Translate ( %g %g %g )\n", 339 | trans[U_TRANSX], trans[U_TRANSY], trans[U_TRANSZ]); 340 | } 341 | if (rflag) { 342 | tab_indent(); 343 | fprintf(gOutfile, "Rotate ( Z %g )\n", 344 | trans[U_ROTATEZ]); 345 | tab_indent(); 346 | fprintf(gOutfile, "Rotate ( Y %g )\n", 347 | trans[U_ROTATEY]); 348 | tab_indent(); 349 | fprintf(gOutfile, "Rotate ( X %g )\n", 350 | trans[U_ROTATEX]); 351 | } 352 | if (sflag) { 353 | tab_indent(); 354 | fprintf(gOutfile, "Scale ( %g %g %g )\n", 355 | trans[U_SCALEX], trans[U_SCALEY], trans[U_SCALEZ]); 356 | } 357 | break; 358 | 359 | case OUTPUT_VRML1: 360 | if (sflag) { 361 | tab_indent(); 362 | fprintf(gOutfile, "scaleFactor %g %g %g\n", 363 | trans[U_SCALEX], trans[U_SCALEY], trans[U_SCALEZ]); 364 | } 365 | if (rflag) { 366 | SET_COORD3(rotang, trans[U_ROTATEX], trans[U_ROTATEY], 367 | trans[U_ROTATEZ]); 368 | lib_calc_rotation_axis(rotang, axis); 369 | tab_indent(); 370 | fprintf(gOutfile, "rotation %g %g %g %g\n", 371 | axis[0], axis[1], axis[2], axis[3]); 372 | } 373 | if (tflag) { 374 | tab_indent(); 375 | fprintf(gOutfile, "translation %g %g %g\n", 376 | trans[U_TRANSX], trans[U_TRANSY], trans[U_TRANSZ]); 377 | } 378 | break; 379 | 380 | case OUTPUT_VRML2: 381 | if (sflag) { 382 | tab_indent(); 383 | fprintf(gOutfile, "scale %g %g %g\n", 384 | trans[U_SCALEX], trans[U_SCALEY], trans[U_SCALEZ]); 385 | } 386 | if (rflag) { 387 | SET_COORD3(rotang, trans[U_ROTATEX], trans[U_ROTATEY], 388 | trans[U_ROTATEZ]); 389 | lib_calc_rotation_axis(rotang, axis); 390 | tab_indent(); 391 | fprintf(gOutfile, "rotation %g %g %g %g\n", 392 | axis[0], axis[1], axis[2], axis[3]); 393 | } 394 | if (tflag) { 395 | tab_indent(); 396 | fprintf(gOutfile, "translation %g %g %g\n", 397 | trans[U_TRANSX], trans[U_TRANSY], trans[U_TRANSZ]); 398 | } 399 | break; 400 | 401 | default: 402 | fprintf(stderr, "Internal Error: bad file type in libtx.c\n"); 403 | exit(1); 404 | break; 405 | } 406 | } /* lib_output_tx_sequence */ 407 | 408 | void 409 | lib_tx_pop() 410 | { 411 | tx_ptr last_tx; 412 | 413 | if (TxStack == NULL) { 414 | fprintf(stderr, "Attempt to pop beyond bottom of transform stack\n"); 415 | } 416 | else { 417 | last_tx = TxStack; 418 | lib_copy_matrix(CurrentTx, last_tx->tx); 419 | TxStack = TxStack->next; 420 | free(last_tx); 421 | } 422 | } 423 | 424 | void 425 | lib_tx_push() 426 | { 427 | tx_ptr new_tx; 428 | 429 | if ((new_tx = malloc(sizeof(struct tx_struct))) == NULL) { 430 | fprintf(stderr, "Failed to allocate polygon data\n"); 431 | exit(EXIT_FAIL); 432 | } 433 | lib_copy_matrix(new_tx->tx, CurrentTx); 434 | new_tx->next = TxStack; 435 | TxStack = new_tx; 436 | } 437 | 438 | #ifdef ANSI_FN_DEF 439 | void lib_tx_rotate(int axis, double angle) 440 | #else 441 | void lib_tx_rotate(axis, angle) 442 | int axis; 443 | double angle; 444 | #endif 445 | { 446 | MATRIX mx1, mx2; 447 | 448 | lib_create_rotate_matrix(mx1, axis, angle); 449 | lib_copy_matrix(mx2, CurrentTx); 450 | lib_matrix_multiply(CurrentTx, mx1, mx2); 451 | } 452 | 453 | #ifdef ANSI_FN_DEF 454 | void lib_tx_scale(COORD3 vec) 455 | #else 456 | void lib_tx_scale(vec) 457 | COORD3 vec; 458 | #endif 459 | { 460 | MATRIX mx1, mx2; 461 | 462 | lib_create_scale_matrix(mx1, vec); 463 | lib_copy_matrix(mx2, CurrentTx); 464 | lib_matrix_multiply(CurrentTx, mx1, mx2); 465 | } 466 | 467 | /*-----------------------------------------------------------------*/ 468 | #ifdef ANSI_FN_DEF 469 | void lib_tx_translate(COORD3 vec) 470 | #else 471 | void lib_tx_translate(vec) 472 | COORD3 vec; 473 | #endif 474 | { 475 | MATRIX mx1, mx2; 476 | 477 | lib_create_translate_matrix(mx1, vec); 478 | lib_copy_matrix(mx2, CurrentTx); 479 | lib_matrix_multiply(CurrentTx, mx1, mx2); 480 | } 481 | 482 | /*-----------------------------------------------------------------*/ 483 | /* From Graphics Gems II, "unmatrix" written by Spencer W. Thomas. 484 | Note that tran has to have at least 16 entries which will be set 485 | to: 486 | Sx, Sy, Sz, Shearxy, Shearxz, Shearyz, Rx, Ry, Rz, Tx, Ty, Tz, 487 | P(x, y, z, w) 488 | */ 489 | #ifdef ANSI_FN_DEF 490 | int lib_tx_unwind(MATRIX tx_mat, double *tran) 491 | #else 492 | int lib_tx_unwind(tx_mat, tran) 493 | MATRIX tx_mat; 494 | double *tran; 495 | #endif 496 | { 497 | int i, j; 498 | MATRIX locmat, pmat, invpmat; 499 | COORD4 prhs, psol; 500 | COORD3 row[3]; 501 | 502 | lib_copy_matrix(locmat, tx_mat); 503 | 504 | /* Divide through by the homogenous value (normalize) */ 505 | if (locmat[3][3] != 0.0) 506 | for (i=0;i<4;i++) 507 | for (j=0;j<4;j++) 508 | locmat[i][j] /= locmat[3][3]; 509 | 510 | /* pmat is used to solve for perspective, but it also provides 511 | an easy way to test for singularity of the upper 3x3 component */ 512 | lib_copy_matrix(pmat, locmat); 513 | for (i=0;i<3;i++) 514 | pmat[i][3] = 0.0; 515 | pmat[3][3] = 1.0; 516 | 517 | if (lib_matrix_det4x4(pmat) == 0.0) 518 | return 0; 519 | 520 | /* First, isolate perspective */ 521 | if (locmat[0][3] != 0.0 || 522 | locmat[1][3] != 0.0 || 523 | locmat[2][3] != 0.0) { 524 | /* prhs is the right hand side of the equation */ 525 | prhs[X] = locmat[0][3]; 526 | prhs[Y] = locmat[1][3]; 527 | prhs[Z] = locmat[2][3]; 528 | prhs[W] = locmat[3][3]; 529 | 530 | /* Solve the equation by inverting pmat and multiplying 531 | prhs by the inverse. */ 532 | lib_invert_matrix(invpmat, pmat); 533 | lib_transform_coord(psol, prhs, invpmat); 534 | 535 | /* Save the perspective information */ 536 | tran[U_PERSPX] = psol[X]; 537 | tran[U_PERSPY] = psol[Y]; 538 | tran[U_PERSPZ] = psol[Z]; 539 | tran[U_PERSPW] = psol[W]; 540 | 541 | /* Clear the perspective partition */ 542 | locmat[0][3] = 0.0; 543 | locmat[1][3] = 0.0; 544 | locmat[2][3] = 0.0; 545 | locmat[3][3] = 1.0; 546 | } 547 | else { 548 | /* No perspective */ 549 | tran[U_PERSPX] = 0.0; 550 | tran[U_PERSPY] = 0.0; 551 | tran[U_PERSPZ] = 0.0; 552 | tran[U_PERSPW] = 0.0; 553 | } 554 | 555 | /* Pull out the translation */ 556 | for (i=0;i<3;i++) { 557 | tran[U_TRANSX+i] = locmat[3][i]; 558 | locmat[3][i] = 0.0; 559 | } 560 | 561 | /* Figure out scale and shear */ 562 | for (i=0;i<3;i++) { 563 | row[i][X] = locmat[i][0]; 564 | row[i][Y] = locmat[i][1]; 565 | row[i][Z] = locmat[i][2]; 566 | } 567 | /* Compute X scale factor and normalize the first row */ 568 | tran[U_SCALEX] = lib_normalize_vector(row[0]); 569 | 570 | /* Compute XY shear factor and make 2nd row orthogonal to 1st */ 571 | tran[U_SHEARXY] = DOT_PRODUCT(row[0], row[1]); 572 | COMB_COORD(row[1], row[1], row[0], 1.0, -tran[U_SHEARXY]); 573 | 574 | /* Compute Y scale and normalize 2nd row */ 575 | tran[U_SCALEY] = lib_normalize_vector(row[1]); 576 | tran[U_SHEARXY] /= tran[U_SCALEY]; 577 | 578 | /* Compute XZ and YZ shears, orthogonalize 3rd row */ 579 | tran[U_SHEARXZ] = DOT_PRODUCT(row[0], row[2]); 580 | COMB_COORD(row[2], row[2], row[0], 1.0, -tran[U_SHEARXZ]); 581 | tran[U_SHEARYZ] = DOT_PRODUCT(row[1], row[2]); 582 | COMB_COORD(row[2], row[2], row[1], 1.0, -tran[U_SHEARYZ]); 583 | 584 | /* Get Z scale and normalize 3rd row */ 585 | tran[U_SCALEZ] = lib_normalize_vector(row[2]); 586 | tran[U_SHEARXZ] /= tran[U_SCALEZ]; 587 | tran[U_SHEARYZ] /= tran[U_SCALEZ]; 588 | 589 | /* At this point, the matrix (in rows[]) is orthonormal. 590 | Check for a coordinate system flip. If the determinant 591 | is -1, then negate thematrix and the scaling factors */ 592 | CROSS(prhs, row[1], row[2]); 593 | if (DOT_PRODUCT(row[0], prhs) < 0.0) { 594 | for (i=0;i<3;i++) { 595 | tran[U_SCALEX+i] *= -1.0; 596 | row[i][X] *= -1.0; 597 | row[i][Y] *= -1.0; 598 | row[i][Z] *= -1.0; 599 | } 600 | } 601 | 602 | /* Get the rotations out */ 603 | tran[U_ROTATEY] = asin(-row[0][Z]); 604 | if (cos(tran[U_ROTATEY]) != 0) { 605 | if (fabs(row[1][Z]) < EPSILON && fabs(row[2][Z]) < EPSILON) 606 | tran[U_ROTATEX] = 0.0; 607 | else 608 | tran[U_ROTATEX] = atan2(row[1][Z], row[2][Z]); 609 | if (fabs(row[0][Y]) < EPSILON && fabs(row[0][X]) < EPSILON) 610 | tran[U_ROTATEZ] = 0.0; 611 | else 612 | tran[U_ROTATEZ] = atan2(row[0][Y], row[0][X]); 613 | } 614 | else { 615 | tran[U_ROTATEX] = atan2(row[1][X], row[1][Y]); 616 | tran[U_ROTATEZ] = 0.0; 617 | } 618 | 619 | return 1; 620 | } 621 | -------------------------------------------------------------------------------- /src/libvec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libvec.h - vector library definitions 3 | * 4 | * Version: 2.2 (11/17/87) 5 | * Author: Eric Haines 6 | * 7 | * Modified: 1 October 1992 8 | * Alexander R. Enzmann 9 | * 10 | * Modified: 2 August 1993 - More ANSI C compatibility fixes (LIBVEC_H) 11 | * Eduard [esp] Schwan 12 | * 13 | */ 14 | #ifndef LIBVEC_H 15 | #define LIBVEC_H 16 | 17 | #include "def.h" 18 | 19 | #if __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #define X_AXIS 0 24 | #define Y_AXIS 1 25 | #define Z_AXIS 2 26 | 27 | /* Basic math functions */ 28 | void lib_zero_matrix PARAMS((MATRIX mx)); 29 | void lib_create_identity_matrix PARAMS((MATRIX mx)); 30 | void lib_copy_matrix PARAMS((MATRIX mres, MATRIX mx)); 31 | void lib_create_translate_matrix PARAMS((MATRIX mx, COORD3 vec)); 32 | void lib_create_scale_matrix PARAMS((MATRIX mx, COORD3 vec)); 33 | void lib_create_rotate_matrix PARAMS((MATRIX mx, int axis, double angle)); 34 | void lib_create_axis_rotate_matrix PARAMS((MATRIX mx, COORD3 rvec, 35 | double angle)); 36 | void lib_create_canonical_matrix PARAMS((MATRIX trans, MATRIX itrans, 37 | COORD3 origin, COORD3 up)); 38 | void lib_create_view_matrix PARAMS((MATRIX T, COORD3 from, COORD3 at, 39 | COORD3 up, int xres, int yres, 40 | double angle, double aspect)); 41 | void lib_calc_view_vector PARAMS((COORD3 from, COORD3 at, COORD3 up, COORD4 axis)); 42 | void lib_transform_coord PARAMS((COORD4 vres, COORD4 vec, MATRIX mx)); 43 | void lib_transform_point PARAMS((COORD3 vres, COORD3 vec, MATRIX mx)); 44 | void lib_transform_vector PARAMS((COORD3 vres, COORD3 vec, MATRIX mx)); 45 | void lib_transform_normal PARAMS((COORD3 vres, COORD3 vec, MATRIX mx)); 46 | void lib_transpose_matrix PARAMS((MATRIX mxres, MATRIX mx)); 47 | void lib_matrix_multiply PARAMS((MATRIX mxres, MATRIX mx1, MATRIX mx2)); 48 | double lib_matrix_det4x4 PARAMS((MATRIX)); 49 | void lib_invert_matrix PARAMS((MATRIX, MATRIX)); 50 | void lib_rotate_cube_face PARAMS((COORD3 vec, int major_axis, int mod_face)); 51 | int lib_clip_to_box PARAMS((COORD3 start, COORD3 end, double bounds[2][3])); 52 | double lib_normalize_vector PARAMS((COORD3 cvec)); 53 | double lib_gauss_rand PARAMS((long iseed)); 54 | void lib_create_orthogonal_vectors PARAMS((COORD3 axis, COORD3 basis1, 55 | COORD3 basis2)); 56 | void lib_calc_rotation_axis PARAMS((COORD3 rot_angles, COORD4 axis)); 57 | 58 | #if __cplusplus 59 | } 60 | #endif 61 | 62 | #endif /* LIBVEC_H */ 63 | -------------------------------------------------------------------------------- /src/makefile: -------------------------------------------------------------------------------- 1 | # generic makefile for standard procedural databases 2 | # Author: Eric Haines 3 | 4 | CC=cc -O 5 | SUFOBJ=.o 6 | SUFEXE= 7 | INC=def.h lib.h 8 | LIBOBJ=drv_null$(SUFOBJ) libini$(SUFOBJ) libinf$(SUFOBJ) libpr1$(SUFOBJ) \ 9 | libpr2$(SUFOBJ) libpr3$(SUFOBJ) libply$(SUFOBJ) libdmp$(SUFOBJ) \ 10 | libvec$(SUFOBJ) libtx$(SUFOBJ) 11 | BASELIB=-lm 12 | 13 | all: balls gears mount rings teapot tetra tree \ 14 | readdxf readnff readobj \ 15 | sample lattice shells jacks sombrero nurbtst 16 | 17 | drv_null$(SUFOBJ): $(INC) drv_null.c drv.h 18 | $(CC) -c drv_null.c 19 | 20 | libini$(SUFOBJ): $(INC) libini.c 21 | $(CC) -c libini.c 22 | 23 | libinf$(SUFOBJ): $(INC) libinf.c 24 | $(CC) -c libinf.c 25 | 26 | libpr1$(SUFOBJ): $(INC) libpr1.c 27 | $(CC) -c libpr1.c 28 | 29 | libpr2$(SUFOBJ): $(INC) libpr2.c 30 | $(CC) -c libpr2.c 31 | 32 | libpr3$(SUFOBJ): $(INC) libpr3.c 33 | $(CC) -c libpr3.c 34 | 35 | libply$(SUFOBJ): $(INC) libply.c 36 | $(CC) -c libply.c 37 | 38 | libdmp$(SUFOBJ): $(INC) libdmp.c 39 | $(CC) -c libdmp.c 40 | 41 | libvec$(SUFOBJ): $(INC) libvec.c 42 | $(CC) -c libvec.c 43 | 44 | libtx$(SUFOBJ): $(INC) libtx.c 45 | $(CC) -c libtx.c 46 | 47 | balls$(SUFEXE): $(LIBOBJ) balls.c 48 | $(CC) -o balls$(SUFEXE) balls.c $(LIBOBJ) $(BASELIB) 49 | 50 | gears$(SUFEXE): $(LIBOBJ) gears.c 51 | $(CC) -o gears$(SUFEXE) gears.c $(LIBOBJ) $(BASELIB) 52 | 53 | mount$(SUFEXE): $(LIBOBJ) mount.c 54 | $(CC) -o mount$(SUFEXE) mount.c $(LIBOBJ) $(BASELIB) 55 | 56 | rings$(SUFEXE): $(LIBOBJ) rings.c 57 | $(CC) -o rings$(SUFEXE) rings.c $(LIBOBJ) $(BASELIB) 58 | 59 | teapot$(SUFEXE): $(LIBOBJ) teapot.c 60 | $(CC) -o teapot$(SUFEXE) teapot.c $(LIBOBJ) $(BASELIB) 61 | 62 | tetra$(SUFEXE): $(LIBOBJ) tetra.c 63 | $(CC) -o tetra$(SUFEXE) tetra.c $(LIBOBJ) $(BASELIB) 64 | 65 | tree$(SUFEXE): $(LIBOBJ) tree.c 66 | $(CC) -o tree$(SUFEXE) tree.c $(LIBOBJ) $(BASELIB) 67 | 68 | readdxf$(SUFEXE): $(LIBOBJ) readdxf.c 69 | $(CC) -o readdxf$(SUFEXE) readdxf.c $(LIBOBJ) $(BASELIB) 70 | 71 | readnff$(SUFEXE): $(LIBOBJ) readnff.c 72 | $(CC) -o readnff$(SUFEXE) readnff.c $(LIBOBJ) $(BASELIB) 73 | 74 | readobj$(SUFEXE): $(LIBOBJ) readobj.c 75 | $(CC) -o readobj$(SUFEXE) readobj.c $(LIBOBJ) $(BASELIB) 76 | 77 | sample$(SUFEXE): $(LIBOBJ) sample.c 78 | $(CC) -o sample$(SUFEXE) sample.c $(LIBOBJ) $(BASELIB) 79 | 80 | lattice$(SUFEXE): $(LIBOBJ) lattice.c 81 | $(CC) -o lattice$(SUFEXE) lattice.c $(LIBOBJ) $(BASELIB) 82 | 83 | shells$(SUFEXE): $(LIBOBJ) shells.c 84 | $(CC) -o shells$(SUFEXE) shells.c $(LIBOBJ) $(BASELIB) 85 | 86 | jacks$(SUFEXE): $(LIBOBJ) jacks.c 87 | $(CC) -o jacks$(SUFEXE) jacks.c $(LIBOBJ) $(BASELIB) 88 | 89 | sombrero$(SUFEXE): $(LIBOBJ) sombrero.c 90 | $(CC) -o sombrero$(SUFEXE) sombrero.c $(LIBOBJ) $(BASELIB) 91 | 92 | nurbtst$(SUFEXE): $(LIBOBJ) nurbtst.c 93 | $(CC) -o nurbtst$(SUFEXE) nurbtst.c $(LIBOBJ) $(BASELIB) 94 | 95 | clean: 96 | rm -f balls gears mount rings teapot tetra tree \ 97 | readdxf readnff readobj \ 98 | sample lattice shells jacks sombrero nurbtst 99 | rm -f $(LIBOBJ) 100 | -------------------------------------------------------------------------------- /src/makefile.dj: -------------------------------------------------------------------------------- 1 | # makefile for standard procedural databases 2 | # Modified to support DJGPP+GRX graphics -- Antonio Costa INESC 3 | 4 | CC=gcc -O -m486 -s 5 | CC2=gcc -m486 -s 6 | SUFOBJ=.o 7 | SUFEXE=.exe 8 | INC=def.h lib.h 9 | LIBOBJ=drv_ibm$(SUFOBJ) libini$(SUFOBJ) libinf$(SUFOBJ) libpr1$(SUFOBJ) libpr2$(SUFOBJ) libpr3$(SUFOBJ) libply$(SUFOBJ) libdmp$(SUFOBJ) libvec$(SUFOBJ) libtx$(SUFOBJ) 10 | BASELIB=-lgrx -lm 11 | 12 | all: balls gears mount rings teapot tetra tree \ 13 | readdxf readnff readobj \ 14 | sample lattice shells jacks sombrero nurbtst 15 | 16 | drv_ibm$(SUFOBJ): $(INC) drv_ibm.c drv.h 17 | $(CC) -DGRX -c drv_ibm.c 18 | 19 | libini$(SUFOBJ): $(INC) libini.c 20 | $(CC) -c libini.c 21 | 22 | libinf$(SUFOBJ): $(INC) libinf.c 23 | $(CC) -c libinf.c 24 | 25 | libpr1$(SUFOBJ): $(INC) libpr1.c 26 | $(CC) -c libpr1.c 27 | 28 | libpr2$(SUFOBJ): $(INC) libpr2.c 29 | $(CC) -c libpr2.c 30 | 31 | libpr3$(SUFOBJ): $(INC) libpr3.c 32 | $(CC) -c libpr3.c 33 | 34 | libply$(SUFOBJ): $(INC) libply.c 35 | $(CC) -c libply.c 36 | 37 | libdmp$(SUFOBJ): $(INC) libdmp.c 38 | $(CC) -c libdmp.c 39 | 40 | libvec$(SUFOBJ): $(INC) libvec.c 41 | $(CC) -c libvec.c 42 | 43 | libtx$(SUFOBJ): $(INC) libtx.c 44 | $(CC) -c libtx.c 45 | 46 | balls$(EXE): $(LIBOBJ) balls.c 47 | $(CC) -o balls$(EXE) balls.c $(LIBOBJ) $(BASELIB) 48 | aout2exe $* 49 | @del $* >nul 50 | 51 | gears$(EXE): $(LIBOBJ) gears.c 52 | $(CC) -o gears$(EXE) gears.c $(LIBOBJ) $(BASELIB) 53 | aout2exe $* 54 | @del $* >nul 55 | 56 | mount$(EXE): $(LIBOBJ) mount.c 57 | $(CC) -o mount$(EXE) mount.c $(LIBOBJ) $(BASELIB) 58 | aout2exe $* 59 | @del $* >nul 60 | 61 | rings$(EXE): $(LIBOBJ) rings.c 62 | $(CC) -o rings$(EXE) rings.c $(LIBOBJ) $(BASELIB) 63 | aout2exe $* 64 | @del $* >nul 65 | 66 | teapot$(EXE): $(LIBOBJ) teapot.c 67 | $(CC) -o teapot$(EXE) teapot.c $(LIBOBJ) $(BASELIB) 68 | aout2exe $* 69 | @del $* >nul 70 | 71 | tetra$(EXE): $(LIBOBJ) tetra.c 72 | $(CC) -o tetra$(EXE) tetra.c $(LIBOBJ) $(BASELIB) 73 | aout2exe $* 74 | @del $* >nul 75 | 76 | tree$(EXE): $(LIBOBJ) tree.c 77 | $(CC) -o tree$(EXE) tree.c $(LIBOBJ) $(BASELIB) 78 | aout2exe $* 79 | @del $* >nul 80 | 81 | readdxf$(EXE): $(LIBOBJ) readdxf.c 82 | $(CC) -o readdxf$(EXE) readdxf.c $(LIBOBJ) $(BASELIB) 83 | aout2exe $* 84 | @del $* >nul 85 | 86 | readnff$(EXE): $(LIBOBJ) readnff.c 87 | $(CC) -o readnff$(EXE) readnff.c $(LIBOBJ) $(BASELIB) 88 | aout2exe $* 89 | @del $* >nul 90 | 91 | readobj$(EXE): $(LIBOBJ) readobj.c 92 | $(CC) -o readobj$(EXE) readobj.c $(LIBOBJ) $(BASELIB) 93 | aout2exe $* 94 | @del $* >nul 95 | 96 | sample$(EXE): $(LIBOBJ) sample.c 97 | $(CC) -o sample$(EXE) sample.c $(LIBOBJ) $(BASELIB) 98 | aout2exe $* 99 | @del $* >nul 100 | 101 | lattice$(EXE): $(LIBOBJ) lattice.c 102 | $(CC) -o lattice$(EXE) lattice.c $(LIBOBJ) $(BASELIB) 103 | aout2exe $* 104 | @del $* >nul 105 | 106 | shells$(EXE): $(LIBOBJ) shells.c 107 | $(CC) -o shells$(EXE) shells.c $(LIBOBJ) $(BASELIB) 108 | aout2exe $* 109 | @del $* >nul 110 | 111 | jacks$(EXE): $(LIBOBJ) jacks.c 112 | $(CC) -o jacks$(EXE) jacks.c $(LIBOBJ) $(BASELIB) 113 | aout2exe $* 114 | @del $* >nul 115 | 116 | sombrero$(EXE): $(LIBOBJ) sombrero.c 117 | $(CC) -o sombrero$(EXE) sombrero.c $(LIBOBJ) $(BASELIB) 118 | aout2exe $* 119 | @del $* >nul 120 | 121 | nurbtst$(EXE): $(LIBOBJ) nurbtst.c 122 | $(CC) -o nurbtst$(EXE) nurbtst.c $(LIBOBJ) $(BASELIB) 123 | aout2exe $* 124 | @del $* >nul 125 | 126 | clean: 127 | @del balls.exe >nul 128 | @del gears.exe >nul 129 | @del mount.exe >nul 130 | @del rings.exe >nul 131 | @del teapot.exe >nul 132 | @del tetra.exe >nul 133 | @del tree.exe >nul 134 | @del readdxf.exe >nul 135 | @del readnff.exe >nul 136 | @del readobj.exe >nul 137 | @del sample.exe >nul 138 | @del lattice.exe >nul 139 | @del shells.exe >nul 140 | @del jacks.exe >nul 141 | @del sombrero.exe >nul 142 | @del nurbtst.exe >nul 143 | @del *.o >nul 144 | @echo Clean done. 145 | -------------------------------------------------------------------------------- /src/makefile.dos: -------------------------------------------------------------------------------- 1 | # Makefile for the SPD stuff - generic for IBM clones, 2 | # modify to support whatever compiler you have. 3 | CC =cc 4 | # 5 | #CFLAGS =-mx 6 | CFLAGS =-O -Aa 7 | EXE = exe 8 | OBJ = o 9 | 10 | # DOS version: 11 | #SPDOBJS = drv_ibm.$(OBJ) libini.$(OBJ) libinf.$(OBJ) libpr1.$(OBJ) libpr2.$(OBJ) libpr3.$(OBJ) libply.$(OBJ) libdmp.$(OBJ) libvec.$(OBJ) libtx.$(OBJ) 12 | # other versions... 13 | SPDOBJS = drv_null.$(OBJ) libini.$(OBJ) libinf.$(OBJ) libpr1.$(OBJ) libpr2.$(OBJ) libpr3.$(OBJ) libply.$(OBJ) libdmp.$(OBJ) libvec.$(OBJ) libtx.$(OBJ) 14 | 15 | # Zortech specific graphics library 16 | #LIBFILES=fg.lib 17 | #LIBFILES=fgp.lib 18 | LIBFILES=-lm 19 | 20 | all: balls.$(EXE) gears.$(EXE) mount.$(EXE) rings.$(EXE) teapot.$(EXE) \ 21 | tetra.$(EXE) tree.$(EXE) \ 22 | readdxf.$(EXE) readnff.$(EXE) readobj.$(EXE) \ 23 | sample.$(EXE) lattice.$(EXE) shells.$(EXE) jacks.$(EXE) \ 24 | sombrero.$(EXE) nurbtst.$(EXE) 25 | 26 | # Rule to compile c progs into obj's 27 | .c.$(OBJ): 28 | $(CC) $(CFLAGS) -c $< 29 | 30 | # DOS only 31 | #drv_ibm.$(OBJ): drv_ibm.c drv.h def.h 32 | 33 | drv_null.$(OBJ): drv_null.c drv.h def.h 34 | 35 | libini.$(OBJ): libini.c lib.h libvec.h drv.h 36 | 37 | libinf.$(OBJ): libinf.c lib.h libvec.h drv.h 38 | 39 | libpr1.$(OBJ): libpr1.c lib.h libvec.h drv.h 40 | 41 | libpr2.$(OBJ): libpr2.c lib.h libvec.h drv.h 42 | 43 | libpr3.$(OBJ): libpr3.c lib.h libvec.h drv.h 44 | 45 | libply.$(OBJ): libply.c lib.h libvec.h drv.h 46 | 47 | libdmp.$(OBJ): libdmp.c lib.h libvec.h drv.h 48 | 49 | libvec.$(OBJ): libvec.c libvec.h 50 | 51 | libtx.$(OBJ): libtx.c lib.h libvec.h drv.h 52 | 53 | balls.$(EXE): balls.$(OBJ) $(SPDOBJS) 54 | $(CC) $(CFLAGS) balls.$(OBJ) $(SPDOBJS) $(LIBFILES) 55 | 56 | gears.$(EXE): gears.$(OBJ) $(SPDOBJS) 57 | $(CC) $(CFLAGS) gears.$(OBJ) $(SPDOBJS) $(LIBFILES) 58 | 59 | mount.$(EXE): mount.$(OBJ) $(SPDOBJS) 60 | $(CC) $(CFLAGS) mount.$(OBJ) $(SPDOBJS) $(LIBFILES) 61 | 62 | rings.$(EXE): rings.$(OBJ) $(SPDOBJS) 63 | $(CC) $(CFLAGS) rings.$(OBJ) $(SPDOBJS) $(LIBFILES) 64 | 65 | teapot.$(EXE): teapot.$(OBJ) $(SPDOBJS) 66 | $(CC) $(CFLAGS) teapot.$(OBJ) $(SPDOBJS) $(LIBFILES) 67 | 68 | tetra.$(EXE): tetra.$(OBJ) $(SPDOBJS) 69 | $(CC) $(CFLAGS) tetra.$(OBJ) $(SPDOBJS) $(LIBFILES) 70 | 71 | tree.$(EXE): tree.$(OBJ) $(SPDOBJS) 72 | $(CC) $(CFLAGS) tree.$(OBJ) $(SPDOBJS) $(LIBFILES) 73 | 74 | readdxf.$(EXE): readdxf.$(OBJ) $(SPDOBJS) 75 | $(CC) $(CFLAGS) readdxf.$(OBJ) $(SPDOBJS) $(LIBFILES) 76 | 77 | readnff.$(EXE): readnff.$(OBJ) $(SPDOBJS) 78 | $(CC) $(CFLAGS) readnff.$(OBJ) $(SPDOBJS) $(LIBFILES) 79 | 80 | readobj.$(EXE): readobj.$(OBJ) $(SPDOBJS) 81 | $(CC) $(CFLAGS) readobj.$(OBJ) $(SPDOBJS) $(LIBFILES) 82 | 83 | sample.$(EXE): sample.$(OBJ) $(SPDOBJS) 84 | $(CC) $(CFLAGS) sample.$(OBJ) $(SPDOBJS) $(LIBFILES) 85 | 86 | lattice.$(EXE): lattice.$(OBJ) $(SPDOBJS) 87 | $(CC) $(CFLAGS) lattice.$(OBJ) $(SPDOBJS) $(LIBFILES) 88 | 89 | shells.$(EXE): shells.$(OBJ) $(SPDOBJS) 90 | $(CC) $(CFLAGS) shells.$(OBJ) $(SPDOBJS) $(LIBFILES) 91 | 92 | jacks.$(EXE): jacks.$(OBJ) $(SPDOBJS) 93 | $(CC) $(CFLAGS) jacks.$(OBJ) $(SPDOBJS) $(LIBFILES) 94 | 95 | sombrero.$(EXE): sombrero.$(OBJ) $(SPDOBJS) 96 | $(CC) $(CFLAGS) sombrero.$(OBJ) $(SPDOBJS) $(LIBFILES) 97 | 98 | nurbtst.$(EXE): nurbtst.$(OBJ) $(SPDOBJS) 99 | $(CC) $(CFLAGS) nurbtst.$(OBJ) $(SPDOBJS) $(LIBFILES) 100 | -------------------------------------------------------------------------------- /src/makefile.hp: -------------------------------------------------------------------------------- 1 | # makefile for standard procedural databases 2 | # Author: Eric Haines 3 | # Works on HP 700 machines, might even work for you 4 | # 5 | # NOTE: assumes you've done a 6 | # export LDOPTS="-a shared" 7 | # before running this makefile (i.e. it uses shared libraries) 8 | 9 | CC=cc -O -Aa 10 | SUFOBJ=.o 11 | SUFEXE=.exe 12 | INC=def.h lib.h 13 | LIBOBJ=drv_hp$(SUFOBJ) libini$(SUFOBJ) libinf$(SUFOBJ) libpr1$(SUFOBJ) libpr2$(SUFOBJ) libpr3$(SUFOBJ) libply$(SUFOBJ) libdmp$(SUFOBJ) libvec$(SUFOBJ) libtx$(SUFOBJ) 14 | BASELIB=-L /usr/lib/X11R5 \ 15 | -L /opt/graphics/common/lib \ 16 | -lXwindow -lhpgfx \ 17 | -lXhp11 -lX11 -lm -ldld 18 | 19 | all: balls gears mount rings teapot tetra tree \ 20 | readdxf readnff readobj \ 21 | sample lattice shells jacks sombrero nurbtst 22 | 23 | drv_hp$(SUFOBJ): $(INC) drv_hp.c drv.h 24 | $(CC) -c drv_hp.c 25 | 26 | libini$(SUFOBJ): $(INC) libini.c 27 | $(CC) -c libini.c 28 | 29 | libinf$(SUFOBJ): $(INC) libinf.c 30 | $(CC) -c libinf.c 31 | 32 | libpr1$(SUFOBJ): $(INC) libpr1.c 33 | $(CC) -c libpr1.c 34 | 35 | libpr2$(SUFOBJ): $(INC) libpr2.c 36 | $(CC) -c libpr2.c 37 | 38 | libpr3$(SUFOBJ): $(INC) libpr3.c 39 | $(CC) -c libpr3.c 40 | 41 | libply$(SUFOBJ): $(INC) libply.c 42 | $(CC) -c libply.c 43 | 44 | libdmp$(SUFOBJ): $(INC) libdmp.c 45 | $(CC) -c libdmp.c 46 | 47 | libtx$(SUFOBJ): $(INC) libtx.c 48 | $(CC) -c libtx.c 49 | 50 | libvec$(SUFOBJ): $(INC) libvec.c 51 | $(CC) -c libvec.c 52 | 53 | balls$(EXE): $(LIBOBJ) balls.c 54 | $(CC) -o balls$(EXE) balls.c $(LIBOBJ) $(BASELIB) 55 | 56 | gears$(EXE): $(LIBOBJ) gears.c 57 | $(CC) -o gears$(EXE) gears.c $(LIBOBJ) $(BASELIB) 58 | 59 | mount$(EXE): $(LIBOBJ) mount.c 60 | $(CC) -o mount$(EXE) mount.c $(LIBOBJ) $(BASELIB) 61 | 62 | rings$(EXE): $(LIBOBJ) rings.c 63 | $(CC) -o rings$(EXE) rings.c $(LIBOBJ) $(BASELIB) 64 | 65 | teapot$(EXE): $(LIBOBJ) teapot.c 66 | $(CC) -o teapot$(EXE) teapot.c $(LIBOBJ) $(BASELIB) 67 | 68 | tetra$(EXE): $(LIBOBJ) tetra.c 69 | $(CC) -o tetra$(EXE) tetra.c $(LIBOBJ) $(BASELIB) 70 | 71 | tree$(EXE): $(LIBOBJ) tree.c 72 | $(CC) -o tree$(EXE) tree.c $(LIBOBJ) $(BASELIB) 73 | 74 | readdxf$(EXE): $(LIBOBJ) readdxf.c 75 | $(CC) -o readdxf$(EXE) readdxf.c $(LIBOBJ) $(BASELIB) 76 | 77 | readnff$(EXE): $(LIBOBJ) readnff.c 78 | $(CC) -o readnff$(EXE) readnff.c $(LIBOBJ) $(BASELIB) 79 | 80 | readobj$(EXE): $(LIBOBJ) readobj.c 81 | $(CC) -o readobj$(EXE) readobj.c $(LIBOBJ) $(BASELIB) 82 | 83 | sample$(EXE): $(LIBOBJ) sample.c 84 | $(CC) -o sample$(EXE) sample.c $(LIBOBJ) $(BASELIB) 85 | 86 | lattice$(EXE): $(LIBOBJ) lattice.c 87 | $(CC) -o lattice$(EXE) lattice.c $(LIBOBJ) $(BASELIB) 88 | 89 | shells$(EXE): $(LIBOBJ) shells.c 90 | $(CC) -o shells$(EXE) shells.c $(LIBOBJ) $(BASELIB) 91 | 92 | jacks$(EXE): $(LIBOBJ) jacks.c 93 | $(CC) -o jacks$(EXE) jacks.c $(LIBOBJ) $(BASELIB) 94 | 95 | sombrero$(EXE): $(LIBOBJ) sombrero.c 96 | $(CC) -o sombrero$(EXE) sombrero.c $(LIBOBJ) $(BASELIB) 97 | 98 | nurbtst$(EXE): $(LIBOBJ) nurbtst.c 99 | $(CC) -o nurbtst$(EXE) nurbtst.c $(LIBOBJ) $(BASELIB) 100 | 101 | clean: 102 | rm -f balls gears mount rings teapot tetra tree \ 103 | readdxf readnff readobj \ 104 | sample lattice shells jacks sombrero nurbtst 105 | rm -f $(LIBOBJ) 106 | -------------------------------------------------------------------------------- /src/makefile.nul: -------------------------------------------------------------------------------- 1 | # generic makefile for standard procedural databases 2 | # Author: Eric Haines 3 | 4 | CC=cc -O 5 | SUFOBJ=.o 6 | SUFEXE= 7 | INC=def.h lib.h 8 | LIBOBJ=drv_null$(SUFOBJ) libini$(SUFOBJ) libinf$(SUFOBJ) libpr1$(SUFOBJ) \ 9 | libpr2$(SUFOBJ) libpr3$(SUFOBJ) libply$(SUFOBJ) libdmp$(SUFOBJ) \ 10 | libvec$(SUFOBJ) libtx$(SUFOBJ) 11 | BASELIB=-lm 12 | 13 | all: balls gears mount rings teapot tetra tree \ 14 | readdxf readnff readobj \ 15 | sample lattice shells jacks sombrero nurbtst 16 | 17 | drv_null$(SUFOBJ): $(INC) drv_null.c drv.h 18 | $(CC) -c drv_null.c 19 | 20 | libini$(SUFOBJ): $(INC) libini.c 21 | $(CC) -c libini.c 22 | 23 | libinf$(SUFOBJ): $(INC) libinf.c 24 | $(CC) -c libinf.c 25 | 26 | libpr1$(SUFOBJ): $(INC) libpr1.c 27 | $(CC) -c libpr1.c 28 | 29 | libpr2$(SUFOBJ): $(INC) libpr2.c 30 | $(CC) -c libpr2.c 31 | 32 | libpr3$(SUFOBJ): $(INC) libpr3.c 33 | $(CC) -c libpr3.c 34 | 35 | libply$(SUFOBJ): $(INC) libply.c 36 | $(CC) -c libply.c 37 | 38 | libdmp$(SUFOBJ): $(INC) libdmp.c 39 | $(CC) -c libdmp.c 40 | 41 | libvec$(SUFOBJ): $(INC) libvec.c 42 | $(CC) -c libvec.c 43 | 44 | libtx$(SUFOBJ): $(INC) libtx.c 45 | $(CC) -c libtx.c 46 | 47 | balls$(SUFEXE): $(LIBOBJ) balls.c 48 | $(CC) -o balls$(SUFEXE) balls.c $(LIBOBJ) $(BASELIB) 49 | 50 | gears$(SUFEXE): $(LIBOBJ) gears.c 51 | $(CC) -o gears$(SUFEXE) gears.c $(LIBOBJ) $(BASELIB) 52 | 53 | mount$(SUFEXE): $(LIBOBJ) mount.c 54 | $(CC) -o mount$(SUFEXE) mount.c $(LIBOBJ) $(BASELIB) 55 | 56 | rings$(SUFEXE): $(LIBOBJ) rings.c 57 | $(CC) -o rings$(SUFEXE) rings.c $(LIBOBJ) $(BASELIB) 58 | 59 | teapot$(SUFEXE): $(LIBOBJ) teapot.c 60 | $(CC) -o teapot$(SUFEXE) teapot.c $(LIBOBJ) $(BASELIB) 61 | 62 | tetra$(SUFEXE): $(LIBOBJ) tetra.c 63 | $(CC) -o tetra$(SUFEXE) tetra.c $(LIBOBJ) $(BASELIB) 64 | 65 | tree$(SUFEXE): $(LIBOBJ) tree.c 66 | $(CC) -o tree$(SUFEXE) tree.c $(LIBOBJ) $(BASELIB) 67 | 68 | readdxf$(SUFEXE): $(LIBOBJ) readdxf.c 69 | $(CC) -o readdxf$(SUFEXE) readdxf.c $(LIBOBJ) $(BASELIB) 70 | 71 | readnff$(SUFEXE): $(LIBOBJ) readnff.c 72 | $(CC) -o readnff$(SUFEXE) readnff.c $(LIBOBJ) $(BASELIB) 73 | 74 | readobj$(SUFEXE): $(LIBOBJ) readobj.c 75 | $(CC) -o readobj$(SUFEXE) readobj.c $(LIBOBJ) $(BASELIB) 76 | 77 | sample$(SUFEXE): $(LIBOBJ) sample.c 78 | $(CC) -o sample$(SUFEXE) sample.c $(LIBOBJ) $(BASELIB) 79 | 80 | lattice$(SUFEXE): $(LIBOBJ) lattice.c 81 | $(CC) -o lattice$(SUFEXE) lattice.c $(LIBOBJ) $(BASELIB) 82 | 83 | shells$(SUFEXE): $(LIBOBJ) shells.c 84 | $(CC) -o shells$(SUFEXE) shells.c $(LIBOBJ) $(BASELIB) 85 | 86 | jacks$(SUFEXE): $(LIBOBJ) jacks.c 87 | $(CC) -o jacks$(SUFEXE) jacks.c $(LIBOBJ) $(BASELIB) 88 | 89 | sombrero$(SUFEXE): $(LIBOBJ) sombrero.c 90 | $(CC) -o sombrero$(SUFEXE) sombrero.c $(LIBOBJ) $(BASELIB) 91 | 92 | nurbtst$(SUFEXE): $(LIBOBJ) nurbtst.c 93 | $(CC) -o nurbtst$(SUFEXE) nurbtst.c $(LIBOBJ) $(BASELIB) 94 | 95 | clean: 96 | rm -f balls gears mount rings teapot tetra tree \ 97 | readdxf readnff readobj \ 98 | sample lattice shells jacks sombrero nurbtst 99 | rm -f $(LIBOBJ) 100 | -------------------------------------------------------------------------------- /src/makefile.x11: -------------------------------------------------------------------------------- 1 | # X11 Driver makefile for standard procedural databases 2 | # Author: Bob Kozdemba 3 | # 4 | # You may have to specify compiler options if the X11 libraries and include 5 | # files are located in directories other than default. 6 | # (i.e. CC=cc -O -I/usr/local/include/X11 -L/usr/local/lib/X11) 7 | # 8 | 9 | CC=cc -O 10 | SUFOBJ=.o 11 | SUFEXE= 12 | INC=def.h lib.h 13 | LIBOBJ=drv_x11$(SUFOBJ) libini$(SUFOBJ) libinf$(SUFOBJ) libpr1$(SUFOBJ) \ 14 | libpr2$(SUFOBJ) libpr3$(SUFOBJ) libply$(SUFOBJ) libdmp$(SUFOBJ) \ 15 | libvec$(SUFOBJ) libtx$(SUFOBJ) 16 | BASELIB=-lX11 -lm 17 | 18 | all: balls gears mount rings teapot tetra tree \ 19 | readdxf readnff readobj \ 20 | sample lattice shells jacks sombrero nurbtst 21 | 22 | drv_x11$(SUFOBJ): $(INC) drv_x11.c drv.h 23 | $(CC) -c drv_x11.c 24 | 25 | libini$(SUFOBJ): $(INC) libini.c 26 | $(CC) -c libini.c 27 | 28 | libinf$(SUFOBJ): $(INC) libinf.c 29 | $(CC) -c libinf.c 30 | 31 | libpr1$(SUFOBJ): $(INC) libpr1.c 32 | $(CC) -c libpr1.c 33 | 34 | libpr2$(SUFOBJ): $(INC) libpr2.c 35 | $(CC) -c libpr2.c 36 | 37 | libpr3$(SUFOBJ): $(INC) libpr3.c 38 | $(CC) -c libpr3.c 39 | 40 | libply$(SUFOBJ): $(INC) libply.c 41 | $(CC) -c libply.c 42 | 43 | libdmp$(SUFOBJ): $(INC) libdmp.c 44 | $(CC) -c libdmp.c 45 | 46 | libvec$(SUFOBJ): $(INC) libvec.c 47 | $(CC) -c libvec.c 48 | 49 | libtx$(SUFOBJ): $(INC) libtx.c 50 | $(CC) -c libtx.c 51 | 52 | balls$(SUFEXE): $(LIBOBJ) balls.c 53 | $(CC) -o balls$(SUFEXE) balls.c $(LIBOBJ) $(BASELIB) 54 | 55 | gears$(SUFEXE): $(LIBOBJ) gears.c 56 | $(CC) -o gears$(SUFEXE) gears.c $(LIBOBJ) $(BASELIB) 57 | 58 | mount$(SUFEXE): $(LIBOBJ) mount.c 59 | $(CC) -o mount$(SUFEXE) mount.c $(LIBOBJ) $(BASELIB) 60 | 61 | rings$(SUFEXE): $(LIBOBJ) rings.c 62 | $(CC) -o rings$(SUFEXE) rings.c $(LIBOBJ) $(BASELIB) 63 | 64 | teapot$(SUFEXE): $(LIBOBJ) teapot.c 65 | $(CC) -o teapot$(SUFEXE) teapot.c $(LIBOBJ) $(BASELIB) 66 | 67 | tetra$(SUFEXE): $(LIBOBJ) tetra.c 68 | $(CC) -o tetra$(SUFEXE) tetra.c $(LIBOBJ) $(BASELIB) 69 | 70 | tree$(SUFEXE): $(LIBOBJ) tree.c 71 | $(CC) -o tree$(SUFEXE) tree.c $(LIBOBJ) $(BASELIB) 72 | 73 | readdxf$(SUFEXE): $(LIBOBJ) readdxf.c 74 | $(CC) -o readdxf$(SUFEXE) readdxf.c $(LIBOBJ) $(BASELIB) 75 | 76 | readnff$(SUFEXE): $(LIBOBJ) readnff.c 77 | $(CC) -o readnff$(SUFEXE) readnff.c $(LIBOBJ) $(BASELIB) 78 | 79 | readobj$(SUFEXE): $(LIBOBJ) readobj.c 80 | $(CC) -o readobj$(SUFEXE) readobj.c $(LIBOBJ) $(BASELIB) 81 | 82 | sample$(SUFEXE): $(LIBOBJ) sample.c 83 | $(CC) -o sample$(SUFEXE) sample.c $(LIBOBJ) $(BASELIB) 84 | 85 | lattice$(SUFEXE): $(LIBOBJ) lattice.c 86 | $(CC) -o lattice$(SUFEXE) lattice.c $(LIBOBJ) $(BASELIB) 87 | 88 | shells$(SUFEXE): $(LIBOBJ) shells.c 89 | $(CC) -o shells$(SUFEXE) shells.c $(LIBOBJ) $(BASELIB) 90 | 91 | jacks$(SUFEXE): $(LIBOBJ) jacks.c 92 | $(CC) -o jacks$(SUFEXE) jacks.c $(LIBOBJ) $(BASELIB) 93 | 94 | sombrero$(SUFEXE): $(LIBOBJ) sombrero.c 95 | $(CC) -o sombrero$(SUFEXE) sombrero.c $(LIBOBJ) $(BASELIB) 96 | 97 | nurbtst$(SUFEXE): $(LIBOBJ) nurbtst.c 98 | $(CC) -o nurbtst$(SUFEXE) nurbtst.c $(LIBOBJ) $(BASELIB) 99 | 100 | clean: 101 | rm -f balls gears mount rings teapot tetra tree \ 102 | readdxf readnff readobj \ 103 | sample lattice shells jacks sombrero nurbtst 104 | rm -f $(LIBOBJ) 105 | -------------------------------------------------------------------------------- /src/mount.c: -------------------------------------------------------------------------------- 1 | /* 2 | * mount.c - creates a fractal mountain, using Carpenter's method with a 3 | * different extension to square grids. A pyramid of 4 glass spheres 4 | * is added in front of the mountain. One light source. 5 | * 6 | * NOTE: the hashing function used to generate the database originally is 7 | * faulty. The function causes repetition to occur within the fractal 8 | * mountain (obviously not very fractal behavior!). A new hashing 9 | * function is included immediately after the old one: merely define 10 | * NEW_HASH if you want to use a better hashing function. To perform ray 11 | * tracing comparison tests you should still use the old, faulty database 12 | * (it may have repetition, but it's still a good test image). 13 | * 14 | * Author: Eric Haines 15 | * 16 | * size_factor determines the number of objects output. 17 | * Total triangular polygons = 2 * (4**size_factor) 18 | * 19 | * size_factor # triangles # spheres 20 | * 1 8 4 21 | * 2 32 4 22 | * 3 128 4 23 | * 24 | * 6 8192 4 25 | */ 26 | 27 | #include 28 | #include 29 | #include /* atoi */ 30 | #include "def.h" 31 | #include "drv.h" /* display_close() */ 32 | #include "lib.h" 33 | 34 | /* Determine which raytracer we will use */ 35 | static int raytracer_format = OUTPUT_RT_DEFAULT; 36 | /* output format determines if polygons or true surfaces are used */ 37 | static int output_format = OUTPUT_CURVES; 38 | 39 | 40 | /* Complexity of the image */ 41 | static int size_factor = 6; 42 | 43 | #ifdef OUTPUT_TO_FILE 44 | static FILE * stdout_file = NULL; 45 | #else 46 | #define stdout_file stdout 47 | #endif /* OUTPUT_TO_FILE */ 48 | 49 | /* to use a much better hashing function, uncomment this next line */ 50 | /* #define JENKINS_HASH */ 51 | 52 | /* fractal dimension - affects variance of z. Between 2 and 3 */ 53 | #define FRACTAL_DIMENSION 2.2 54 | /* change MOUNTAIN_NO to get a different mountain */ 55 | #define MOUNTAIN_NO 21 56 | 57 | /* lower left corner and width of mountain definitions */ 58 | #define X_CORNER -1.0 59 | #define Y_CORNER -1.0 60 | #define WIDTH 2.0 61 | 62 | #ifndef JENKINS_HASH 63 | 64 | /* Hashing function to get a seed for the random number generator. */ 65 | /* This is the old, buggy hashing function - use it if you wish to 66 | * obtain the same image as in the November 1987 IEEE CG&A article. */ 67 | #define hash_rand(A,B,C) ( ( (((unsigned long)(A))<<(23-(C))) + \ 68 | (((unsigned long)(B))<<(15-(C))) \ 69 | + (((unsigned long)(A))<<(7-(C))) ) & 0xffff) 70 | #else 71 | 72 | /* 73 | * Bob Jenkins invented this great, reasonably fast, very nice 74 | * has function. Check out his web page: 75 | * http://ourworld.compuserve.com/homepages/bob_jenkins/blockcip.htm 76 | */ 77 | #define mix(a,b,c) \ 78 | { \ 79 | a -= b; a -= c; a ^= (c>>13); \ 80 | b -= c; b -= a; b ^= (a<<8); \ 81 | c -= a; c -= b; c ^= (b>>13); \ 82 | a -= b; a -= c; a ^= (c>>12); \ 83 | b -= c; b -= a; b ^= (a<<16); \ 84 | c -= a; c -= b; c ^= (b>>5); \ 85 | a -= b; a -= c; a ^= (c>>3); \ 86 | b -= c; b -= a; b ^= (a<<10); \ 87 | c -= a; c -= b; c ^= (b>>15); \ 88 | } 89 | 90 | int 91 | hash_rand(int A, int B, int C) 92 | { 93 | mix(A,B,C) ; 94 | return C & 0xffff ; 95 | } 96 | 97 | #endif 98 | 99 | static double Roughness ; 100 | 101 | /* create a pyramid of crystal spheres */ 102 | static void 103 | create_spheres(center) 104 | COORD4 center; 105 | { 106 | int i; 107 | double angle; 108 | COORD3 axis, pt, new_pt; 109 | COORD4 sphere; 110 | MATRIX mx; 111 | 112 | SET_COORD3(axis, 1.0, 1.0, 0.0); 113 | (void)lib_normalize_vector(axis); 114 | angle = acos((double)(-1.0/3.0)); 115 | 116 | /* set center of pyramid */ 117 | SET_COORD3(pt, 0.0, 0.0, center[W] * sqrt((double)(3.0/2.0))); 118 | 119 | COPY_COORD4(sphere, center); 120 | ADD2_COORD3(sphere, pt); 121 | lib_output_sphere(sphere, output_format); 122 | 123 | lib_create_axis_rotate_matrix(mx, axis, angle); 124 | lib_transform_vector(new_pt, pt, mx); 125 | 126 | for (i = 0; i < 3; i++) { 127 | lib_create_rotate_matrix(mx, Z_AXIS, (double)i * 2.0 * PI / 3.0); 128 | lib_transform_vector(sphere, new_pt, mx); 129 | ADD2_COORD3(sphere, center); 130 | lib_output_sphere(sphere, output_format); 131 | } 132 | } 133 | 134 | /* 135 | * Build mountain section. If at width > 1, split quadrilateral into four 136 | * parts. Else if at width == 1, output quadrilateral as two triangles. 137 | */ 138 | static void 139 | grow_mountain(fnum_pts, width, ll_x, ll_y, ll_fz, lr_fz, ur_fz, ul_fz) 140 | double fnum_pts; 141 | int width; 142 | int ll_x; 143 | int ll_y ; 144 | double ll_fz; 145 | double lr_fz; 146 | double ur_fz; 147 | double ul_fz; 148 | { 149 | long iz; 150 | int half_width, num_tri, num_tri_vert, num_vert; 151 | double l_fx, r_fx, l_fy, u_fy; 152 | double lower_fz, right_fz, upper_fz, left_fz, middle_fz; 153 | double rise_height, hside_length; 154 | COORD3 tri_vert[3]; 155 | 156 | if ( width == 1 ) { 157 | /* calculate x and y coordinates of corners */ 158 | l_fx = X_CORNER + (double)ll_x * WIDTH / fnum_pts; 159 | r_fx = X_CORNER + (double)(ll_x+1) * WIDTH / fnum_pts; 160 | l_fy = Y_CORNER + (double)ll_y * WIDTH / fnum_pts; 161 | u_fy = Y_CORNER + (double)(ll_y+1) * WIDTH / fnum_pts; 162 | 163 | /* output two triangles for section */ 164 | for (num_tri = 0; num_tri < 2; num_tri++) { 165 | for (num_vert = 0; num_vert < 3; num_vert++) { 166 | num_tri_vert = (num_vert + num_tri * 2) % 4; 167 | switch (num_tri_vert) { 168 | case 0: 169 | SET_COORD3(tri_vert[num_vert], l_fx, l_fy, ll_fz); 170 | break; 171 | case 1: 172 | SET_COORD3(tri_vert[num_vert], r_fx, l_fy, lr_fz); 173 | break; 174 | case 2: 175 | SET_COORD3(tri_vert[num_vert], r_fx, u_fy, ur_fz); 176 | break; 177 | case 3: 178 | SET_COORD3(tri_vert[num_vert], l_fx, u_fy, ul_fz); 179 | break; 180 | } 181 | } 182 | lib_output_polygon(3, tri_vert); 183 | } 184 | } else { 185 | /* subdivide edges and move in z direction */ 186 | half_width = width>>1; 187 | hside_length = (double)half_width * WIDTH / fnum_pts; 188 | rise_height = hside_length * Roughness; 189 | 190 | /* for each midpoint, find z */ 191 | iz = MOUNTAIN_NO + hash_rand(ll_x + half_width, ll_y, size_factor); 192 | lower_fz = (ll_fz + lr_fz) / 2.0 + rise_height * lib_gauss_rand(iz); 193 | iz = MOUNTAIN_NO + hash_rand(ll_x + width, ll_y + half_width, 194 | size_factor); 195 | right_fz = ( lr_fz + ur_fz ) / 2.0 + rise_height * lib_gauss_rand(iz); 196 | iz = MOUNTAIN_NO + hash_rand(ll_x + half_width, ll_y + width, 197 | size_factor); 198 | upper_fz = ( ur_fz + ul_fz ) / 2.0 + rise_height * lib_gauss_rand(iz); 199 | iz = MOUNTAIN_NO + hash_rand( ll_x, ll_y + half_width, size_factor); 200 | left_fz = ( ul_fz + ll_fz ) / 2.0 + rise_height * lib_gauss_rand(iz); 201 | iz = MOUNTAIN_NO + hash_rand(ll_x + half_width, ll_y + half_width, 202 | size_factor); 203 | middle_fz = ( ll_fz + lr_fz + ur_fz + ul_fz ) / 4.0 + 204 | 1.4142136 * rise_height * lib_gauss_rand(iz); 205 | 206 | /* check subsections for subdivision or output */ 207 | PLATFORM_MULTITASK(); 208 | if (width == 1< 11 | #include 12 | #include /* atoi */ 13 | #include "def.h" 14 | #include "drv.h" /* display_close() */ 15 | #include "lib.h" 16 | 17 | 18 | /* These may be read from the command line */ 19 | static int size_factor = 1; 20 | static int raytracer_format = OUTPUT_RT_DEFAULT; 21 | static int output_format = OUTPUT_CURVES; 22 | 23 | #ifdef OUTPUT_TO_FILE 24 | static FILE * stdout_file = NULL; 25 | #else 26 | #define stdout_file stdout 27 | #endif /* OUTPUT_TO_FILE */ 28 | 29 | /* Some standard colors */ 30 | static COORD3 White = { 1.0, 1.0, 1.0 }; 31 | static COORD3 Red = { 1.0, 0.0, 0.0 }; 32 | static COORD3 Green = { 0.0, 1.0, 0.0 }; 33 | static COORD3 Blue = { 0.0, 0.0, 1.0 }; 34 | static COORD3 Cyan = { 0.0, 1.0, 1.0 }; 35 | static COORD3 Yellow = { 1.0, 0.0, 1.0 }; 36 | static COORD3 Magenta = { 1.0, 1.0, 0.0 }; 37 | static COORD3 Black = { 0.0, 0.0, 0.0 }; 38 | 39 | float nknots[] = {0, 0, 0, 0, 1.5, 1.5, 3, 3, 3, 3}; /* Non-uniform knot vector */ 40 | float mknots[] = {0, 0, 0, 0, 1, 2, 2, 2, 2}; /* Uniform open knot vector */ 41 | COORD4 ctlpts0[] = {{ 0, 0, 0, 1}, { 1, 0, 3, 1}, { 2, 0,-3, 1}, 42 | { 3, 0, 3, 1}, { 4, 0, 0, 1}}; 43 | COORD4 ctlpts1[] = {{ 0, 1, 0, 1}, { 1, 1, 0, 1}, { 2, 1, 0, 1}, 44 | { 3, 1, 0, 1}, { 4, 1, 0, 1}}; 45 | COORD4 ctlpts2[] = {{ 0, 2, 0, 1}, { 1, 2, 0, 2}, { 2, 2, 5, 0.5}, 46 | { 3, 2, 0, 1}, { 4, 2, 0, 1}}; 47 | COORD4 ctlpts3[] = {{ 0, 3, 0, 1}, { 1, 3, 0, 2}, { 2, 3, 5, 0.5}, 48 | { 3, 3, 0, 1}, { 4, 3, 0, 1}}; 49 | COORD4 ctlpts4[] = {{ 0, 4, 0, 1}, { 1, 4, 0, 1}, { 2, 4, 0, 20}, 50 | { 3, 4, 0, 1}, { 4, 4, 0, 1}}; 51 | COORD4 ctlpts5[] = {{ 0, 5, 0, 1}, { 1, 5,-3, 1}, { 2, 5, 3, 1}, 52 | { 3, 5,-3, 1}, { 4, 5, 0, 1}}; 53 | 54 | /* Build a single NURB patch and dump it */ 55 | static void 56 | create_a_nurb(curve_format) 57 | int curve_format ; 58 | { 59 | COORD4 *ctlpts[6]; 60 | COORD3 vec; 61 | 62 | lib_output_color(NULL, Red, 0.1, 0.7, 0.0, 0.7, 10.0, 0.0, 1.0); 63 | 64 | ctlpts[0] = ctlpts0; 65 | ctlpts[1] = ctlpts1; 66 | ctlpts[2] = ctlpts2; 67 | ctlpts[3] = ctlpts3; 68 | ctlpts[4] = ctlpts4; 69 | ctlpts[5] = ctlpts5; 70 | 71 | lib_tx_push(); 72 | 73 | lib_tx_rotate(Y, DEG2RAD(30.0)); 74 | lib_tx_rotate(X, DEG2RAD(-90.0)); 75 | SET_COORD3(vec, -2.0, -2.5, 0.0); 76 | lib_tx_translate(vec); 77 | 78 | PLATFORM_PROGRESS(0, 1, 2); 79 | /* lib_output_nurb(4, 6, 4, 5, nknots, mknots, ctlpts, curve_format); */ 80 | lib_output_nurb(4, 6, 4, 5, NULL, NULL, ctlpts, curve_format); 81 | PLATFORM_PROGRESS(0, 2, 2); 82 | 83 | lib_tx_pop(); 84 | } 85 | 86 | /* Main driver - looks the same as every other SPD file... */ 87 | int 88 | main(argc, argv) 89 | int argc; 90 | char *argv[]; 91 | { 92 | COORD4 from, at, up; 93 | COORD4 center; 94 | 95 | PLATFORM_INIT(SPD_NURBTST); 96 | 97 | /* Start by defining which raytracer we will be using */ 98 | if ( lib_gen_get_opts( argc, argv, 99 | &size_factor, &raytracer_format, &output_format ) ) { 100 | return EXIT_FAIL; 101 | } 102 | if ( lib_open( raytracer_format, "NurbTst" ) ) { 103 | return EXIT_FAIL; 104 | } 105 | 106 | lib_set_polygonalization(5, 5); 107 | 108 | /* output background color */ 109 | /* NOTE: Do this BEFORE lib_output_viewpoint(), for display_init() */ 110 | lib_output_background_color( Black ) ; 111 | 112 | SET_COORD3(from, 0, 5, -10); 113 | SET_COORD3(at, 0, 0, 0); 114 | SET_COORD3(up, 0, 1, 0); 115 | lib_output_viewpoint(from, at, up, 30.0, 1.0, 0.001, 256, 256); 116 | 117 | SET_COORD4(center, 0, 50, -10, 1.0); 118 | lib_output_light(center); 119 | 120 | create_a_nurb(output_format); 121 | 122 | lib_close(); 123 | 124 | PLATFORM_SHUTDOWN(); 125 | return EXIT_SUCCESS; 126 | } 127 | -------------------------------------------------------------------------------- /src/readdxf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ReadDXF.c - Read polygons from a DXF file and display them. 3 | * The file "view.dat" is processed for the camera view that will be used. 4 | * 5 | * Author: Alexander Enzmann 6 | * 7 | * size_factor is ignored. 8 | * 9 | * size_factor # spheres # squares 10 | * x xx x 11 | */ 12 | 13 | #include 14 | #include 15 | #include /* atoi */ 16 | #include /* strcmp() */ 17 | #include "def.h" 18 | #include "drv.h" /* display_close() */ 19 | #include "lib.h" 20 | 21 | 22 | /* These may be read from the command line */ 23 | static int raytracer_format = OUTPUT_RT_DEFAULT; 24 | static int output_format = OUTPUT_CURVES; 25 | 26 | 27 | #ifdef OUTPUT_TO_FILE 28 | static FILE * stdout_file = NULL; 29 | #else 30 | #define stdout_file stdout 31 | #endif /* OUTPUT_TO_FILE */ 32 | 33 | 34 | /* This is an outrageous hack to read the polygons from a DXF file. 35 | No attempt is made to be smart, just to graph 3DFACEs. If you have 36 | something better, go for it. There are plenty of DXF files that this 37 | routine won't work for... */ 38 | static void 39 | read_dxf_faces( file ) 40 | FILE *file; 41 | { 42 | char buffer[128]; 43 | int i, j, ind, vcnt, fcnt, lineno, maxvert; 44 | float x; 45 | COORD3 face[16]; 46 | 47 | fcnt = lineno = 0; 48 | while (!feof(file)) { 49 | 50 | /* Skip over uninteresting stuff */ 51 | while (!feof(file) && 52 | fgets(buffer, 127, file) != NULL && 53 | strcmp(buffer, "3DFACE\n")) 54 | /* Void - we are reading lines we can't deal with */ 55 | lineno++; 56 | 57 | if (!feof(file)) { 58 | 59 | #if !defined(applec) && !defined(THINK_C) && !defined(__MWERKS__) 60 | /* Hmm, Xander, isn't kbhit() only in MSDOS, not in Unix libraries..? */ 61 | 62 | /* Test to see if we should stop */ 63 | if (kbhit()) { 64 | display_close(0); 65 | fprintf(stderr, "Draw aborted\n"); 66 | exit(EXIT_FAIL); 67 | } 68 | #endif 69 | 70 | /* As long as there are more faces, read them in */ 71 | fgets(buffer, 127, file); /* Skip the "8" */ 72 | lineno++; 73 | 74 | fgets(buffer, 127, file); /* Skip the "0main" */ 75 | lineno++; 76 | 77 | if (buffer[0] == '0') 78 | ; 79 | else if (!strcmp(buffer, "3DFURN\n")) { 80 | fgets(buffer, 127, file); /* Skip the thing after the 3DFURN */ 81 | fgets(buffer, 127, file); /* Skip over the CONTINUOUS */ 82 | lineno += 2; 83 | if (!strcmp(buffer, "CONTINUOUS\n") && 84 | fgets(buffer, 127, file) != NULL && 85 | sscanf(buffer, "%d", &ind) != 0) { 86 | lineno++; 87 | if (ind == 62) { 88 | fgets(buffer, 127, file); /* Max # of vertices? */ 89 | sscanf(buffer, "%d", &maxvert); 90 | fgets(buffer, 127, file); 91 | sscanf(buffer, "%d", &ind); 92 | lineno++; 93 | } else { 94 | maxvert = -1; 95 | } 96 | fgets(buffer, 127, file); 97 | sscanf(buffer, "%f", &x); 98 | lineno++; 99 | goto inside_vertex_loop; 100 | } 101 | else 102 | break; 103 | } else if (!strcmp(buffer, "2\n")) { 104 | fgets(buffer, 127, file); 105 | sscanf(buffer, "%d", &ind); 106 | lineno++; 107 | if (ind == 62) { 108 | fgets(buffer, 127, file); /* Max # of vertices */ 109 | sscanf(buffer, "%d", &maxvert); 110 | fgets(buffer, 127, file); 111 | sscanf(buffer, "%d", &ind); 112 | lineno++; 113 | } else { 114 | maxvert = -1; 115 | } 116 | fgets(buffer, 127, file); 117 | sscanf(buffer, "%f", &x); 118 | lineno++; 119 | goto inside_vertex_loop; 120 | } else 121 | break; 122 | 123 | lineno += 3; 124 | vcnt = 0; 125 | maxvert = -1; 126 | 127 | /* This is a face, read the vertices */ 128 | while (fgets(buffer, 127, file) != NULL && 129 | (sscanf(buffer, "%d", &ind) != 0) && 130 | ind != 0 && 131 | fgets(buffer, 127, file) != NULL && 132 | sscanf(buffer, "%f", &x)) { 133 | 134 | PLATFORM_MULTITASK(); 135 | 136 | lineno += 2; 137 | inside_vertex_loop: 138 | /* Got a vertex value */ 139 | j = ind / 10; 140 | i = ind % 10; 141 | 142 | if (maxvert > 0 && i > maxvert) 143 | break; 144 | else if (i > vcnt) 145 | vcnt = i; 146 | 147 | /* Place the value into the appropriate face */ 148 | if (j == 1) 149 | face[i][X] = x; 150 | else if (j == 2) 151 | face[i][Y] = x; 152 | else if (j == 3) 153 | face[i][Z] = x; 154 | else if (maxvert > 0) 155 | break; 156 | else { 157 | display_close(1); 158 | fprintf(stderr, "Bad vertex component: %d/%d at line: %d\n", 159 | i, j, lineno); 160 | exit(EXIT_FAIL); 161 | } 162 | } 163 | /* Display the polygon */ 164 | if (vcnt > 0) 165 | lib_output_polygon(vcnt+1, face); 166 | /* 167 | printf("Vert[%d]: ", fcnt); 168 | for (i=0;i ", face[i][X], face[i][Y], face[i][Z]); 170 | printf("\n"); 171 | */ 172 | fcnt++; 173 | } 174 | } 175 | } 176 | 177 | /* Read in the camera specifics: from, at, up, fov. Aspect is hard coded 178 | to 1. */ 179 | static void 180 | setup_view() 181 | { 182 | char buffer[128]; 183 | COORD3 from, at, up; 184 | double angle; 185 | FILE *setup; 186 | 187 | /* output viewpoint */ 188 | if ((setup = fopen("view.dat", "r")) != NULL) { 189 | if (fgets(buffer, 127, setup) && 190 | sscanf(buffer, "%lf %lf %lf", 191 | &from[X], &from[Y], &from[Z]) != 0 && 192 | fgets(buffer, 127, setup) && 193 | sscanf(buffer, "%lf %lf %lf", 194 | &at[X], &at[Y], &at[Z]) != 0 && 195 | fgets(buffer, 127, setup) && 196 | sscanf(buffer, "%lf %lf %lf", 197 | &up[X], &up[Y], &up[Z]) != 0 && 198 | fgets(buffer, 127, setup) && 199 | sscanf(buffer, "%lf", &angle)) { 200 | lib_output_viewpoint(from, at, up, 45.0, 1.0, 1.0, 512, 512); 201 | } else { 202 | #if defined(applec) || defined(THINK_C) 203 | #else 204 | fprintf(stderr, "Invalid 'view.dat' file\n"); 205 | #endif 206 | exit(EXIT_FAIL); 207 | } 208 | fclose( setup ); 209 | } else { 210 | SET_COORD3(from, 0, 10, -10); 211 | SET_COORD3(at, 0, 0, 0); 212 | SET_COORD3(up, 0, 0, 1); 213 | lib_output_viewpoint(from, at, up, 45.0, 1.0, 1.0, 512, 512); 214 | } 215 | } 216 | 217 | /* Read in the camera view, then read in DXF polygons, then display them. */ 218 | int 219 | main(argc, argv) 220 | int argc; 221 | char *argv[]; 222 | { 223 | COORD3 back_color, dxf_color; 224 | COORD4 light; 225 | double lscale; 226 | char file_name[64] ; 227 | FILE *file; 228 | 229 | PLATFORM_INIT(SPD_READDXF); 230 | 231 | /* Start by defining which raytracer we will be using */ 232 | if ( lib_read_get_opts( argc, argv, 233 | &raytracer_format, &output_format, file_name ) ) { 234 | return EXIT_FAIL; 235 | } 236 | if ( lib_open( raytracer_format, "ReadDXF" ) ) { 237 | return EXIT_FAIL; 238 | } 239 | 240 | file = fopen(file_name, "r"); 241 | if (file == NULL) { 242 | fprintf(stderr, "Cannot open dxf file: '%s'\n", file_name); 243 | return EXIT_FAIL; 244 | } 245 | 246 | 247 | /* output background color - dark blue */ 248 | /* NOTE: Do this BEFORE lib_output_viewpoint(), for display_init() */ 249 | SET_COORD3(back_color, 0.1, 0.0, 0.5); 250 | lib_output_background_color(back_color); 251 | 252 | setup_view(); 253 | 254 | /* output object color - light gray */ 255 | SET_COORD3(dxf_color, 0.8, 0.8, 0.8); 256 | lib_output_color(NULL, dxf_color, 0.1, 0.8, 0.0, 0.2, 10.0, 0.0, 1.0); 257 | 258 | /* 259 | * For raytracers that don't scale the light intensity, 260 | * we will do it for them 261 | */ 262 | #define NUM_LIGHTS 2 263 | lscale = ( ((raytracer_format==OUTPUT_NFF) || (raytracer_format==OUTPUT_RTRACE)) 264 | ? 1.0 : 1.0 / sqrt(NUM_LIGHTS)); 265 | 266 | SET_COORD4(light, 40.0, 30.0, 20.0, lscale); 267 | lib_output_light(light); 268 | SET_COORD4(light, -40, -20, 10, lscale); 269 | lib_output_light(light); 270 | 271 | read_dxf_faces(file); 272 | 273 | fclose(file); 274 | 275 | lib_close(); 276 | 277 | PLATFORM_SHUTDOWN(); 278 | return EXIT_SUCCESS; 279 | } 280 | -------------------------------------------------------------------------------- /src/readnff.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ReadNFF.c - Simple NFF file importer. Uses lib to output to 3 | * many different raytracer formats. 4 | * 5 | * Author: Eduard [esp] Schwan 6 | * 7 | * input file parameter... 8 | */ 9 | 10 | #include 11 | #include 12 | #include /* strchr */ 13 | #include /* atoi */ 14 | #include "def.h" 15 | #include "drv.h" /* display_close() */ 16 | #include "lib.h" 17 | 18 | /* These may be read from the command line */ 19 | static int raytracer_format = OUTPUT_RT_DEFAULT; 20 | static int output_format = OUTPUT_CURVES; 21 | 22 | 23 | /*---------------------------------------------------------------------- 24 | Handle an error 25 | ----------------------------------------------------------------------*/ 26 | static void 27 | show_error(s) 28 | char * s; 29 | { 30 | /* SysBeep(1); */ 31 | lib_output_comment("### ERROR! ###\n"); 32 | lib_output_comment(s); 33 | lib_close(); 34 | } 35 | 36 | /*---------------------------------------------------------------------- 37 | Comment. Description: 38 | "#" [ string ] 39 | 40 | Format: 41 | # [ string ] 42 | 43 | As soon as a "#" character is detected, the rest of the line is considered 44 | a comment. 45 | ----------------------------------------------------------------------*/ 46 | static void 47 | do_comment(fp) 48 | FILE *fp; 49 | { 50 | char *cp; 51 | char comment[256]; 52 | 53 | fgets(comment, 255, fp); 54 | /* strip out newline */ 55 | cp = (char*)strchr(comment, '\n'); 56 | if (cp != NULL) 57 | *cp = '\0'; 58 | lib_output_comment(comment); 59 | } 60 | 61 | 62 | /*---------------------------------------------------------------------- 63 | Viewpoint location. Description: 64 | "v" 65 | "from" Fx Fy Fz 66 | "at" Ax Ay Az 67 | "up" Ux Uy Uz 68 | "angle" angle 69 | "hither" hither 70 | "resolution" xres yres 71 | 72 | Format: 73 | 74 | v 75 | from %g %g %g 76 | at %g %g %g 77 | up %g %g %g 78 | angle %g 79 | hither %g 80 | resolution %d %d 81 | 82 | The parameters are: 83 | 84 | From: the eye location in XYZ. 85 | At: a position to be at the center of the image, in XYZ world 86 | coordinates. A.k.a. "lookat". 87 | Up: a vector defining which direction is up, as an XYZ vector. 88 | Angle: in degrees, defined as from the center of top pixel row to 89 | bottom pixel row and left column to right column. 90 | Resolution: in pixels, in x and in y. 91 | 92 | Note that no assumptions are made about normalizing the data (e.g. the 93 | from-at distance does not have to be 1). Also, vectors are not 94 | required to be perpendicular to each other. 95 | 96 | For all databases some viewing parameters are always the same: 97 | Yon is "at infinity." 98 | Aspect ratio is 1.0. 99 | 100 | A view entity must be defined before any objects are defined (this 101 | requirement is so that NFF files can be used by hidden surface machines). 102 | ----------------------------------------------------------------------*/ 103 | static void 104 | do_view(fp) 105 | FILE *fp; 106 | { 107 | float x,y,z; 108 | COORD3 from; 109 | COORD3 at; 110 | COORD3 up; 111 | float fov_angle; 112 | float aspect_ratio; 113 | float hither; 114 | int resx; 115 | int resy; 116 | 117 | if (fscanf(fp, " from %f %f %f", &x, &y, &z) != 3) 118 | goto fmterr; 119 | SET_COORD3(from, x,y,z); 120 | 121 | if (fscanf(fp, " at %f %f %f", &x, &y, &z) != 3) 122 | goto fmterr; 123 | SET_COORD3(at, x,y,z); 124 | 125 | if (fscanf(fp, " up %f %f %f", &x, &y, &z) != 3) 126 | goto fmterr; 127 | SET_COORD3(up, x,y,z); 128 | 129 | if (fscanf(fp, " angle %f", &fov_angle) != 1) 130 | goto fmterr; 131 | 132 | fscanf(fp, " hither %f", &hither); 133 | 134 | aspect_ratio = (float)1.0; 135 | 136 | fscanf(fp, " resolution %d %d", &resx, &resy); 137 | 138 | lib_output_viewpoint(from, at, up, 139 | fov_angle, aspect_ratio, 140 | hither, resx, resy); 141 | return; 142 | fmterr: 143 | show_error("NFF view syntax error"); 144 | exit(1); 145 | } 146 | 147 | 148 | /*---------------------------------------------------------------------- 149 | Positional light. A light is defined by XYZ position. Description: 150 | "l" X Y Z 151 | 152 | Format: 153 | l %g %g %g 154 | 155 | All light entities must be defined before any objects are defined (this 156 | requirement is so that NFF files can be used by hidden surface machines). 157 | Lights have a non-zero intensity of no particular value [this definition 158 | may change soon, with the addition of an intensity and/or color]. 159 | ----------------------------------------------------------------------*/ 160 | static void 161 | do_light(fp) 162 | FILE *fp; 163 | { 164 | float x, y, z; 165 | COORD4 acenter; 166 | 167 | if (fscanf(fp, "%f %f %f",&x, &y, &z) != 3) { 168 | show_error("Light source syntax error"); 169 | exit(1); 170 | } 171 | 172 | SET_COORD4(acenter,x,y,z,0.0); /* intensity=0 */ 173 | 174 | lib_output_light(acenter); 175 | } 176 | 177 | 178 | /*---------------------------------------------------------------------- 179 | Background color. A color is simply RGB with values between 0 and 1: 180 | "b" R G B 181 | 182 | Format: 183 | b %g %g %g 184 | 185 | If no background color is set, assume RGB = {0,0,0}. 186 | ----------------------------------------------------------------------*/ 187 | static void 188 | do_background(fp) 189 | FILE *fp; 190 | { 191 | float r, g, b; 192 | COORD3 acolor; 193 | 194 | if (fscanf(fp, "%f %f %f",&r, &g, &b) != 3) { 195 | show_error("background color syntax error"); 196 | exit(1); 197 | } 198 | SET_COORD3(acolor,r,g,b); 199 | 200 | lib_output_background_color(acolor); 201 | } 202 | 203 | 204 | /*---------------------------------------------------------------------- 205 | Fill color and shading parameters. Description: 206 | "f" red green blue Kd Ks Shine T index_of_refraction 207 | 208 | Format: 209 | f %g %g %g %g %g %g %g %g 210 | 211 | RGB is in terms of 0.0 to 1.0. 212 | 213 | Kd is the diffuse component, Ks the specular, Shine is the Phong cosine 214 | power for highlights, T is transmittance (fraction of light passed per 215 | unit). Usually, 0 <= Kd <= 1 and 0 <= Ks <= 1, though it is not required 216 | that Kd + Ks == 1. Note that transmitting objects ( T > 0 ) are considered 217 | to have two sides for algorithms that need these (normally objects have 218 | one side). 219 | 220 | The fill color is used to color the objects following it until a new color 221 | is assigned. 222 | ----------------------------------------------------------------------*/ 223 | static void 224 | do_fill(fp) 225 | FILE *fp; 226 | { 227 | float r, g, b, ka, kd, ks, ks_spec, phong_pow, ang, t, ior; 228 | COORD3 acolor; 229 | 230 | if (fscanf(fp, "%f %f %f",&r, &g, &b) != 3) { 231 | show_error("fill color syntax error"); 232 | exit(1); 233 | } 234 | SET_COORD3(acolor,r,g,b); 235 | 236 | if (fscanf(fp, "%f %f %f %f %f", &kd, &ks, &phong_pow, &t, &ior) != 5) { 237 | show_error("fill material syntax error"); 238 | exit(1); 239 | } 240 | 241 | /* some parms not input in NFF, so hard-coded. */ 242 | ka = (float)0.1; 243 | ks_spec = ks; 244 | /* convert phong_pow back into phong hilight angle. */ 245 | /* reciprocal of formula in libpr1.c, lib_output_color() */ 246 | if ( phong_pow < 1.0 ) 247 | phong_pow = 1.0 ; 248 | ang = (float)((180.0/PI) * acos( exp(log(0.5)/phong_pow) )); 249 | lib_output_color(NULL, acolor, ka, kd, ks, ks_spec, ang, t, ior); 250 | 251 | } 252 | 253 | 254 | /*---------------------------------------------------------------------- 255 | Cylinder or cone. A cylinder is defined as having a radius and an axis 256 | defined by two points, which also define the top and bottom edge of the 257 | cylinder. A cone is defined similarly, the difference being that the apex 258 | and base radii are different. The apex radius is defined as being smaller 259 | than the base radius. Note that the surface exists without endcaps. The 260 | cone or cylinder description: 261 | 262 | "c" 263 | base.x base.y base.z base_radius 264 | apex.x apex.y apex.z apex_radius 265 | 266 | Format: 267 | c 268 | %g %g %g %g 269 | %g %g %g %g 270 | 271 | A negative value for both radii means that only the inside of the object is 272 | visible (objects are normally considered one sided, with the outside 273 | visible). Note that the base and apex cannot be coincident for a cylinder 274 | or cone. 275 | ----------------------------------------------------------------------*/ 276 | static void 277 | do_cone(fp) 278 | FILE *fp; 279 | { 280 | COORD4 base_pt; 281 | COORD4 apex_pt; 282 | float x0, y0, z0, x1, y1, z1, r0, r1; 283 | 284 | if (fscanf(fp, " %f %f %f %f %f %f %f %f", &x0, &y0, &z0, &r0, 285 | &x1, &y1, &z1, &r1) != 8) { 286 | show_error("cylinder or cone syntax error"); 287 | exit(1); 288 | } 289 | if ( r0 < 0.0) { 290 | r0 = -r0; 291 | r1 = -r1; 292 | } 293 | SET_COORD4(base_pt,x0,y0,z0,r0); 294 | SET_COORD4(apex_pt,x1,y1,z1,r1); 295 | 296 | lib_output_cylcone (base_pt, apex_pt, output_format); 297 | } 298 | 299 | 300 | /*---------------------------------------------------------------------- 301 | Sphere. A sphere is defined by a radius and center position: 302 | "s" center.x center.y center.z radius 303 | 304 | Format: 305 | s %g %g %g %g 306 | 307 | If the radius is negative, then only the sphere's inside is visible 308 | (objects are normally considered one sided, with the outside visible). 309 | ----------------------------------------------------------------------*/ 310 | static void 311 | do_sphere(fp) 312 | FILE *fp; 313 | { 314 | float x, y, z, r; 315 | COORD4 center_pt; 316 | 317 | if (fscanf(fp, "%f %f %f %f", &x, &y, &z, &r) != 4) { 318 | show_error("sphere syntax error"); 319 | exit(1); 320 | } 321 | 322 | SET_COORD4(center_pt,x,y,z,r); 323 | 324 | lib_output_sphere(center_pt, output_format); 325 | } 326 | 327 | 328 | /*---------------------------------------------------------------------- 329 | Polygon. A polygon is defined by a set of vertices. With these databases, 330 | a polygon is defined to have all points coplanar. A polygon has only 331 | one side, with the order of the vertices being counterclockwise as you 332 | face the polygon (right-handed coordinate system). The first two edges 333 | must form a non-zero convex angle, so that the normal and side visibility 334 | can be determined. Description: 335 | 336 | "p" total_vertices 337 | vert1.x vert1.y vert1.z 338 | [etc. for total_vertices vertices] 339 | 340 | Format: 341 | p %d 342 | [ %g %g %g ] <-- for total_vertices vertices 343 | ---------------------------------------------------------------------- 344 | Polygonal patch. A patch is defined by a set of vertices and their normals. 345 | With these databases, a patch is defined to have all points coplanar. 346 | A patch has only one side, with the order of the vertices being 347 | counterclockwise as you face the patch (right-handed coordinate system). 348 | The first two edges must form a non-zero convex angle, so that the normal 349 | and side visibility can be determined. Description: 350 | 351 | "pp" total_vertices 352 | vert1.x vert1.y vert1.z norm1.x norm1.y norm1.z 353 | [etc. for total_vertices vertices] 354 | 355 | Format: 356 | pp %d 357 | [ %g %g %g %g %g %g ] <-- for total_vertices vertices 358 | ----------------------------------------------------------------------*/ 359 | static void 360 | do_poly(fp) 361 | FILE *fp; 362 | { 363 | int ispatch; 364 | int nverts; 365 | int vertcount; 366 | COORD3 *verts; 367 | COORD3 *norms; 368 | float x, y, z; 369 | 370 | ispatch = getc(fp); 371 | if (ispatch != 'p') { 372 | ungetc(ispatch, fp); 373 | ispatch = 0; 374 | } 375 | 376 | if (fscanf(fp, "%d", &nverts) != 1) 377 | goto fmterr; 378 | 379 | verts = (COORD3*)malloc(nverts*sizeof(COORD3)); 380 | if (verts == NULL) 381 | goto memerr; 382 | 383 | if (ispatch) { 384 | norms = (COORD3*)malloc(nverts*sizeof(COORD3)); 385 | if (norms == NULL) 386 | goto memerr; 387 | } 388 | 389 | /* read all the vertices into temp array */ 390 | for (vertcount = 0; vertcount < nverts; vertcount++) { 391 | if (fscanf(fp, " %f %f %f", &x, &y, &z) != 3) 392 | goto fmterr; 393 | SET_COORD3(verts[vertcount],x,y,z); 394 | 395 | if (ispatch) { 396 | if (fscanf(fp, " %f %f %f", &x, &y, &z) != 3) 397 | goto fmterr; 398 | SET_COORD3(norms[vertcount],x,y,z); 399 | } 400 | } 401 | 402 | /* write output */ 403 | if (ispatch) 404 | lib_output_polypatch(nverts, verts, norms); 405 | else 406 | lib_output_polygon(nverts, verts); 407 | 408 | free(verts); 409 | if (ispatch) 410 | free(norms); 411 | 412 | return; 413 | fmterr: 414 | show_error("polygon or patch syntax error"); 415 | exit(1); 416 | memerr: 417 | show_error("can't allocate memory for polygon or patch"); 418 | exit(1); 419 | } 420 | 421 | 422 | /*---------------------------------------------------------------------- 423 | ----------------------------------------------------------------------*/ 424 | static void 425 | parse_nff(fp) 426 | FILE *fp; 427 | { 428 | int c; 429 | 430 | while ( (c = getc(fp)) != EOF ) 431 | switch (c) { 432 | case ' ': /* white space */ 433 | case '\t': 434 | case '\n': 435 | case '\f': 436 | case '\r': 437 | continue; 438 | case '#': /* comment */ 439 | do_comment(fp); 440 | break; 441 | case 'v': /* view point */ 442 | do_view(fp); 443 | break; 444 | case 'l': /* light source */ 445 | do_light(fp); 446 | break; 447 | case 'b': /* background color */ 448 | do_background(fp); 449 | break; 450 | case 'f': /* fill material */ 451 | do_fill(fp); 452 | break; 453 | case 'c': /* cylinder or cone */ 454 | do_cone(fp); 455 | break; 456 | case 's': /* sphere */ 457 | do_sphere(fp); 458 | break; 459 | case 'p': /* polygon or patch */ 460 | do_poly(fp); 461 | break; 462 | default: /* unknown */ 463 | show_error("unknown NFF primitive code"); 464 | exit(1); 465 | } 466 | } /* parse_nff */ 467 | 468 | 469 | /*---------------------------------------------------------------------- 470 | ----------------------------------------------------------------------*/ 471 | int 472 | main(argc,argv) 473 | int argc ; 474 | char *argv[] ; 475 | { 476 | char file_name[256]; 477 | FILE *fp; 478 | 479 | PLATFORM_INIT(SPD_READNFF); 480 | 481 | /* Start by defining which raytracer we will be using */ 482 | if ( lib_read_get_opts( argc, argv, 483 | &raytracer_format, &output_format, file_name ) ) { 484 | return EXIT_FAIL; 485 | } 486 | 487 | if ( lib_open( raytracer_format, "ReadNFF" ) ) { 488 | return EXIT_FAIL; 489 | } 490 | 491 | fp = fopen(file_name, "r"); 492 | if (fp == NULL) { 493 | fprintf(stderr, "Cannot open nff file: '%s'\n", file_name); 494 | return EXIT_FAIL; 495 | } 496 | 497 | /*lib_set_polygonalization(3, 3);*/ 498 | 499 | parse_nff(fp); 500 | 501 | fclose(fp); 502 | 503 | lib_close(); 504 | 505 | PLATFORM_SHUTDOWN(); 506 | return EXIT_SUCCESS; 507 | } 508 | -------------------------------------------------------------------------------- /src/readobj.c: -------------------------------------------------------------------------------- 1 | /* 2 | * readobj.c - Read polygons from a Wavefront OBJ file and display them. 3 | * The file "view.dat" is processed for the camera view that will be used. 4 | * 5 | * Author: Alexander Enzmann 6 | * 7 | * size_factor is ignored. 8 | * 9 | * This code was extracted from the Polyray raytracer. Currently it will only 10 | * read polygons, with or without associated vertex normals. The u/v 11 | * coordinates are read, but not used in this code. Groups (including smoothing 12 | * groups) are ignored. All of the spline patch types are ignored. 13 | * 14 | */ 15 | 16 | #include 17 | #include 18 | #include /* atoi */ 19 | #include /* strcmp() */ 20 | #include "def.h" 21 | #include "drv.h" /* display_close() */ 22 | #include "lib.h" 23 | 24 | 25 | /* These may be read from the command line */ 26 | static int raytracer_format = OUTPUT_RT_DEFAULT; 27 | static int output_format = OUTPUT_CURVES; 28 | 29 | 30 | #ifdef OUTPUT_TO_FILE 31 | static FILE * stdout_file = NULL; 32 | #else 33 | #define stdout_file stdout 34 | #endif /* OUTPUT_TO_FILE */ 35 | 36 | #define MAXTRILINE 512 37 | 38 | /* Data structure for a stack of vertices */ 39 | typedef struct VecVerts_struct VecVerts; 40 | struct VecVerts_struct { 41 | float V[4]; 42 | VecVerts *next; 43 | }; 44 | 45 | /* Data structure for a stack of faces */ 46 | typedef struct Face_struct Faces; 47 | struct Face_struct { 48 | int vcount; 49 | long *verts, *tverts, *nverts; 50 | /* Texture *texture; */ 51 | Faces *next; 52 | }; 53 | 54 | typedef struct triverts_struct triverts; 55 | struct triverts_struct { 56 | COORD3 V[3], N[3], U[3]; 57 | /* Texture *texture; */ 58 | triverts *next; 59 | }; 60 | 61 | /* Stack of raw triangle collections. Each collection is associated 62 | with a single texture name. (currently unused) */ 63 | typedef struct trivertstack_struct trivstack; 64 | struct trivertstack_struct { 65 | /* Texture *texture; */ /* Texture to apply to all triangles */ 66 | triverts *verts; /* List of triangles */ 67 | Faces *fstack; /* Stack of face indices */ 68 | long tcount; /* Number of triangles in this raw object */ 69 | int nflag; /* Are there vertex normals? */ 70 | int uvflag; /* Is there u/v information for the vertices? */ 71 | trivstack *next; /* Next bag of triangles */ 72 | }; 73 | 74 | /* Structure to hold a smoothing group */ 75 | typedef struct SmoothGroup_struct SmoothGroup; 76 | struct SmoothGroup_struct { 77 | unsigned group_num; 78 | Faces *faces; 79 | SmoothGroup *next; 80 | }; 81 | 82 | #define BETWEEN_OBJECTS 0 83 | #define READING_VERTICES 1 84 | #define READING_FACES 2 85 | 86 | #define MAX_VERTICES_PER_FACE 32 87 | 88 | static long vertex_count = 0; 89 | static long vertex_texture_count = 0; 90 | static long vertex_normal_count = 0; 91 | static long face_count = 0; 92 | /* static Texture *current_texture; */ 93 | 94 | static char rbuf[MAXTRILINE]; 95 | static int rbuf_offset = 0; 96 | static int rbuf_length = 0; 97 | 98 | static int 99 | skip_white_space(filep) 100 | FILE *filep; 101 | { 102 | for (; 103 | (rbuf[rbuf_offset] == ' ' || 104 | rbuf[rbuf_offset] == '\t' || 105 | rbuf[rbuf_offset] == '\\') && 106 | rbuf_offset < rbuf_length; 107 | rbuf_offset++) { 108 | 109 | if (rbuf[rbuf_offset] == '\\') { 110 | /* Continuation character, get the next line */ 111 | if (fgets(rbuf, MAXTRILINE, filep) != NULL) { 112 | rbuf_offset = 0; 113 | rbuf_length = strlen(rbuf); 114 | } 115 | else { 116 | rbuf[0] = '\0'; 117 | rbuf_offset = 0; 118 | rbuf_length = 0; 119 | return 0; 120 | } 121 | } 122 | else { 123 | /* White space, just ignore it */ 124 | } 125 | } 126 | return 1; 127 | } 128 | 129 | static void 130 | skip_till_white_space(filep) 131 | FILE *filep; 132 | { 133 | for (; 134 | rbuf[rbuf_offset] != ' ' && 135 | rbuf[rbuf_offset] != '\t' && 136 | rbuf_offset < rbuf_length; 137 | rbuf_offset++) 138 | ; 139 | } 140 | 141 | static int 142 | end_of_line() 143 | { 144 | if (rbuf_offset == rbuf_length || 145 | rbuf[rbuf_offset] == '\n' || 146 | rbuf[rbuf_offset] == '\0') 147 | return 1; 148 | else 149 | return 0; 150 | } 151 | 152 | static int 153 | read_vertex(filep, v, vt, vn) 154 | FILE *filep; 155 | long *v, *vt, *vn; 156 | { 157 | float v0, vt0, vn0; 158 | 159 | skip_white_space(filep); 160 | if (sscanf(&rbuf[rbuf_offset], "%g/%g/%g", &v0, &vt0, &vn0) == 3) { 161 | *v = (long)v0; 162 | *vt = (long)vt0; 163 | *vn = (long)vn0; 164 | } 165 | else if (sscanf(&rbuf[rbuf_offset], "%g//%g", &v0, &vn0) == 2) { 166 | *v = (long)v0; 167 | *vt = (long)0L; 168 | *vn = (long)vn0; 169 | } 170 | else if (sscanf(&rbuf[rbuf_offset], "%g/%g", &v0, &vt0) == 2) { 171 | *v = (long)v0; 172 | *vt = (long)vt0; 173 | *vn = (long)0L; 174 | } 175 | else if (sscanf(&rbuf[rbuf_offset], "%g", &v0) == 1) { 176 | *v = (long)v0; 177 | *vt = 0L; 178 | *vn = 0L; 179 | } 180 | else { 181 | fprintf(stderr, "Bad vertex data\n"); 182 | exit(1); 183 | } 184 | skip_till_white_space(filep); 185 | return 1; 186 | } 187 | 188 | static Faces * 189 | read_face(filep) 190 | FILE *filep; 191 | { 192 | Faces *face; 193 | int i, vcount, vtp_flag, vnp_flag; 194 | long v[MAX_VERTICES_PER_FACE], *vp; 195 | long vt[MAX_VERTICES_PER_FACE], *vtp; 196 | long vn[MAX_VERTICES_PER_FACE], *vnp; 197 | 198 | vp = &v[0]; 199 | vtp = &vt[0]; 200 | vnp = &vn[0]; 201 | vtp_flag = 0; 202 | vnp_flag = 0; 203 | for (vcount=0; 204 | vcount= MAX_VERTICES_PER_FACE) 214 | fprintf(stderr, "Too many vertices in a face"); 215 | 216 | face = malloc(sizeof(Faces)); 217 | face->verts = malloc(vcount * sizeof(long)); 218 | if (vtp_flag) 219 | face->tverts = malloc(vcount * sizeof(long)); 220 | else 221 | face->tverts = NULL; 222 | if (vnp_flag) 223 | face->nverts = malloc(vcount * sizeof(long)); 224 | else 225 | face->nverts = NULL; 226 | face->vcount = vcount; 227 | for (i=0;i 0) 229 | face->verts[i] = v[i] - 1; 230 | else 231 | face->verts[i] = vertex_count - vt[i]; 232 | if (vtp_flag) { 233 | if (vt[i] > 0) 234 | face->tverts[i] = vt[i] - 1; 235 | else 236 | face->tverts[i] = vertex_texture_count - vt[i]; 237 | } 238 | if (vnp_flag) { 239 | if (vn[i] > 0) 240 | face->nverts[i] = vn[i] - 1; 241 | else 242 | face->nverts[i] = vertex_normal_count - vn[i]; 243 | } 244 | } 245 | face->next = NULL; 246 | return face; 247 | } 248 | 249 | static void 250 | make_triangles(vcount, normal_count, fstack, 251 | vstack, nstack) 252 | long vcount, normal_count; 253 | Faces *fstack; 254 | VecVerts *vstack, *nstack; 255 | { 256 | COORD3 *V, *N; 257 | long tcnt; 258 | VecVerts *vtemp; 259 | Faces *ftemp1, *ftemp2; 260 | 261 | /* Now we need to allocate space for the vertices and process 262 | the face stacks into a set of triangles */ 263 | V = (COORD3 *)malloc(vcount * sizeof(COORD3)); 264 | if (normal_count > 0) 265 | N = (COORD3 *)malloc(normal_count * sizeof(COORD3)); 266 | else 267 | N = NULL; 268 | 269 | /* Copy the vertices into the V array */ 270 | for (tcnt=vcount-1;vstack!=NULL&&tcnt>=0;tcnt--) { 271 | /* Copy this vertex into the array */ 272 | COPY_COORD3(V[tcnt], vstack->V); 273 | /* Free up the space used for this vertex */ 274 | vtemp = vstack; 275 | vstack = vstack->next; 276 | free(vtemp); 277 | } 278 | if (tcnt != -1 || vstack != NULL) { 279 | fprintf(stderr, "Didn't properly process .obj vertices"); 280 | exit(1); 281 | } 282 | 283 | /* Copy the normals into the N array */ 284 | for (tcnt=normal_count-1;nstack!=NULL&&tcnt>=0;tcnt--) { 285 | /* Copy this vertex into the array */ 286 | COPY_COORD3(N[tcnt], nstack->V); 287 | /* Free up the space used for this vertex */ 288 | vtemp = nstack; 289 | nstack = nstack->next; 290 | free(vtemp); 291 | } 292 | if (tcnt != -1 || nstack != NULL) { 293 | fprintf(stderr, "Didn't properly process .obj normals"); 294 | exit(1); 295 | } 296 | 297 | /* Create triangles in the form we want them */ 298 | for (ftemp1=fstack,tcnt=0;ftemp1!=NULL;tcnt++) { 299 | /* We need to turn the face into a set of triangles and 300 | stuff each one onto the stack */ 301 | COORD3 *verts, *norms; 302 | int j, npoints; 303 | 304 | /* Allocate temporary space to hold the polygon (yes, 305 | I know this loop thrashes malloc(), but that's 306 | just tough. */ 307 | npoints = ftemp1->vcount; 308 | verts = (COORD3 *)malloc(npoints * sizeof(COORD3)); 309 | if (ftemp1->nverts != NULL) 310 | norms = (COORD3 *)malloc(npoints * sizeof(COORD3)); 311 | else 312 | norms = NULL; 313 | 314 | /* Stuff the vertices of the polygon into the array 315 | verts for subsequent chopping. */ 316 | for (j=0;jverts[j]]); 318 | if (norms != NULL) 319 | COPY_COORD3(norms[j], N[ftemp1->nverts[j]]); 320 | } 321 | if (norms != NULL) 322 | lib_output_polypatch(npoints, verts, norms); 323 | else 324 | lib_output_polygon(npoints, verts); 325 | 326 | /* Free the temporary polygon storage */ 327 | free(verts); 328 | if (norms != NULL) free(norms); 329 | 330 | /* Dispose of the ones we just looked at */ 331 | ftemp2 = ftemp1; 332 | ftemp1 = ftemp1->next; 333 | free(ftemp2->verts); 334 | if (ftemp2->tverts) free(ftemp2->tverts); 335 | if (ftemp2->nverts) free(ftemp2->nverts); 336 | free(ftemp2); 337 | } 338 | } 339 | 340 | static VecVerts * 341 | new_vecvert(x, y, z, w) 342 | float x, y, z, w; 343 | { 344 | VecVerts *vert; 345 | vert = malloc(sizeof(VecVerts)); 346 | vert->V[0] = (float)x; 347 | vert->V[1] = (float)y; 348 | vert->V[2] = (float)z; 349 | vert->V[3] = (float)w; 350 | vert->next = NULL; 351 | return vert; 352 | } 353 | 354 | static int 355 | read_obj_faces(filep) 356 | FILE *filep; 357 | { 358 | char ctype[MAXTRILINE], tbuf1[MAXTRILINE], tbuf2[MAXTRILINE]; 359 | float v0, v1, v2, v3; 360 | int icnt; 361 | VecVerts *vstack, *nstack, *vtemp; 362 | Faces *fstack, *ftemp1; 363 | 364 | fseek(filep, 0, SEEK_SET); 365 | 366 | vstack = NULL; 367 | nstack = NULL; 368 | fstack = NULL; 369 | vertex_count = 0; 370 | vertex_texture_count = 0; 371 | vertex_normal_count = 0; 372 | face_count = 0; 373 | 374 | /* Read the entire file, processing triangles as we go. */ 375 | while(TRUE){ 376 | if (fgets(rbuf, MAXTRILINE, filep) == NULL) 377 | break; 378 | /* First read in the command for this line */ 379 | icnt = sscanf(rbuf, "%s", ctype); 380 | rbuf_offset = strlen(ctype); 381 | rbuf_length = strlen(rbuf); 382 | 383 | /* Looking for a statement like: "v x y z w" */ 384 | if (!strcmp(ctype, "v")) { 385 | /* Read a vertex */ 386 | icnt = sscanf(rbuf, "%s %g %g %g %g", tbuf1, &v0, &v1, &v2, &v3); 387 | if (icnt == 4 || icnt == 5) { 388 | /* Valid vertex */ 389 | vtemp = new_vecvert(v0, v1, v2, (icnt == 4 ? 0.0 : v3)); 390 | vtemp->next = vstack; 391 | vstack = vtemp; 392 | vertex_count++; 393 | } 394 | else 395 | fprintf(stderr, "Bad vertex\n"); 396 | continue; 397 | } 398 | 399 | /* Looking for a statement like: "vn x y z" */ 400 | if (!strcmp(ctype, "vn")) { 401 | /* Read a vertex */ 402 | icnt = sscanf(rbuf, "%s %g %g %g", tbuf1, &v0, &v1, &v2); 403 | if (icnt == 4) { 404 | /* Valid vertex */ 405 | vtemp = new_vecvert(v0, v1, v2, 0.0 ); 406 | vtemp->next = nstack; 407 | nstack = vtemp; 408 | vertex_normal_count++; 409 | } 410 | else 411 | fprintf(stderr, "Bad normal\n"); 412 | continue; 413 | } 414 | 415 | /* Looking for a statement like: "vt u v w" */ 416 | if (!strcmp(ctype, "vt")) { 417 | /* Read a vertex */ 418 | icnt = sscanf(rbuf, "%s %g %g %g", tbuf1, &v0, &v1, &v2); 419 | /* For now we are ignoring texture coordinates */ 420 | continue; 421 | } 422 | 423 | /* Look for: "usemtl texture_name" */ 424 | if (!strcmp(ctype, "usemtl")) { 425 | icnt = sscanf(rbuf, "%s %s", tbuf1, tbuf2); 426 | if (icnt == 2) { 427 | /* Got a texture name, do nothing for now */ 428 | } 429 | else 430 | fprintf(stderr, "Bad texture (usemtl) name\n"); 431 | continue; 432 | } 433 | 434 | if (!strcmp(ctype, "f")) { 435 | /* Read a face */ 436 | ftemp1 = read_face(filep); 437 | if (ftemp1 != NULL) { 438 | /* ftemp1->texture = current_texture; */ 439 | ftemp1->next = fstack; 440 | fstack = ftemp1; 441 | face_count++; 442 | } 443 | else 444 | fprintf(stderr, "Bad face\n"); 445 | continue; 446 | } 447 | } 448 | 449 | /* Turn the contents of the face stack into triangle objects. This 450 | routine removes the memory associated with tristack. */ 451 | make_triangles(vertex_count, vertex_normal_count, 452 | fstack, vstack, nstack); 453 | 454 | return face_count; 455 | } 456 | 457 | /* Read in the camera specifics: from, at, up, fov. Aspect is hard coded 458 | to 1. */ 459 | static void 460 | setup_view() 461 | { 462 | char buffer[128]; 463 | COORD3 from, at, up; 464 | double angle; 465 | FILE *setup; 466 | 467 | /* output viewpoint */ 468 | if ((setup = fopen("view.dat", "r")) != NULL) { 469 | if (fgets(buffer, 127, setup) && 470 | sscanf(buffer, "%lf %lf %lf", 471 | &from[X], &from[Y], &from[Z]) != 0 && 472 | fgets(buffer, 127, setup) && 473 | sscanf(buffer, "%lf %lf %lf", 474 | &at[X], &at[Y], &at[Z]) != 0 && 475 | fgets(buffer, 127, setup) && 476 | sscanf(buffer, "%lf %lf %lf", 477 | &up[X], &up[Y], &up[Z]) != 0 && 478 | fgets(buffer, 127, setup) && 479 | sscanf(buffer, "%lf", &angle)) { 480 | lib_output_viewpoint(from, at, up, 45.0, 1.0, 1.0, 512, 512); 481 | } else { 482 | #if defined(applec) || defined(THINK_C) 483 | #else 484 | fprintf(stderr, "Invalid 'view.dat' file\n"); 485 | #endif 486 | exit(EXIT_FAIL); 487 | } 488 | fclose( setup ); 489 | } else { 490 | SET_COORD3(from, 0, 10, -10); 491 | SET_COORD3(at, 0, 0, 0); 492 | SET_COORD3(up, 0, 0, 1); 493 | lib_output_viewpoint(from, at, up, 45.0, 1.0, 1.0, 512, 512); 494 | } 495 | } 496 | 497 | /* Read in the camera view, then read in OBJ polygons, then display them. */ 498 | int 499 | main(argc, argv) 500 | int argc; 501 | char *argv[]; 502 | { 503 | COORD3 back_color, dxf_color; 504 | COORD4 light; 505 | double lscale; 506 | char file_name[64] ; 507 | FILE *file; 508 | 509 | PLATFORM_INIT(SPD_READOBJ); 510 | 511 | /* Start by defining which raytracer we will be using */ 512 | if ( lib_read_get_opts( argc, argv, 513 | &raytracer_format, &output_format, file_name ) ) { 514 | return EXIT_FAIL; 515 | } 516 | if ( lib_open( raytracer_format, "ReadOBJ" ) ) { 517 | return EXIT_FAIL; 518 | } 519 | 520 | file = fopen(file_name, "r"); 521 | if (file == NULL) { 522 | fprintf(stderr, "Cannot open obj file: '%s'\n", file_name); 523 | return EXIT_FAIL; 524 | } 525 | 526 | /*lib_set_polygonalization(3, 3);*/ 527 | 528 | /* output background color - dark blue */ 529 | /* NOTE: Do this BEFORE lib_output_viewpoint(), for display_init() */ 530 | SET_COORD3(back_color, 0.1, 0.0, 0.5); 531 | lib_output_background_color(back_color); 532 | 533 | setup_view(); 534 | 535 | /* output object color - light gray */ 536 | SET_COORD3(dxf_color, 0.8, 0.8, 0.8); 537 | lib_output_color(NULL, dxf_color, 0.1, 0.8, 0.0, 0.2, 10.0, 0.0, 1.0); 538 | 539 | /* 540 | * For raytracers that don't scale the light intensity, 541 | * we will do it for them 542 | */ 543 | #define NUM_LIGHTS 2 544 | lscale = ( ((raytracer_format==OUTPUT_NFF) || (raytracer_format==OUTPUT_RTRACE)) 545 | ? 1.0 : 1.0 / sqrt(NUM_LIGHTS)); 546 | 547 | SET_COORD4(light, 40.0, 30.0, 20.0, lscale); 548 | lib_output_light(light); 549 | SET_COORD4(light, -40, -20, 10, lscale); 550 | lib_output_light(light); 551 | 552 | read_obj_faces(file); 553 | 554 | fclose(file); 555 | 556 | lib_close(); 557 | 558 | PLATFORM_SHUTDOWN(); 559 | return EXIT_SUCCESS; 560 | } 561 | -------------------------------------------------------------------------------- /src/rings.c: -------------------------------------------------------------------------------- 1 | /* 2 | * rings.c - Create objects with 6 pentagonal rings which connect the midpoints 3 | * of the edges of a dodecahedron. A pyramid of these objects is formed, 4 | * which the viewer looks upon from the point. A plane is placed behind 5 | * the pyramid for shadows. Three light sources. 6 | * 7 | * Author: Eric Haines 8 | * 9 | * size_factor determines the number of objects output. 10 | * Each object has 30 cylinders and 30 spheres. 11 | * Total objects = SF*SF + (SF-1)*(SF-1) + ... + 1 plus 1 backdrop square. 12 | * formula for # of spheres or cylinders = 5*SF*(SF+1)*(2*SF+1) 13 | * 14 | * size_factor # spheres # cylinders # squares 15 | * 1 30 30 1 16 | * 2 150 150 1 17 | * 3 420 420 1 18 | * 19 | * 7 4200 4200 1 20 | */ 21 | 22 | #include 23 | #include 24 | #include /* atoi */ 25 | #include "def.h" 26 | #include "drv.h" /* display_close() */ 27 | #include "lib.h" 28 | 29 | static int size_factor = 7 ; 30 | static int raytracer_format = OUTPUT_RT_DEFAULT; 31 | static int output_format = OUTPUT_CURVES; 32 | 33 | #ifdef OUTPUT_TO_FILE 34 | static FILE * stdout_file = NULL; 35 | #else 36 | #define stdout_file stdout 37 | #endif /* OUTPUT_TO_FILE */ 38 | 39 | /* if spread out is > 1, succeeding layers spread out more */ 40 | #define SPREAD_OUT 1 41 | 42 | /* Create the set of 30 points needed to generate the rings */ 43 | static void 44 | create_dodec( minor_radius, vertex ) 45 | double minor_radius ; 46 | COORD3 vertex[30] ; 47 | { 48 | int num_vertex, num_pentagon ; 49 | double scale, x_rotation, z_rotation ; 50 | COORD3 temp_vertex ; 51 | MATRIX x_matrix, z_matrix ; 52 | 53 | /* scale object to fit in a sphere of radius 1 */ 54 | scale = 1.0 / ( 1.0 + minor_radius ) ; 55 | 56 | /* 57 | * define one pentagon as on the XY plane, with points starting along +X 58 | * and N fifths of the way around the Z axis. 59 | */ 60 | for ( num_vertex = 0 ; num_vertex < 5 ; ++num_vertex ) { 61 | vertex[num_vertex][X] = scale * cos((double)num_vertex * 2.0*PI/5.0 ) ; 62 | vertex[num_vertex][Y] = scale * sin((double)num_vertex * 2.0*PI/5.0 ) ; 63 | vertex[num_vertex][Z] = 0.0 ; 64 | vertex[num_vertex][W] = 1.0 ; 65 | } 66 | 67 | /* 68 | * find the rotation angle (in radians) along the X axis: 69 | * angle between two adjacent dodecahedron faces. 70 | */ 71 | x_rotation = 2.0 * 72 | acos( cos( (double)(PI/3.0) ) / sin( (double)(PI/5.0) ) ) ; 73 | lib_create_rotate_matrix( x_matrix, X_AXIS, x_rotation ) ; 74 | 75 | /* 76 | * Find each of the other 5 pentagons: rotate along the X axis, 77 | * then rotate on the Z axis. 78 | */ 79 | for ( num_pentagon = 1 ; num_pentagon < 6 ; ++num_pentagon ) { 80 | /* 81 | * find the rotation angle (in radians) along the Z axis: 82 | * 1/10th plus N fifths of the way around * 2 * PI. 83 | */ 84 | z_rotation = PI*( 2.0*(double)(num_pentagon-1)+1.0 ) / 5.0 ; 85 | lib_create_rotate_matrix( z_matrix, Z_AXIS, z_rotation ) ; 86 | 87 | for ( num_vertex = 0 ; num_vertex < 5 ; ++num_vertex ) { 88 | 89 | lib_transform_point( temp_vertex 90 | , vertex[num_vertex] 91 | , x_matrix 92 | ) ; 93 | 94 | lib_transform_point( vertex[5*num_pentagon+num_vertex] 95 | , temp_vertex 96 | , z_matrix 97 | ) ; 98 | } 99 | } 100 | } 101 | 102 | int 103 | main(argc,argv) 104 | int argc; 105 | char *argv[]; 106 | { 107 | int prev_elem, num_elem, num_depth, num_objx, num_objz ; 108 | double radius, spread, y_diff, xz_diff ; 109 | COORD4 base_pt, apex_pt, light ; 110 | COORD3 from, at, up ; 111 | COORD3 wvec ; 112 | COORD3 back_color, ring_color[6] ; 113 | COORD3 wall[4], offset, dodec[30] ; 114 | double lscale; 115 | 116 | PLATFORM_INIT(SPD_RINGS); 117 | 118 | /* Start by defining which raytracer we will be using */ 119 | if ( lib_gen_get_opts( argc, argv, 120 | &size_factor, &raytracer_format, &output_format ) ) { 121 | return EXIT_FAIL; 122 | } 123 | if ( lib_open( raytracer_format, "Rings" ) ) { 124 | return EXIT_FAIL; 125 | } 126 | 127 | radius = 0.07412 ; /* cone and sphere radius */ 128 | 129 | /* calculate spread of objects */ 130 | spread = 1 / sin( (double)( PI/8.0 ) ) ; 131 | if ( SPREAD_OUT <= spread ) { 132 | y_diff = spread / SPREAD_OUT ; 133 | xz_diff = 1.0 ; 134 | } 135 | else { 136 | y_diff = 1.0 ; 137 | xz_diff = SPREAD_OUT / spread ; 138 | } 139 | 140 | /* output background color - UNC sky blue */ 141 | /* NOTE: Do this BEFORE lib_output_viewpoint(), for display_init() */ 142 | /* note that the background color should never be seen */ 143 | SET_COORD3( back_color, 0.078, 0.361, 0.753 ) ; 144 | lib_output_background_color( back_color ) ; 145 | 146 | /* output viewpoint */ 147 | SET_COORD3( from, -1.0, -spread, 0.5 ) ; 148 | SET_COORD3( at, from[X], from[Y] + 1.0, from[Z] ) ; 149 | SET_COORD3( up, 0.0, 0.0, 1.0 ) ; 150 | lib_output_viewpoint( from, at, up, 45.0, 1.0, 1.0, 512, 512); 151 | 152 | /* 153 | * For raytracers that don't scale the light intensity, 154 | * we will do it for them 155 | */ 156 | #define NUM_LIGHTS 3 157 | lscale = ( ((raytracer_format==OUTPUT_NFF) || (raytracer_format==OUTPUT_RTRACE)) 158 | ? 1.0 : 1.0 / sqrt(NUM_LIGHTS)); 159 | 160 | /* output light source */ 161 | SET_COORD4( light, 3.0, -spread, 3.0, lscale ) ; 162 | lib_output_light( light ) ; 163 | SET_COORD4( light, -4.0, -spread, 1.0, lscale ) ; 164 | lib_output_light( light ) ; 165 | SET_COORD4( light, 2.0, -spread, -4.0, lscale ) ; 166 | lib_output_light( light ) ; 167 | 168 | /* output wall polygon - white */ 169 | SET_COORD3( back_color, 1.0, 1.0, 1.0 ) ; 170 | lib_output_color(NULL, back_color, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0); 171 | 172 | /* just spans 45 degree view + 1% */ 173 | wvec[Y] = y_diff * ( size_factor + 1 ) ; 174 | wvec[X] = wvec[Z] = 1.01 * ( wvec[Y] - from[Y] ) * tan( PI / 8.0 ) ; 175 | SET_COORD3( wall[0], wvec[X]+from[X], wvec[Y], wvec[Z]+from[Z] ) ; 176 | SET_COORD3( wall[1], -wvec[X]+from[X], wvec[Y], wvec[Z]+from[Z] ) ; 177 | SET_COORD3( wall[2], -wvec[X]+from[X], wvec[Y], -wvec[Z]+from[Z] ) ; 178 | SET_COORD3( wall[3], wvec[X]+from[X], wvec[Y], -wvec[Z]+from[Z] ) ; 179 | lib_output_polygon( 4, wall ) ; 180 | 181 | /* set up ring colors - RGB and complements */ 182 | SET_COORD3( ring_color[0], 1.0, 0.0, 0.0 ) ; 183 | SET_COORD3( ring_color[1], 0.0, 1.0, 0.0 ) ; 184 | SET_COORD3( ring_color[2], 0.0, 0.0, 1.0 ) ; 185 | SET_COORD3( ring_color[3], 0.0, 1.0, 1.0 ) ; 186 | SET_COORD3( ring_color[4], 1.0, 0.0, 1.0 ) ; 187 | SET_COORD3( ring_color[5], 1.0, 1.0, 0.0 ) ; 188 | 189 | create_dodec( radius, dodec ) ; 190 | /* radius of osculating cylinders and spheres (no derivation given) */ 191 | base_pt[W] = apex_pt[W] = radius ; 192 | 193 | for ( num_depth = 0 ; num_depth < size_factor ; ++num_depth ) { 194 | PLATFORM_PROGRESS(0, num_depth, size_factor-1); 195 | offset[Y] = y_diff * (double)(num_depth+1) ; 196 | for ( num_objz = 0 ; num_objz <= num_depth ; ++num_objz ) { 197 | offset[Z] = xz_diff * (double)(2*num_objz - num_depth) ; 198 | for ( num_objx = 0 ; num_objx <= num_depth ; ++num_objx ) { 199 | offset[X] = xz_diff * (double)(2*num_objx - num_depth) ; 200 | for ( num_elem = 0 ; num_elem < 30 ; ++num_elem ) { 201 | PLATFORM_MULTITASK(); 202 | COPY_COORD3( base_pt, dodec[num_elem] ) ; 203 | ADD2_COORD3( base_pt, offset ) ; 204 | if ( num_elem%5 == 0 ) { 205 | prev_elem = num_elem + 4 ; 206 | /* new ring beginning - output color */ 207 | lib_output_color(NULL, ring_color[num_elem/5], 208 | 0.0, 0.5, 0.2, 0.3, 37.0, 0.0, 0.0); 209 | } 210 | else { 211 | prev_elem = num_elem - 1 ; 212 | } 213 | COPY_COORD3( apex_pt, dodec[prev_elem] ) ; 214 | ADD2_COORD3( apex_pt, offset ) ; 215 | 216 | lib_output_cylcone( base_pt, apex_pt, output_format ) ; 217 | lib_output_sphere( base_pt, output_format ) ; 218 | } 219 | } 220 | } 221 | } 222 | 223 | lib_close(); 224 | 225 | PLATFORM_SHUTDOWN(); 226 | return EXIT_SUCCESS; 227 | } 228 | -------------------------------------------------------------------------------- /src/sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * sample.c - Simple file to make a scene with a few objects 3 | * 4 | * Author: Alexander Enzmann 5 | * 6 | * Modified: 1 September 1993 7 | * Eric Haines 8 | * changed file name, made sure values were passed as doubles 9 | * (the HPUX compiler sees "..., 5, ..." as an integer and merrily 10 | * passes the integer representation down to the subroutine which 11 | * wants a double). 12 | * 13 | * size_factor is ignored. 14 | * 15 | * size_factor # spheres # squares 16 | * x xx x 17 | */ 18 | 19 | #include 20 | #include /* atoi */ 21 | #include "def.h" 22 | #include "drv.h" /* display_close() */ 23 | #include "lib.h" 24 | 25 | 26 | /* These may be read from the command line */ 27 | static int size_factor = 1; 28 | static int raytracer_format = OUTPUT_RT_DEFAULT; 29 | static int output_format = OUTPUT_CURVES; 30 | 31 | #ifdef OUTPUT_TO_FILE 32 | static FILE * stdout_file = NULL; 33 | #else 34 | #define stdout_file stdout 35 | #endif /* OUTPUT_TO_FILE */ 36 | 37 | static COORD3 Red = { 1.0, 0.0, 0.0 }; 38 | static COORD3 Cyan = { 0.0, 1.0, 1.0 }; 39 | static COORD3 Yellow = { 1.0, 0.0, 1.0 }; 40 | static COORD3 Magenta = { 1.0, 1.0, 0.0 }; 41 | 42 | int 43 | main(argc, argv) 44 | int argc; 45 | char *argv[]; 46 | { 47 | COORD3 back_color; 48 | COORD4 from, at, up; 49 | COORD4 center, normal; 50 | COORD4 base, apex; 51 | 52 | PLATFORM_INIT(SPD_GENERIC); 53 | 54 | /* Start by defining which raytracer we will be using */ 55 | if ( lib_gen_get_opts( argc, argv, 56 | &size_factor, &raytracer_format, &output_format ) ) { 57 | return EXIT_FAIL; 58 | } 59 | if ( lib_open( raytracer_format, "Sample" ) ) { 60 | return EXIT_FAIL; 61 | } 62 | /* lib_set_polygonalization(8, 8); */ 63 | 64 | /* output background color - Light Grey */ 65 | /* NOTE: Do this BEFORE lib_output_viewpoint(), for display_init() */ 66 | SET_COORD3( back_color, 0.8, 0.8, 0.8 ) ; 67 | lib_output_background_color( back_color ) ; 68 | 69 | SET_COORD3(from, 0, 5, -5); 70 | SET_COORD3(at, 0, 0, 0); 71 | SET_COORD3(up, 0, 1, 0); 72 | lib_output_viewpoint(from, at, up, 45.0, 1.0, 0.001, 512, 512); 73 | 74 | SET_COORD4(center, -10, 20, -20, 1.0); 75 | lib_output_light(center); 76 | 77 | lib_output_color(NULL, Cyan, 0.1, 0.7, 0.0, 0.7, 10.0, 0.0, 1.0); 78 | SET_COORD3(center,-1, 0, 0); 79 | SET_COORD3(normal, 1, 1,-0.5); 80 | lib_output_torus(center, normal, 2.0, 0.5, output_format); 81 | PLATFORM_PROGRESS(0, 0, 4); 82 | 83 | lib_output_color(NULL, Magenta, 0.1, 0.7, 0.0, 0.7, 10.0, 0.0, 1.0); 84 | SET_COORD3(center, 0, 0, 0); 85 | SET_COORD3(normal, 0, 1,-0.5); 86 | lib_output_torus(center, normal, 2.0, 0.5, output_format); 87 | PLATFORM_PROGRESS(0, 1, 4); 88 | 89 | lib_output_color(NULL, Yellow, 0.1, 0.7, 0.0, 0.7, 10.0, 0.0, 1.0); 90 | SET_COORD3(center, 1, 0, 0); 91 | SET_COORD3(normal,-1, 1,-0.5); 92 | lib_output_torus(center, normal, 2.0, 0.5, output_format); 93 | PLATFORM_PROGRESS(0, 2, 4); 94 | 95 | lib_output_color(NULL, Red, 0.1, 0.7, 0.0, 0.7, 10.0, 0.0, 1.0); 96 | SET_COORD4(base, 0, -2, 0, 2); 97 | SET_COORD4(apex, 0, 2, 0, 0.1); 98 | lib_output_cylcone(base, apex, output_format); 99 | PLATFORM_PROGRESS(0, 3, 4); 100 | 101 | lib_set_polygonalization(4, 1); 102 | lib_output_color(NULL, Red, 0.1, 0.7, 0.0, 0.7, 10.0, 0.0, 1.0); 103 | SET_COORD3(base, 0, -2, 0); 104 | SET_COORD3(apex, 0, 1, 0); 105 | lib_output_disc(base, apex, 0.0, 4.0, output_format); 106 | PLATFORM_PROGRESS(0, 4, 4); 107 | 108 | lib_close(); 109 | 110 | PLATFORM_SHUTDOWN(); 111 | return EXIT_SUCCESS; 112 | } 113 | -------------------------------------------------------------------------------- /src/shells.c: -------------------------------------------------------------------------------- 1 | /* 2 | * shells.c - Creates a shell using Pickover's generation method (see IEEE 3 | * CG&A November 1989). One light source. This thing tends to bring ray 4 | * tracers to their knees (lots of overlapping primitives, many quite 5 | * tiny) - it's meant as a study of a realistic yet pathological database. 6 | * 7 | * There are various additional characteristics which can be diddled with 8 | * for different shell shapes (most pretty unrealistic, but there you go). 9 | * See Pickover's article for more information. Do "shells -?" to see the 10 | * additional parameters which can be varied (listed at the end). 11 | * 12 | * Author: Eric Haines 13 | * 14 | * Modified: Antonio Costa, INESC 15 | * Changed lib_get_opts to shells_get_opts 16 | * Corrected bug with light source definition 17 | * Changed several vars from COORD4 to COORD3 18 | * 19 | * Size factor determines the number of objects output. 20 | * Total objects = 180*(2**SF) spheres 21 | * 22 | * Size factor # spheres # squares 23 | * 1 360 1 24 | * 2 720 1 25 | * 3 1440 1 26 | * 4 2880 1 27 | * 5 5760 1 28 | */ 29 | 30 | #include 31 | #include 32 | #include "def.h" 33 | #include "lib.h" 34 | 35 | /* These may be read from the command line */ 36 | static int size_factor = 5; 37 | static int raytracer_format = OUTPUT_RT_DEFAULT; 38 | static int output_format = OUTPUT_CURVES; 39 | 40 | 41 | #ifdef OUTPUT_TO_FILE 42 | static FILE * stdout_file = NULL; 43 | #else 44 | #define stdout_file stdout 45 | #endif /* OUTPUT_TO_FILE */ 46 | 47 | 48 | static double fgamma = 1.0 ; /* 0.01 to 3 */ 49 | static double alpha = 0.0 ; /* > 1 - 1.1 is good */ 50 | static double beta = -2.0 ; /* ~ -2 */ 51 | static double a = 0.15 ; /* exponent constant */ 52 | static double k = 1.0 ; /* relative size */ 53 | 54 | static void 55 | shells_show_usage() 56 | { 57 | show_gen_usage() ; 58 | fprintf(stderr, "-a alpha - alpha value (0 to 1.1 is good)\n"); 59 | fprintf(stderr, "-b beta - beta value (-2 is good)\n"); 60 | fprintf(stderr, "-g gamma - gamma value (0.01 to 3 is good)\n"); 61 | fprintf(stderr, "-e exponent - exponent value (0.15 is good)\n"); 62 | } 63 | 64 | static int 65 | shells_get_opts( argc, argv, p_size, p_rdr, p_curve ) 66 | int argc ; 67 | char *argv[] ; 68 | int *p_size, *p_rdr, *p_curve ; 69 | { 70 | int num_arg ; 71 | int val ; 72 | double fval ; 73 | 74 | num_arg = 0 ; 75 | 76 | while ( ++num_arg < argc ) { 77 | if ( (*argv[num_arg] == '-') || (*argv[num_arg] == '/') ) { 78 | switch( argv[num_arg][1] ) { 79 | case 'g': /* gamma */ 80 | if ( ++num_arg < argc ) { 81 | sscanf( argv[num_arg], "%lf", &fval ) ; 82 | if ( fval < 0.0 ) { 83 | fprintf( stderr, 84 | "bad gamma value %lf given\n",fval); 85 | shells_show_usage(); 86 | return( TRUE ) ; 87 | } 88 | fgamma = fval ; 89 | } else { 90 | fprintf( stderr, "not enough args for -g option\n" ) ; 91 | shells_show_usage(); 92 | return( TRUE ) ; 93 | } 94 | break ; 95 | case 'a': /* alpha */ 96 | if ( ++num_arg < argc ) { 97 | sscanf( argv[num_arg], "%lf", &alpha ) ; 98 | } else { 99 | fprintf( stderr, "not enough args for -a option\n" ) ; 100 | shells_show_usage(); 101 | return( TRUE ) ; 102 | } 103 | break ; 104 | case 'b': /* beta */ 105 | if ( ++num_arg < argc ) { 106 | sscanf( argv[num_arg], "%lf", &beta ) ; 107 | } else { 108 | fprintf( stderr, "not enough args for -b option\n" ) ; 109 | shells_show_usage(); 110 | return( TRUE ) ; 111 | } 112 | break ; 113 | case 'e': /* exponent selection */ 114 | if ( ++num_arg < argc ) { 115 | sscanf( argv[num_arg], "%lf", &a ) ; 116 | } else { 117 | fprintf( stderr, "not enough args for -e option\n" ) ; 118 | shells_show_usage(); 119 | return( TRUE ) ; 120 | } 121 | break ; 122 | 123 | case 's': /* size selection */ 124 | if ( ++num_arg < argc ) { 125 | sscanf( argv[num_arg], "%d", &val ) ; 126 | if ( val < 1 ) { 127 | fprintf( stderr, 128 | "bad size value %d given\n",val); 129 | shells_show_usage(); 130 | return( TRUE ) ; 131 | } 132 | *p_size = val ; 133 | } else { 134 | fprintf( stderr, "not enough args for -s option\n" ) ; 135 | shells_show_usage(); 136 | return( TRUE ) ; 137 | } 138 | break ; 139 | case 'c': /* true curve output */ 140 | *p_curve = OUTPUT_CURVES ; 141 | break ; 142 | case 't': /* tessellated curve output */ 143 | *p_curve = OUTPUT_PATCHES ; 144 | break ; 145 | case 'r': /* renderer selection */ 146 | if ( ++num_arg < argc ) { 147 | sscanf( argv[num_arg], "%d", &val ) ; 148 | if ( val < OUTPUT_VIDEO || val >= OUTPUT_DELAYED ) { 149 | fprintf( stderr, 150 | "bad renderer value %d given\n",val); 151 | shells_show_usage(); 152 | return( TRUE ) ; 153 | } 154 | *p_rdr = val ; 155 | } else { 156 | fprintf( stderr, "not enough args for -r option\n" ) ; 157 | shells_show_usage(); 158 | return( TRUE ) ; 159 | } 160 | break ; 161 | default: 162 | fprintf( stderr, "unknown argument -%c\n", 163 | argv[num_arg][1] ) ; 164 | shells_show_usage(); 165 | return( TRUE ) ; 166 | } 167 | } else { 168 | fprintf( stderr, "unknown argument %s\n", 169 | argv[num_arg] ) ; 170 | shells_show_usage(); 171 | return( TRUE ) ; 172 | } 173 | } 174 | return( FALSE ) ; 175 | } 176 | 177 | int 178 | main(argc,argv) 179 | int argc ; 180 | char *argv[] ; 181 | { 182 | double r,angle ; 183 | long i, steps ; 184 | COORD3 back_color, obj_color ; 185 | COORD3 from, at, up ; 186 | COORD4 light ; 187 | COORD4 sphere; 188 | 189 | PLATFORM_INIT(SPD_SHELLS); 190 | 191 | /* Start by defining which raytracer we will be using */ 192 | if ( shells_get_opts( argc, argv, 193 | &size_factor, &raytracer_format, &output_format ) ) { 194 | return EXIT_FAIL; 195 | } 196 | if ( lib_open( raytracer_format, "Shells" ) ) { 197 | return EXIT_FAIL; 198 | } 199 | /* lib_set_polygonalization(2, 2);*/ 200 | 201 | /* output background color - UNC sky blue */ 202 | /* NOTE: Do this BEFORE lib_output_viewpoint(), for display_init() */ 203 | SET_COORD3( back_color, 0.078, 0.361, 0.753 ) ; 204 | lib_output_background_color( back_color ) ; 205 | 206 | /* output viewpoint */ 207 | SET_COORD3( from, -6.0, -60.0, 35.0 ) ; 208 | SET_COORD3( at, 0.0, 8.0, -15.0 ) ; 209 | SET_COORD3( up, 0.0, 0.0, 1.0 ) ; 210 | lib_output_viewpoint( from, at, up, 45.0, 1.0, 0.5, 512, 512 ) ; 211 | 212 | /* output light sources */ 213 | SET_COORD4( light, -100.0, -100.0, 100.0, 1.0 ) ; 214 | lib_output_light( light ) ; 215 | 216 | /* set up sphere color */ 217 | SET_COORD3( obj_color, 1.0, 0.8, 0.4 ) ; 218 | lib_output_color( NULL, obj_color, 0.0, 0.8, 0.2, 0.5, 10.0, 0.0, 1.0 ) ; 219 | 220 | steps = (long)(180.0 * pow( 2.0, (double)size_factor )) ; 221 | for ( i = -steps*2/3; i <= steps/3 ; ++i ) { 222 | PLATFORM_PROGRESS(-steps*2/3, i, steps/3); 223 | PLATFORM_MULTITASK(); 224 | 225 | angle = 3.0 * 6.0 * PI * (double)i / (double)steps ; 226 | r = k * exp( a * angle ) ; 227 | sphere[X] = r * sin( angle ) ; 228 | sphere[Y] = r * cos( angle ) ; 229 | if ( alpha > 0.0 ) { 230 | /* alternate formula: z = alpha * angle */ 231 | sphere[Z] = alpha * angle ; 232 | } else { 233 | sphere[Z] = beta * r ; 234 | } 235 | sphere[W] = r / fgamma ; 236 | lib_output_sphere( sphere, output_format ) ; 237 | } 238 | 239 | lib_close(); 240 | 241 | PLATFORM_SHUTDOWN(); 242 | return EXIT_SUCCESS; 243 | } 244 | -------------------------------------------------------------------------------- /src/sombrero.c: -------------------------------------------------------------------------------- 1 | /* sombrero.c - example of the use of heightfield output 2 | From: Alexander Enzmann <70323.2461@compuserve.com> 3 | Updated: 4/22/95 Eduard Schwan - Added code to match other 4 | example styles, and made width/height variable based on size parameter 5 | * size_factor width/height patches 6 | * 1 32x32 7 | * 2 64x64 8 | * 3 128x128 9 | * 4 256x256 10 | 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include "def.h" 17 | #include "drv.h" /* display_close() */ 18 | #include "lib.h" 19 | 20 | /* Standard arguments */ 21 | static int size_factor = 1; 22 | static int raytracer_format = OUTPUT_RT_DEFAULT; 23 | static int output_format = OUTPUT_CURVES; 24 | 25 | /* Define constants for the sombrero function */ 26 | static double a_const, b_const, c_const, two_pi_a; 27 | 28 | static float ** 29 | create_sombrero(width, height, x0, x1, y0, y1) 30 | unsigned width, height; 31 | double x0, x1, y0, y1; 32 | { 33 | float **data; 34 | double x, deltax, y, deltay; 35 | unsigned i, j; 36 | 37 | a_const = 1.0; 38 | b_const = 1.0; 39 | c_const = 3.0; 40 | two_pi_a = 2.0 * 3.14159265358 * a_const; 41 | 42 | deltax = (x1 - x0) / (double)width; 43 | deltay = (y1 - y0) / (double)height; 44 | 45 | if ((data = malloc(height * sizeof(float *))) == NULL) { 46 | fprintf(stderr, "HF allocation failed\n"); 47 | exit(1); 48 | } 49 | for (i=0,y=y0;i .001 || transmitted > .001) { 19 | /* Construct a normalized incident vector */ 20 | IN = normalize (I); 21 | 22 | if (reflected > .001) { 23 | Rfldir = normalize(reflect(IN, Nf)); 24 | r = reflected * trace (P, Rfldir); 25 | } 26 | if (transmitted > .001) { 27 | Rfrdir = normalize(refract(IN, Nf, index)); 28 | tr = transmitted * trace (P, Rfrdir); 29 | } 30 | } 31 | 32 | Oi = Os; 33 | Ci = Os * ( Cs * (Ka*ambient() + Kd*diffuse(Nf) + r + tr) + 34 | specularcolor * Ks*specular(Nf,-normalize(I),roughness)); 35 | } 36 | -------------------------------------------------------------------------------- /src/tetra.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tetra.c - Create a tetrahedral pyramid. This environment is based on the 3 | * scene used by Glassner ("Space Subdivision for Fast Ray Tracing," IEEE 4 | * CG&A, October 1984) and Kay & Kajiya ("Ray Tracing Complex Scenes," 5 | * SIGGRAPH '86 Proceedings) for testing their ray tracers. 6 | * One light source. 7 | * 8 | * Author: Eric Haines 9 | * 10 | * Note: the view and light positions are the same (after transformation to 11 | * a different set of world coordinates) as used by Kay & Kajiya, 12 | * courtesy of Tim Kay. For some reason, the number of shadow rays 13 | * generated is different (Kay gets 34K, I get 46K). One light source. 14 | * 15 | * size_factor determines the number of polygons output. 16 | * Total triangular polygons = 4**SF 17 | * 18 | * size_factor # triangles 19 | * 1 4 20 | * 2 16 21 | * 3 64 22 | * 23 | * 6 4096 24 | */ 25 | 26 | #include 27 | #include 28 | #include /* atoi */ 29 | #include "def.h" 30 | #include "drv.h" /* display_close() */ 31 | #include "lib.h" 32 | 33 | static int size_factor = 6 ; 34 | static int raytracer_format = OUTPUT_RT_DEFAULT; 35 | static int output_format = OUTPUT_CURVES; 36 | 37 | #ifdef OUTPUT_TO_FILE 38 | static FILE * stdout_file = NULL; 39 | #else 40 | #define stdout_file stdout 41 | #endif /* OUTPUT_TO_FILE */ 42 | 43 | 44 | /* Create tetrahedrons recursively */ 45 | static void 46 | create_tetra( depth, center ) 47 | int depth ; 48 | COORD4 center ; 49 | { 50 | int num_face, num_vert, swap, vert_ord[3] ; 51 | int x_dir, y_dir, z_dir ; 52 | COORD3 face_pt[3], obj_pt[4] ; 53 | COORD4 sub_center ; 54 | 55 | if ( depth <= 1 ) { 56 | /* Output tetrahedron */ 57 | 58 | PLATFORM_MULTITASK(); 59 | 60 | /* find opposite corners of a cube which form a tetrahedron */ 61 | for ( num_vert = 0, x_dir = -1 ; x_dir <= 1 ; x_dir += 2 ) { 62 | for ( y_dir = -1 ; y_dir <= 1 ; y_dir += 2 ) { 63 | for ( z_dir = -1 ; z_dir <= 1 ; z_dir += 2 ) { 64 | if ( x_dir*y_dir*z_dir == 1 ) { 65 | obj_pt[num_vert][X] = 66 | center[X] + (double)x_dir * center[W] ; 67 | obj_pt[num_vert][Y] = 68 | center[Y] + (double)y_dir * center[W] ; 69 | obj_pt[num_vert][Z] = 70 | center[Z] + (double)z_dir * center[W] ; 71 | ++num_vert ; 72 | } 73 | } 74 | } 75 | } 76 | 77 | /* find faces and output */ 78 | for ( num_face = 0 ; num_face < 4 ; ++num_face ) { 79 | /* output order: 80 | * face 0: points 0 1 2 81 | * face 1: points 3 2 1 82 | * face 2: points 2 3 0 83 | * face 3: points 1 0 3 84 | */ 85 | for ( num_vert = 0 ; num_vert < 3 ; ++num_vert ) { 86 | vert_ord[num_vert] = (num_face + num_vert) % 4 ; 87 | } 88 | if ( num_face%2 == 1 ) { 89 | swap = vert_ord[0] ; 90 | vert_ord[0] = vert_ord[2] ; 91 | vert_ord[2] = swap ; 92 | } 93 | 94 | for ( num_vert = 0 ; num_vert < 3 ; ++num_vert ) { 95 | COPY_COORD3( face_pt[num_vert], obj_pt[vert_ord[num_vert]] ) ; 96 | } 97 | lib_output_polygon( 3, face_pt ) ; 98 | } 99 | } 100 | 101 | else { 102 | /* Create sub-tetrahedra */ 103 | 104 | /* find opposite corners of a cube to form sub-tetrahedra */ 105 | for ( x_dir = -1 ; x_dir <= 1 ; x_dir += 2 ) { 106 | for ( y_dir = -1 ; y_dir <= 1 ; y_dir += 2 ) { 107 | if (depth==size_factor) 108 | PLATFORM_PROGRESS(0, (x_dir+1)*2+(y_dir+1), 7); 109 | for ( z_dir = -1 ; z_dir <= 1 ; z_dir += 2 ) { 110 | if ( x_dir*y_dir*z_dir == 1 ) { 111 | sub_center[X] = 112 | center[X] + (double)x_dir * center[W] / 2.0 ; 113 | sub_center[Y] = 114 | center[Y] + (double)y_dir * center[W] / 2.0 ; 115 | sub_center[Z] = 116 | center[Z] + (double)z_dir * center[W] / 2.0 ; 117 | sub_center[W] = center[W] / 2.0 ; 118 | 119 | create_tetra( depth-1, sub_center ) ; 120 | } 121 | } 122 | } 123 | } 124 | } 125 | } 126 | 127 | int 128 | main(argc,argv) 129 | int argc ; 130 | char *argv[] ; 131 | { 132 | double lscale; 133 | COORD3 back_color, tetra_color ; 134 | COORD3 from, at, up ; 135 | COORD4 center_pt, light ; 136 | 137 | PLATFORM_INIT(SPD_TETRA); 138 | 139 | /* Start by defining which raytracer we will be using */ 140 | if ( lib_gen_get_opts( argc, argv, 141 | &size_factor, &raytracer_format, &output_format ) ) { 142 | return EXIT_FAIL; 143 | } 144 | if ( lib_open( raytracer_format, "Tetra" ) ) { 145 | return EXIT_FAIL; 146 | } 147 | 148 | /* output background color - UNC sky blue */ 149 | /* NOTE: Do this BEFORE lib_output_viewpoint(), for display_init() */ 150 | SET_COORD3( back_color, 0.078, 0.361, 0.753 ) ; 151 | lib_output_background_color( back_color ) ; 152 | 153 | /* output viewpoint */ 154 | SET_COORD3( from, 1.022846, -3.177154, -2.174512 ) ; 155 | SET_COORD3( at, -0.004103, -0.004103, 0.216539 ) ; 156 | SET_COORD3( up, -0.816497, -0.816497, 0.816497 ) ; 157 | lib_output_viewpoint( from, at, up, 45.0, 1.0, 1.0, 512, 512); 158 | 159 | /* 160 | * For raytracers that don't scale the light intensity, 161 | * we will do it for them 162 | */ 163 | #define NUM_LIGHTS 1 164 | lscale = ( ((raytracer_format==OUTPUT_NFF) || (raytracer_format==OUTPUT_RTRACE)) 165 | ? 1.0 : 1.0 / sqrt(NUM_LIGHTS)); 166 | 167 | /* output light source */ 168 | SET_COORD4( light, 2.0, -18.0, -5.0, lscale) ; 169 | lib_output_light( light ) ; 170 | 171 | /* output tetrahedron color - red */ 172 | SET_COORD3( tetra_color, 1.0, 0.2, 0.2 ) ; 173 | lib_output_color(NULL, tetra_color, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0); 174 | 175 | /* compute and output tetrahedral object */ 176 | SET_COORD4( center_pt, 0.0, 0.0, 0.0, 1.0 ) ; 177 | create_tetra( size_factor, center_pt ) ; 178 | 179 | lib_close(); 180 | 181 | PLATFORM_SHUTDOWN(); 182 | return EXIT_SUCCESS; 183 | } 184 | -------------------------------------------------------------------------------- /src/tree.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tree.c - Creates a tree using Aono & Kunii's generation method. 3 | * (See IEEE CG&A May 1984). A square polygon is placed beneath the 4 | * tree to act as a field. Seven light sources. 5 | * 6 | * Author: Eric Haines 7 | * 8 | * size_factor determines the number of objects output. 9 | * Total objects = 2**(SF+1)-1 cones and spheres + 1 square polygon. 10 | * 11 | * size_factor # spheres # cones # squares 12 | * 1 3 3 1 13 | * 2 7 7 1 14 | * 3 15 15 1 15 | * 16 | * 11 4095 4095 1 17 | */ 18 | 19 | #include 20 | #include 21 | #include /* atoi */ 22 | #include "def.h" 23 | #include "drv.h" /* display_close() */ 24 | #include "lib.h" 25 | 26 | /* These may be read from the command line */ 27 | static int size_factor = 11; 28 | static int raytracer_format = OUTPUT_RT_DEFAULT; 29 | static int output_format = OUTPUT_CURVES; 30 | 31 | #ifdef OUTPUT_TO_FILE 32 | static FILE * stdout_file = NULL; 33 | #else 34 | #define stdout_file stdout 35 | #endif /* OUTPUT_TO_FILE */ 36 | 37 | /* the following affect the shape of the tree */ 38 | #define BR_ANGLE_0 40.0 39 | #define BR_ANGLE_1 25.0 40 | #define BR_CONTR_0 0.65 41 | #define BR_CONTR_1 0.70 42 | #define BR_DIAMETER 0.67 43 | #define DIV_ANGLE 140.0 44 | #define WIDTH_HEIGHTH_RATIO 0.15 45 | 46 | static MATRIX Rst_mx[2] ; 47 | 48 | /* grow tree branches recursively */ 49 | static void 50 | grow_tree(cur_mx, scale, depth) 51 | MATRIX cur_mx; 52 | double scale; 53 | int depth; 54 | { 55 | int i; 56 | COORD3 vec; 57 | COORD4 apex, base; 58 | MATRIX new_mx; 59 | 60 | PLATFORM_MULTITASK(); 61 | 62 | /* output branch */ 63 | SET_COORD3( vec, 0.0, 0.0, 0.0 ) ; 64 | lib_transform_point( base, vec, cur_mx ) ; 65 | base[W] = scale * WIDTH_HEIGHTH_RATIO ; 66 | 67 | SET_COORD3( vec, 0.0, 0.0, 1.0 ) ; 68 | lib_transform_point( apex, vec, cur_mx ) ; 69 | apex[W] = base[W] * BR_DIAMETER ; 70 | 71 | lib_output_cylcone( base, apex, output_format ) ; 72 | lib_output_sphere( apex, output_format ) ; 73 | 74 | if ( depth > 0 ) { 75 | --depth ; 76 | 77 | for ( i = 0 ; i < 2 ; ++i ) { 78 | if (depth==size_factor-1) 79 | PLATFORM_PROGRESS(0, i, 1); 80 | lib_matrix_multiply( new_mx, Rst_mx[i], cur_mx ) ; 81 | grow_tree( new_mx, scale * BR_DIAMETER, depth ) ; 82 | } 83 | } 84 | } 85 | 86 | /* 87 | * Set up matrices for growth of each branch with respect to the 88 | * parent branch, then grow each branch. 89 | */ 90 | static void 91 | create_tree() 92 | { 93 | int i; 94 | double branch_angle, branch_contraction, divergence; 95 | MATRIX ident_mx, temp1_mx, temp2_mx, tempr_mx, tempst_mx; 96 | 97 | for ( i = 0 ; i < 2 ; ++i ) { 98 | if ( i == 0 ) { 99 | branch_angle = BR_ANGLE_0 ; 100 | divergence = 90.0 ; 101 | branch_contraction = BR_CONTR_0 ; 102 | } else { 103 | branch_angle = BR_ANGLE_1 ; 104 | divergence = DIV_ANGLE + 90.0 ; 105 | branch_contraction = BR_CONTR_1 ; 106 | } 107 | 108 | /* rotate along X axis by branching angle */ 109 | lib_create_rotate_matrix( temp1_mx, X_AXIS, branch_angle*PI/180.0 ) ; 110 | 111 | /* rotate along Z axis by divergence angle */ 112 | lib_create_rotate_matrix( temp2_mx, Z_AXIS, divergence*PI/180.0 ) ; 113 | 114 | lib_matrix_multiply( tempr_mx, temp1_mx, temp2_mx ) ; 115 | 116 | /* include translation of branch, scaled */ 117 | lib_create_identity_matrix( tempst_mx ) ; 118 | tempst_mx[0][0] = branch_contraction; 119 | tempst_mx[1][1] = branch_contraction; 120 | tempst_mx[2][2] = branch_contraction; 121 | tempst_mx[3][2] = 1.0; 122 | 123 | /* concatenate */ 124 | lib_matrix_multiply( Rst_mx[i], tempr_mx, tempst_mx ) ; 125 | } 126 | 127 | /* set up initial matrix */ 128 | lib_create_identity_matrix( ident_mx ) ; 129 | grow_tree( ident_mx, 1.0, size_factor ) ; 130 | } 131 | 132 | int 133 | main(argc,argv) 134 | int argc; 135 | char *argv[]; 136 | { 137 | COORD3 field[4]; 138 | COORD3 from, at, up; 139 | COORD3 back_color, tree_color; 140 | COORD4 light; 141 | double lscale; 142 | 143 | PLATFORM_INIT(SPD_TREE); 144 | 145 | /* Start by defining which raytracer we will be using */ 146 | if ( lib_gen_get_opts( argc, argv, 147 | &size_factor, &raytracer_format, &output_format ) ) { 148 | return EXIT_FAIL; 149 | } 150 | if ( lib_open( raytracer_format, "Tree" ) ) { 151 | return EXIT_FAIL; 152 | } 153 | 154 | /* output background color - UNC sky blue */ 155 | /* NOTE: Do this BEFORE lib_output_viewpoint(), for display_init() */ 156 | SET_COORD3( back_color, 0.078, 0.361, 0.753 ) ; 157 | lib_output_background_color( back_color ) ; 158 | 159 | /* output viewpoint */ 160 | SET_COORD3( from, 4.5, 0.4, 2.0 ) ; 161 | SET_COORD3( at, 0.0, 0.0, 1.5 ) ; 162 | SET_COORD3( up, 0.0, 0.0, 1.0 ) ; 163 | lib_output_viewpoint(from, at, up, 45.0, 1.0, 1.0, 512, 512); 164 | 165 | /* 166 | * For raytracers that don't scale the light intensity, 167 | * we will do it for them 168 | */ 169 | #define NUM_LIGHTS 7 170 | lscale = ( ((raytracer_format==OUTPUT_NFF) || (raytracer_format==OUTPUT_RTRACE)) 171 | ? 1.0 : 1.0 / sqrt(NUM_LIGHTS)); 172 | 173 | /* output light source */ 174 | SET_COORD4( light, -5.0, 5.0, 50.0, lscale ) ; 175 | lib_output_light( light ) ; 176 | SET_COORD4( light, 30.0, -30.0, 30.0, lscale ) ; 177 | lib_output_light( light ) ; 178 | SET_COORD4( light, -40.0, -30.0, 20.0, lscale ) ; 179 | lib_output_light( light ) ; 180 | SET_COORD4( light, 10.0, 30.0, 40.0, lscale ) ; 181 | lib_output_light( light ) ; 182 | SET_COORD4( light, -30.0, 40.0, 10.0, lscale ) ; 183 | lib_output_light( light ) ; 184 | SET_COORD4( light, 50.0, 25.0, 20.0, lscale ) ; 185 | lib_output_light( light ) ; 186 | SET_COORD4( light, -10.0, -60.0, 30.0, lscale ) ; 187 | lib_output_light( light ) ; 188 | 189 | /* output field polygon - green */ 190 | SET_COORD3( back_color, 0.2, 0.7, 0.2 ) ; 191 | lib_output_color(NULL, back_color, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0); 192 | SET_COORD3( field[0], 50.0, 50.0, 0.0 ) ; 193 | SET_COORD3( field[1], -50.0, 50.0, 0.0 ) ; 194 | SET_COORD3( field[2], -50.0, -50.0, 0.0 ) ; 195 | SET_COORD3( field[3], 50.0, -50.0, 0.0 ) ; 196 | lib_output_polygon( 4, field ) ; 197 | 198 | /* set up tree color - brown */ 199 | SET_COORD3( tree_color, 0.55, 0.4, 0.2 ) ; 200 | lib_output_color(NULL, tree_color, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0); 201 | 202 | /* create tree */ 203 | create_tree(); 204 | 205 | lib_close(); 206 | 207 | PLATFORM_SHUTDOWN(); 208 | return EXIT_SUCCESS; 209 | } 210 | -------------------------------------------------------------------------------- /src/view.dat: -------------------------------------------------------------------------------- 1 | 5 -20 0 # from 2 | 0 0 0 # at 3 | 0 0 1 # up 4 | 20 # angle 5 | # the above is a default view file for readdxf 6 | --------------------------------------------------------------------------------