Flirt/000755 000316 000311 00000000000 06114645511 011761 5ustar00wrzlgup000000 000000 Flirt/Doc/000755 000316 000311 00000000000 06114643123 012463 5ustar00wrzlgup000000 000000 Flirt/Doc/flirt.doc000644 000316 000311 00000121326 06114643123 014277 0ustar00wrzlgup000000 000000 ------------------------------------------------------------------------------- FLIRT Faster than Light Ray Tracer ~ ~~ ~ ~ by wRZL and rft ------------------------------------------------------------------------------- Faster than Light - that's real easy. Put an object 3000 km away and 'trace' more than 100 rays per second through that object -> we 'trace' 300000 km per second -> Faster than Light :-) (If you can't trace 100 per second -> put it farther away !) ------------------------------------------------------------------------------- Credits: Original Authors: wRZL - Wolfgang Stuerzlinger wrzl@eichow.una.ac.at rft - Robert F. Tobler ------------------------------------------------------------------------------- USAGE: flirt [-i ] [-l ] [-m simple] [-m riss] [-r [x]] [-x {}|{-}|{-}|{-}] [-y {}|{-}|{-}|{-}] ist ein FTL-File ist ein RGB-File Defaultmaessig ist das Standard Materialmodell aktiviert, '-m simple' aktiviert das Simple-Materialmodell. '-m riss' aktiviert das RISS-Materialmodell. Mit -l wird ein Logfile erzeugt, dabei werden die Eingabedaten (Szene,Camera, Lichtquellen,Objekte,Materialien,...) ebenfalls auf das Logfile ausgegeben. z.B. flirt test.ftl test.rgb flirt test.ftl test.rgb -l test.log -m riss -r 300x200 -x 10-20 -y 10-20 flirt ftl\test.ftl rgb\test.rgb -i ftl\ ------------------------------------------------------------------------------- FTL-Files ------------------------------------------------------------------------------- -------------------------------Syntaktisches--------------------------------- Gross-/Kleinschreibung egal (Ausnahme: #-Kommandos) Ganze Zahlen in der Schreibweise [-][0-9]+ Gleitkommazahlen in der Schreibweise [-][0-9]+{.[0-9]+} Trennung der Tokens durch Blank(s),Tab(s) und Zeilenschaltung(en) Alle Zeichen hinter einem '%' bis zum Ende der Zeile werden ignoriert ! #include - inkludiert ein File #if ... #endif wie #if im C-Preprozessor; zulaessige Bedingungen die erfuellt sein koennen: '#if true', und eine von '#if riss', '#if standard' und '#if simple', aber nie mehrere gleichzeitig. Zum Auskommentieren fuer Blocks also: '#if false' --------------------------------Beispiel-------------------------------- Beispiel (Roter Wuerfel ueber goldener Kugel): global scene smallmidpoint camera stest lights stest object stest material air background 0.48 0.6 0.9 #include scenes.dat camera stest eye 5.0 5.0 5.0 direction -5.0 -5.0 -5.0 zoom 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ sphere transform scale 0.5 0.5 0.5 trans 0.0 0.0 -0.5 material gold typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material rot end #include material.dat -----------------------------Allgemeines------------------------------------ Eine Farbe ist durch 3 Gleitkommazahlen gegeben, dem Rot-, Gruen- und Blau-Anteil, jeweils ein Wert zwischen 0 und 1. ################# BEGIN DERZEIT NICHT IMPLEMENTIERT ######################## Optional kann man mit Spektralfarben zu arbeiten, die Spektra werden durch 20 Spektralwerte angegeben. ################# ENDE DERZEIT NICHT IMPLEMENTIERT ######################## Punkte und Vektoren sind durch 3 Gleitkommazahlen gegeben, dem x-, y- und z-Wert. Falls in der Beschreibung ein ? vorkommt (z.B. ) ist ein Boolscher Wert gemeint. Er kann entweder 'true' oder 'false' sein. -------------------------Aufbau eines FTL-Files---------------------------- Ein FTL-File ist aus verschiedenen Abschnitten zusammengesetzt. global 'Inhaltsverzeichnis' scene Szenenbeschreibung camera Kameradefinition lights Lichtquellen object Objekte material Materialien 'global' kann nur einmal vorkommen, alle anderen Abschnitte koennen mehrfach (mit wechselnden Namen) im File auftreten ! --------------------------------global-------------------------------- global scene camera lights object material background Der Namen der Szene, Kamera, Lichtquellen und des Szenen-Objekt(baum)s bestimmen den Aufbau der Szene. 'material' bestimmt den globalen Brechungsindex (z.B. fuer Bilder unter Wasser usw). 'background' bestimmt die Farbe des Hintergrundes. --------------------------------scene-------------------------------- scene xpix xstart - optional xend - optional ypix xstart - optional xend - optional shadow_rays - optional texturing - optional bbox_test - optional bsphere_test - optional bounds_test - optional max_reflection max_refraction min_contribution SAMPLING xpix,ypix: maximale Aufloesung: 2048x2048 xstart,xend: default: 0 und xpix - 1 ystart,yend: default: 0 und ypix - 1 Mit diesen Parametern kann man z.B. nur einen Auschnitt raytracen. shadow_rays: default: TRUE Damit kann man verhindern dass Schattenfuehler geschossen werden. texturing: default: FALSE Normalerweise keine Texturen bbox_test,bsphere_test,bounds_test: Damit koennen die Boundingvolume-test kontrolliert werden bbox_test ist defaultmaessig TRUE, die anderen FALSE. Sinnlos ist es mehr als einen Boundingvolume-test zu aktiveren. max_reflection = 0 bedeutet keine Reflexionsstrahlen -> keine Spiegelungen max_refraction = 0 bedeutet keine Transparenzstrahlen -> keine Brechungen Mehr als 100 Reflexions und Transparenzstrahlen geben nur bei ganz speziellen Szenen einen Sinn. min_contribution ist ein Wert, bis zu dem ein Strahl fuer die Farbe eines Pixels noch beruecksichtigt wird (z.B. 0.00390625 = 1/256, kleinere Werte haben wenig Sinn !) SAMPLING = MIDPOINT | OVERSAMPLING | ADAPTIVE MIDPOINT := sampling midpoint OVERSAMPLING := sampling oversampling max_level ADAPTIVE := sampling adaptive max_level OVERSAMPLING ist ein jittered Oversampling ! Fuer ADAPTIVE sollte die Anzahl der rekursiven Unterteilungen 1 bis 4 sein Im Include-File "scenes.dat" sind einige Szenen vordefiniert. Die Commandline-Switches -r,-x,-y haben Prioritaet vor der Szenendefinition ! --------------------------------camera-------------------------------- camera eye direction - optional zoom - optional twist - optional parallel - optional Falls 'direction' nicht angegeben wird, wird die Kamera (falls sie innerhalb der Szene steht) auf den Mittelpunkt der Szene ausgerichtet. Falls 'zoom' nicht angegeben wird, wird der Zoomfaktor so eingestellt, dass die ganze Szene sichtbar ist. 'twist' ist normalerweise 0.0, 180.0 waere eine auf den Kopf gestellte Kamera 'parallel' ist normalerweise FALSE, also wird perspektivisch abgebildet ! --------------------------------lights-------------------------------- lights LIGHTSOURCE(S) - eine oder mehrere end LIGHTSOURCE = POINTLIGHT | AMBIENTLIGHT | INFINITYLIGHT | SPOTLIGHT | DISTRIBLIGHT | SPHERELIGHT POINTLIGHT := typ pointlight position color AMBIENTLIGHT := typ ambientlight color INFINITYLIGHT := typ infinitylight direction color SPOTLIGHT := typ spotlight position direction power minangle maxangle color DISTRIBLIGHT := typ distributionlight position direction distribution <19 Abstrahlungswerte> color SPHERELIGHT := typ spherelight position radius color ist die Farbe der Lichtquelle POINTLIGHT ist eine Punktlichtquelle. AMBIENTLIGHT ist ein Licht aus allen Richtungen gleichzeitig, dient also zur globalen Aufhellung. INFINITYLIGHT ist ein Lichtquelle die unendlich weit weg ist, deren Strahlen also parallel sind, in Richtung des angegeben Vektors SPOTLIGHT ist ein Spot: Der Richtungsvektor gibt die Abstrahlrichtung an. Es existieren zwei Moeglichkeiten die Abschwaechung zu definieren, beide zusammen sind auch moeglich ! 1) 'power' bestimmt den Grad der Abschwaechung, sinnvolle Werte liegen zwischen 0.0 (keine Abschwaechung) und 50 (Nadelstrahler). 2) Ab 'minangle' wird die Staerke noch abgeschwaecht bis sie bei 'maxangle' Null wird, d.h. ausserhalb dieses Winkels wird kein Licht mehr abgestrahlt. 'Minangle' muss kleiner 'maxangle' sein, falls keine Abschwaechung gewuenscht wird ist 'minangle' auf 0.0 zu setzen. (Zwischen minangle und maxangle wird die Abschwaechung kubisch interpoliert.) DISTRIBLIGHT ist eine Lichtquelle, bei der die Verteilung der Abstrahlung explizit in einer Tabelle angegeben wird. Fuer die Winkel von 0 bis 180 Grad werden in 10-Grad Schritten Werte vorgegeben, die die Abschwaechung bestimmen. Zwischen diesen Werten wird linear interpoliert. Jeder dieser Werte darf zwischen 0.0 und 1.0 sein. ################# BEGIN DERZEIT NICHT IMPLEMENTIERT ######################## SPHERELIGHT ist eine Kugellichtquelle mit dem angegebenen Durchmesser. ################# ENDE DERZEIT NICHT IMPLEMENTIERT ######################## --------------------------------object-------------------------------- Es koennen mehrere Objektbaume angegeben werden, die aneinander gehaengt werden koennen (siehe named objects). Hilfsstrukturen sind Punktlisten und Texturen, diese koennen ebenfalls mehrfach vorkommen. Sie werden ueber den angegeben Namen im Objektbaum verwendet. --------------------------------texture--------------------------------- ################# BEGIN DERZEIT NICHT IMPLEMENTIERT ######################## ################# ENDE DERZEIT NICHT IMPLEMENTIERT ######################## -------------------------------pointlist-------------------------------- points number ... Ueber 'number' wird die Anzahl der nachfolgenden Punkte definiert. ---------------------------------object--------------------------------- object OBJTREE end OBJTREE := COMBOBJ | NAMEDOBJ | GRIDOBJ | CUBEOBJ | SPHEROBJ | CYLINDOBJ | CONEOBJ | PARABOLOBJ | PARSWEPOBJ | TORUSOBJ | HYPERBOBJ | HYPERSOBJ | PLANEOBJ | TRIANGLEOBJ | BSPLINEOBJ | XYZ_UV_OBJ | FUNCT_UV_OBJ Ein Objektbaum besteht aus einem oder mehreren Objekten. Bei vielen Objekten kann eine Transformation angegeben werden: TRANSFORM := EXPLICITTRAF | MATRIXTRAF EXPLICITTRAF := { TRAFO }+ - eine oder mehrere TRAFO:= trans | scale | rotx | roty | rotz | shearxy | shearxz | shearyz MATRIXTRAF := matrix <4 x 3 Werte> Eine Transformation kann also entweder explizit durch Transformations- operationen, wie z.B. eine Verschiebung oder eine Rotation um die x-Achse gegeben sein, oder durch eine Matrix. Spiegelungen erreicht man durch eine Skalierung mit -1. COMBOBJ := OROBJ | ANDOBJ | SUBOBJ OROBJ := typ csg_or OBJTREE OBJTREE ANDOBJ := typ csg_and OBJTREE OBJTREE SUBOBJ := typ csg_sub OBJTREE OBJTREE Die Kombinationsknoten dienen zur CSG-Kombination von zwei Subbaeumen. Dabei hat immer der linke Baum Prioritaet, aber das Material der Grenzflaechen wird durch den jeweiligen Koerper definiert. Z.B. ist Glas-Kugel SUB Holz-Wuerfel eine durchsichtige Kugel, der ein Teil fehlt, die Schnittflaeche ist aber aus Holz, also undurchsichtig. Bei transparenten Materialien empfiehlt es sich die Objekte leicht ueberlappend zu definieren, da aufgrund numerischer Fehler sonst leicht unerwuenschte Effekte auftreten koennen. NAMEDOBJ := typ named object transform TRANSFORM - optional material - optional texture - optional Ein benanntes Objekt haengt einen bereits existierenden Objektbaum an dieser Stelle ein. Optional kann dieser Baum auch noch transformiert werden, das Material und die Texture koennen ebenfalls geaendert werden. Im File "platonic.dat" sind die fuenf platonischen Koerper als Objektbaeume enthalten: tetraeder,octaeder,hexaeder,icosaeder,dodecaeder. z.B.: #include platonic.dat ... typ named object icosaeder transform trans 0.0 0.0 1.0 material rot GRIDOBJ := typ grid dimension <3 Ganzzahlen> OBJTREE Ein Grid ist kein Objekt an sich, sondern eine Optimierung des Raytracens. Durch die 3 Werte 'dimension' wird eine regelmaessige Unterteilung des Raumes angegeben, dadurch entsteht ein Raum-'gitter', Fuer jedes dieser Raumelemente (voxel) werden nun alle Objekte gesammelt, die in diesem Volumen liegen. In diesem Grid koennen nun Strahlen schneller getraced werden, da nicht mehr der ganze Objektbaum beruecksichtigt werden muss. Sinnvolle Unterteilungen liegen im Bereich von 3x3x3 bis 25x25x25, und haengen von der Szene ab, z.B. fuer ein Schachbrett ist 7x7x4 sinnlos, 8x8x4 hingegen optimal. Der zusaetzliche Speicherverbrauch waechst mit der 3. Potenz. CUBEOBJ := CUBE | SIMPLECUBE CUBE := typ cube transform TRANSFORM - optional material texture - optional SIMPLECUBE := typ cube min max material texture - optional Ein Wuerfel oder Quader. Der Standard-Cube ist 0/0/0 - 1/1/1. Simplecube existiert zur einfacheren Eingabe von Wuerfeln/Quadern und ersetzt die Transformation durch Angabe zweier Eckpunkte. SPHEREOBJ := SPHERE | SIMPLESPHERE SPHERE := typ sphere transform TRANSFORM - optional material texture - optional SIMPLESPHERE := typ sphere center radius material texture - optional Eine Kugel oder Ellipsoid. Die Standard-Sphere hat den Mittelpunkt im Ursprung (0/0/0) und hat den Radius 1. Simplesphere existiert zur einfacheren Eingabe von Kugeln und ersetzt die Transformation durch Angabe des Mittelpunkts und Radius. CYLINDOBJ := typ cylinder transform TRANSFORM - optional material texture - optional CONEOBJ := typ cone transform TRANSFORM - optional material texture - optional PARABOLOBJ := typ paraboloid transform TRANSFORM - optional material texture - optional PARSWEPOBJ := typ parabolasweep transform TRANSFORM - optional material texture - optional Der Standard-Cylinder steht auf dem Ursprung und hat den Radius 1. Der Standard-Cone steht mit der Spitze im Ursprung, die Basisflaeche zeigt nach oben und hat den Radius 1. Das Standard-Paraboloid steht im Ursprung und endet bei z = 1, ist also dem Cone in seiner Gestalt aehnlich, oder ist eine Parabel um die z-Achse gedreht. Der Standard-Parsweep ist eine Parabel in der xy-Ebene die bei x = 1 endet und in z-Richtung bis z = 1 gesweept (verschoben) ist. TORUSOBJ := typ torus radius transform TRANSFORM - optional material texture - optional HYPERBOBJ := typ hyperboloid radius transform TRANSFORM - optional material texture - optional HYPERSOBJ := typ hyperboloasweep radius transform TRANSFORM - optional material texture - optional Der Standard-Torus hat als Mittelpunkt den Ursrung, liegt in der xy-Ebene und hat den Aussendurchmesser 1. Der Innendurchmesser bestimmt also die 'Dicke' des Torus. (0.0 < 'radius' < 1.0). Das Standard-Hyperboloid hat die z-Achse als Hauptachse und geht von -1 bis +1, Positive Radien geben ein einschaliges Hyperboloid, negative Radien geben ein zweischaliges Hyperboloid (-1.0 < 'radius' < 1.0). Die Gestalt ist also eine Hyperbel um die z-Achse gedreht. Der Standard-Hyperbolasweep ist eine Hyperbel in der xy-Ebene die von -1 bis +1 geht und in z-Richtung bis z = 1 gesweept (verschoben) ist (-1.0 < 'radius' < 1.0). PLANEOBJ := typ planes points number { PLANE }+ material texture - optional PLANE := plane <3 Punktindizes> | doubleplane <4 Punktindizes> Ein durch Ebenen begrenztes Objekt, z.B. ein Tetraeder. Dieses Objekt kann nicht direkt transformiert werden, sondern nur durch ein 'named'-Objekt. 'points' definiert die zu verwendene Punktliste, 'number' die Anzahl der Ebenen, wobei parallele Ebenen, also Doppelebenen, nur einmal zaehlen, ein Wuerfel hat also 'number'=3. Jede Ebene wird durch drei Punkte, durch ihre Indizes in der Punktliste, bestimmt, die parallele Doppelebene kann durch einen vierten Punkt festgelegt werten. TRIANGLEOBJ := typ triangle points vertices <3 Punktindizes> normals <3 Normalvektorindizes> - optional material texture - optional Ein Dreieck. Dieses Objekt kann nicht direkt transformiert werden, sondern nur durch ein 'named'-Objekt. 'points' definiert die zu verwendene Punktliste, 'vertices' definiert die drei Eckpunkte. Falls 'normals' angegeben wird, werden drei Normalvektoren den Eckpunkten zugeordnet, und beim Berechnen des Normalvektors wird zwischen diesen interpoliert (Phong-Shading). Falls 'normals' nicht angegeben wird, wird der Normalvektor ueber das Kreuzprodukt der Vektor von Punkt 1 zu Punkt 2 und von Punkt 1 zu Punkt 3 berechnet. Das Dreieck ist nur von einer Seite sichtbar !!!! BSPLINEOBJ := typ bspline_patch transform TRANSFORM - optional dimension <2 Ganzzahlen> order <2 Ganzzahlen> closed align nviteration thickness tolerance epiped_height controlpoints material texture - optional Eine Bezier- oder Bspline-Flaeche. 'dimension' definiert die Anzahl der Kontrollpunkte in u- und in v-Richtung. 'order' definiert die Ordnung in u- und v-Richtung ('order' = 'dimension' - Bezierflaeche 'order' < 'dimension' - Bsplineflaeche). 'closed' legt fest ob die Flaeche in u oder in v geschlossen ist. ....... 'controlpoints' ist eine Liste von 'order-u' mal 'order-v' Kontrollpunkten XYZ_UV_OBJ := typ epipedtree xyz_uv maxdepth - optional maxiterations - optional maxepipedheight - optional displaydepth - optional Local { MACRO_DEF }* - optional Equations X(U,V) = EXPR; Y(U,V) = EXPR; Z(U,V) = EXPR; U_Range - optional V_Range - optional transform TRANSFORM - optional material texture - optional FUNCT_UV_OBJ := typ epipedtree funct_uv maxdepth - optional maxiterations - optional maxepipedheight - optional displaydepth - optional Local { MACRO_DEF }* - optional Function F(U,V) = EXPR; U_Range - optional V_Range - optional transform TRANSFORM - optional material texture - optional MACRO_DEF := () = EXPR; | = EXPR; Eine durch Gleichungen in zwei unabhaengigen Variablen U und V definierte parameterische Flaechen. Bei Funct_UV-Flaechen gilt: X := U, Y := V, Z := F(U,V). Das Standardintervall fuer U oder V ist [0.0 ... 1.0]. ################# BEGIN DERZEIT NICHT IMPLEMENTIERT ######################## octree polyeder sweep (rotational,translational,conical) spheresweep select + transform + calculation ################# ENDE DERZEIT NICHT IMPLEMENTIERT ######################## --------------------------------material-------------------------------- Es existieren drei Materialmodelle: 'Standard', 'Simple' und 'Riss' 'Standard' sind die Standard-Materialien fuer Ray-Tracer. 'Simple' sind einfach zu definierende Materialien mit wenig Parametern. 'Riss' ist die Materialdefinition des RISS-Systems und haendisch nur schwer zu erstellen. Beim Aufruf des FLIRT ist defaultmaessig das 'Standard'- Modell eingestellt. Fuer alle Materialmodelle gilt: 'refract_index' ist der Brechungsfaktor, 1.0 ist der Defaultwert und entspricht Luft, 1.4 Glas, 2.42 Diamant, hoehere Werte sind undurchsichtig. Alle Farben sind durch 3 Farbwerte (Rot, Gruen, Blau) zwischen 0 und 1 definiert. Falls nicht anders angegeben sind alle Faktoren (z.B. reflectivity) ebenfalls zwischen 0 und 1 und haben als defaultwert 0. Ein 'Standard'-Material wird wie folgt definiert: material ambient diffuse specular specpow reflectivity transparency body translucency extinction refract_index emission 'ambient' ist eine Annaeherung des Umgebungslichts, 'diffuse' ist die diffuse Farbe, 'specular' definiert welches Licht bei Glanz reflektiert wird, 'specpow' bestimmt den Glanz (0 = matt, 200 = sehr glaenzend), 'reflectivity' bestimmt, wie stark das Material spiegelt, 'transparency' bestimmt, wie transparent das Material ist. 'body' definiert bei Transparenz die Farbe des Inneren des Materials, wobei der Defaultwert 1.0 1.0 1.0 ist ! 'translucency' bestimmt wie stark Licht durchscheinent, 'extinction' definiert, wie stark das Licht im Inneren durchgelassen wird, wobei der Defaultwert 1.0 1.0 1.0 alles Licht durchlaesst, 'emission' definiert ob das Material leuchtet. Nur 'diffuse' muss angegeben werden, alle anderen Werte sind optional. Das 'Simple'-Material-Modell wird durch '-m simple' aktiviert. material smoothness <'Glattheitsfaktor'> metalness <'Metallisch-Faktor'> transparency refract_index color 'smoothness' gibt die Glattheit der Oberflaeche an (zwischen 0.0 und 1.0). 0.0 gibt ein Material wie z.B. Tafelkreide, 1.0 sieht wie Plastik aus. 'metalness' gibt die Metall-Aehnlichkeit an (zwischen 0.0 und 1.0 - Metall). 'transparency' 1.0 ist sehr durchsichtig, 0.0 ist opaque (zwischen 0.0 und 1.0). Nur 'color' muss angegeben werden, alle anderen Werte sind optional. Das 'Riss'-Material-Modell wird durch '-m riss' aktiviert. material specular refract_index diffuse extinction absorption emission refraction facets <20 Mikrofacettenfaktoren> 'diffuse' ist nur zur Kontrolle vorhanden, es wird aus 'refraction' und 'extinction' berechnet, und kann nicht direkt geaendert werden ! Genaure Beschreibung siehe RISS. ------------------------------------------------------------------------------- Grammatik fuer FTL-Files ------------------------------------------------------------------------------- FILE := GLOBAL SCENE CAMERA LIGHTS POINTS OBJECTS { STDMATS | SMPLMATS | RISSMATS } GLOBAL := global scene camera lights object material background COLOR SCENE := scene xpix [ xstart ] [ xend ] ypix [ ystart ] [ yend ] [ shadow_rays ] [ texturing ] [ max_reflection ] [ max_refraction ] [ min_contribution ] { MIDPOINT | OVERSAMPLING | STOCHASTIC | ADAPTIVE } MIDPOINT := sampling midpoint OVERSAMPLING := sampling oversampling max_level ADAPTIVE := sampling adaptive max_level STOCHASTIC := sampling stochastic min_rays max_rays d alpha CAMERA := camera eye PNT3 [ direction VEC3 ] [ zoom ] [ twist ] [ parallel ] LIGHTS := lights LIGHT [ LIGHTS ] end LIGHT := { AMBIENTLIGHT | POINTLIGHT | INFINITYLIGHT | SPHERELIGHT | SPOTLIGHT | DISTRIBLIGHT } AMBIENTLIGHT := typ ambientlight color COLOR POINTLIGHT := typ pointlight position PNT3 color COLOR INFINITYLIGHT := typ infinitylight direction VEC3 color COLOR SPHERELIGHT := typ spherelight position PNT3 radius color COLOR SPOTLIGHT := typ spotlight position PNT3 direction VEC3 power minangle maxangle color COLOR DISTRIBLIGHT := typ distributionlight position PNT3 direction VEC3 distribution <19 x float> color COLOR POINTS := POINTLIST [ POINTS ] POINTLIST := points number POINTLIST1 POINTLIST1 := PNT3 [ POINTLIST1 ] OBJECTS := OBJECT [ OBJECTS ] OBJECT := object OBJNODE end OBJNODE := { COMBNODE | NAMEDOBJ | GRID | SCUBE | SSPHERE | OBJ | OBJ1PAR | HYPERELLOBJ | PLANEOBJ | TRIANGLEOBJ | BSPLINE | XYZ_UV | FUNCT_UV } COMBNODE := typ { csg_or | csg_and | csg_sub } OBJNODE OBJNODE NAMEDOBJ := typ named object [ transform TRANSFORMATION ] [ material ] [ texture ] GRID := typ grid dimx dimy dimz OBJNODE SCUBE := typ cube min PNT3 max PNT3 material [ texture ] SSPHERE := typ sphere center PNT3 radius material [ texture ] OBJ := typ { cube | sphere | cylinder | cone | paraboloid | parabolasweep } [ transform TRANSFORMATION ] material [ texture ] OBJ1PAR := typ { hyperboloid | hyperbolasweep | torus } radius [ transform TRANSFORMATION ] material [ texture ] HYPERELLOBJ := typ hyperellipsoid order VEC3 [ transform TRANSFORMATION ] material [ texture ] PLANEOBJ := typ planes points number PLANES material [ texture ] PLANES := { plane | doubleplane } [ PLANES ] TRIANGLEOBJ := typ triangle points vertices [ normals ] material [ texture ] BSPLINE := typ bspline_patch [ transform TRANSFORMATION ] dimension order closed thickness tolerance epiped_height controlpoints POINTLIST1 material [ texture ] XYZ_UV := typ epipedtree xyz_uv [ maxdepth ] [ maxiterations ] [ maxepipedheight ] [ displaydepth ] [ Local MACRO ] Equations X(U,V) = EXPR; Y(U,V) = EXPR; Z(U,V) = EXPR; [ U_Range ] [ V_Range ] material [ texture ] FUNCT_UV := typ epipedtree funct_uv [ maxdepth ] [ maxiterations ] [ maxepipedheight ] [ displaydepth ] [ Local MACRO ] Function F(U,V) = EXPR; [ U_Range ] [ V_Range ] material [ texture ] MACRO := { := EXPR; MACRO } | void TRANSFORMATION := { MATRIXTRANS | EXPLICITTRANS } MATRIXTRANS := matrix VEC3 VEC3 VEC3 VEC3 inverse VEC3 VEC3 VEC3 VEC3 EXPLICITTRANS := TRANS { EXPLICITTRANS } TRANS := { trans VEC3 | scale VEC3 | rotx | roty | rotz | shearxy <2 x float> | shearxz <2 x float> | shearyz <2 x float> } STDMATS := STDMAT [ STDMATS ] STDMAT := material [ ambient COLOR ] diffuse COLOR [ specular COLOR ] [ specpow ] [ reflectivity ] [ transparency ] [ body COLOR ] [ translucency ] [ extinction ] [ refract_index ] [ emission COLOR ] SMPLMATS := SMPLMAT [ SMPLMATS ] SMPLMAT := material [ smoothness ] [ metalness ] [ transparency ] [ refract_index ] color COLOR RISSMATS := RISSMAT [ RISSMATS ] RISSMAT:= material specular refract_index diffuse COLOR extinction COLOR absorption COLOR emission COLOR refraction COLOR facets <20 x float> COLOR := <3 x float> PNT3 := <3 x float> VEC3 := <3 x float> := T | F := {a-zA-Z0-9_}+ := {0-9}+ := [[-]{0-9}+].[{0-9+}][E[-|+]{0-9}+] diffuse COLOR extinction COLOR absorption COLOR emission COLOR refraction COLOR facets <20 x float> COLOR := <3 x fFlirt/Doc/program.doc000644 000316 000311 00000076576 06114643123 014646 0ustar00wrzlgup000000 000000 ------------------------------------------------------------------------------- Typen ------------------------------------------------------------------------------- File Typ Beschreibung color.d COLOR Repraesentation einer Farbe (FLOAT r,g,b) geometr2.d VEC2 2d Vektor (FLOAT x,y) geometr2.d PNT2 2d Punkt (FLOAT x,y) geometr2.d INTPNT2 2d Punkt mit Integerkoordinaten (INT x,y) geometr2.d MAT2 2d Transformationsmatrix (FLOAT e[3][2]) geometr2.d AXIS2 2d Strahl (PNT2 origin,VEC2 direction) geometr2.d RAY2 2d Strahl - mit 1 / Richtung (PNT2 origin,VEC2 direction,VEC2 inv_dir) geometr2.d BOX2 2d Box (PNT2 min,max) geometr2.d SPHERE2 2d Sphere - mit Radius^2 (PNT2 center,FLOAT radius_2) geometr3.d VEC3 3d Vektor (FLOAT x,y,z) geometr3.d PNT3 3d Punkt (FLOAT x,y,z) geometr3.d INTPNT3 3d Punkt mit Integerkoordinaten (INT x,y,z) geometr3.d MAT3 3d Transformationsmatrix (FLOAT e[4][3]) geometr3.d AXIS3 3d Strahl (PNT3 origin,VEC3 direction) geometr3.d RAY3 3d Strahl - mit 1 / Richtung (PNT3 origin,VEC3 direction,VEC3 inv_dir) geometr3.d BOX3 3d Box (PNT3 min,max) geometr3.d SPHERE3 3d Sphere - mit Radius^2 (PNT3 center,FLOAT radius_2) geometr3.d PLANE3 3d Ebene (PNT3 origin,VEC3 normal,FLOAT ndotp) hitlist.d HITINFO Eintrag in Hitliste (HITINFO *next - Verkettung, ULONG face - Oberflaechenummer, FLOAT t - Strahlparameter, OBJECT *obj - Oberflaechenobjekt, OBJECT *newobj - Strahl tritt in diese Obj ein, RAY3 ray - Strahl im lokalen Koordsys (inv_dir wird nicht benuetzt), VEC3 normal - Normalvektor, PNT2 uv - Oberflaechenkoordinaten, PNT3 local_point - Punkt im lokalen Koordsys, VEC3 local_normal - NV im lokalen Koordsys) [ normal,uv,local_point,local_normal muessen nicht gesetzt sein, koennen aber bereits vor einem Aufruf von 'norm()' belegt sein - siehe Objektprozeduren ] hitlist.d HITLIST Hitliste (HITINFO *first,*last, OBJECT *firstobj - Objekt in dem die Liste beginnt) objects.d OBJECT Objektknoten (OBJTYP typ,BYTE test_bbox - Flags fuer Boundingboxtest,BOOLEAN test_bsphere - Flag fuer Boundingspheretest,ULONG rayno - fuer Optimierung, BOX3 - Boundingbox,SPHERE3 - Boundingsphere, BOUNDLIST *bounds - sonstige Umgebungen, union u - spezielle Objectdaten) system.d WORD Maschinenwort system.d BOOL Boolscher Wert (1 byte) system.d BOOLEAN Boolscher Wert (1 byte) system.d CHAR Zeichen (1 byte) system.d INT 16-bit Integer (2 byte) system.d LONG 32-bit Integer (4 byte) system.d UCHAR Character fuer Strings (1 byte) system.d BYTE 8-bit Integer ohne Vorzeichen (1 byte) system.d UINT 16-bit Integer ohne Vorzeichen (2 byte) system.d ULONG 32-bit Integer ohne Vorzeichen (4 byte) system.d FLOAT Floatingpointzahl mit 7 Stellen Genauigkeit system.d DOUBLE Floatingpointzahl mit 15 Stellen Genauigkeit Macros: system.d VOID fuer Prozeduren - void system.d VOIDPTR fuer allgemeine Zeiger - Zeiger auf VOID system.d Const fuer konstante - const system.d Extern fuer externe Variablen/Funktionen - extern system.d Register fuer Registervariable - register system.d Static fuer lokale/statische Variable/Funktionen - static system.d TRUE fuer BOOLEAN system.d FALSE fuer BOOLEAN system.d forever Endlosschleife system.d block block { local_vars; stmts; } light.d Strukturen fuer Lichtquellen material.d Strukturen fuer Materialien objects.d Strukturen fuer Objekten szene.d Strukturen fuer Szenen texture.d Strukturen fuer Texturen ------------------------------------------------------------------------------- Macros/Funktionen ------------------------------------------------------------------------------- --------------------------------File: bounding.f------------------------------- VEC3 box_normal[7] Tabelle der Normalvektoren auf eine Box, meist indiziert ueber face 1-6 ! BOOLEAN hitbbox(RAY3 *ray, FLOAT *tmin, FLOAT *tmax, BYTE mask, BOX3 *box) TRUE wenn der Strahl die Boundingbox trifft - wobei nur die Seiten getestet werden die in mask angegeben sind - Rueckgabe tmin-tmax BOOLEAN hitbox(RAY3 *ray, FLOAT *tmin, FLOAT *tmax, ULONG *tminface, ULONG *tmaxface, BOX3 *box) TRUE wenn der Strahl die Box trifft - tmin,tmax sind nur Ausgabe- parameter, der Strahl wird also von -F_HUGE bis F_HUGE mit der Box geschnitten! tminface,tmaxface geben die Seiten an, wo der Strahl trifft. BOOLEAN hitbsphere(RAY3 *ray,FLOAT *tmin,FLOAT *tmax,SPHERE3 *sphere) TRUE wenn der Strahl die Boundingsphere trifft - Rueckgabe tmin-tmax BOOLEAN hitbounds(RAY3 *ray,FLOAT *tmin,FLOAT *tmax,BOUNDLIST *bounds) TRUE wenn der Strahl die Umgebungen trifft - Rueckgabe tmin-tmax BOOLEAN insidebbox(PNT3 *pnt,BOX3 *box) TRUE wenn der Punkt innerhalb der Box liegt BOOLEAN insidebsphere(PNT3 *pnt,SPHERE3 *sphere) TRUE wenn der Punkt innerhalb der Sphere liegt BOOLEAN insidebounds(PNT3 *pnt,BOUNDLIST *bounds) TRUE wenn der Punkt innerhalb der Umgebungen liegt VOID boundsphere4box(BOX3 *box,SPHERE3 *sphere) liefert eine Sphere, die die Box umschliesst VOID bounds4points(UINT number,PNT3 *points,BOX3 *box,SPHERE3 *sphere, PNT3 *center,MAT3 *mat) Fuer die Punktliste (Array points mit number Punkten) wird falls Box != NULL eine Boundingbox erstellt, falls Sphere != NULL eine Boundingsphere mit vorgegebenem Mittelpunkt (Center == NULL), falls Center != NULL wird der Mittelpunkt geschaetzt. Optional kann noch eine Transformationsmatrix angegeben werden mit der die Punkt vorher transformiert werden. BOOLEAN HIT_BOUNDS(OBJECT *obj,RAY3 ray,FLOAT tmin,FLOAT tmax) - Macro TRUE wenn der Strahl die Umgebungen des Objekts trifft BOOLEAN INSIDE_BOUND_TEST(OBJECT *obj,PNT3 pnt) - Macro TRUE wenn der Punkt innerhalb der Objektumgebungen liegt --------------------------------File: color.f-------------------------------- FLOAT colormax(COLOR c) - Macro liefert den maximaler Farbwert BOOLEAN color_iszero(COLOR c) - Macro TRUE, wenn == 0.0 also schwarz FLOAT extract_r(COLOR c) - Macro FLOAT extract_g(COLOR c) - Macro FLOAT extract_b(COLOR c) - Macro liefert den Rot/Gruen/Blau-Anteil einer Farbe VOID colorinit(COLOR c,FLOAT k) - Macro Initialisiert alle Farbwerte mit k VOID colormini(COLOR c1,COLOR c2,COLOR c) - Macro VOID colormaxi(COLOR c1,COLOR c2,COLOR c) - Macro Minimum/Maximum zweier Farben VOID coloradd(COLOR c1,COLOR c2,COLOR c) - Macro VOID colorsub(COLOR c1,COLOR c2,COLOR c) - Macro VOID colormult(COLOR c1,COLOR c2,COLOR c) - Macro VOID colordiv(COLOR c1,COLOR c2,COLOR c) - Macro Addition/Subtraktion/Multiplikation/Division zweier Farben VOID coloraddscaled(COLOR c1,COLOR c2,FLOAT k,COLOR c) - Macro Addition mit skalierter zweiter Farbe VOID colormultk(COLOR c1,FLOAT k,COLOR c) - Macro Multiplikation mit einem Wert VOID colorpowk(COLOR c1,FLOAT k,COLOR c) - Macro Farbe hoch k VOID colorinv(COLOR c1,COLOR c) - Macro Berechnet 1 / Farbe VOID colorinterpol(COLOR c1,COLOR c2,FLOAT t,COLOR c) - Macro Interpolation zwischen 2 Farben mit Parameter t COLOR COLWHITE,COLBLACK,COLRED,COLGREEN,COLBLUE; Farben Weiss,Schwarz,Rot,Gruen,Blau VOID readcolor(COLOR *color) Liest eine Farbe vom Datenfile VOID writecolor(COLOR *color) Schreibt eine Farbe auf das Datenfile --------------------------------File: flirt.f--------------------------------- VOIDPTR newonlymem(WORD x) * newonlytyp() * newonlyuni(,) * newonlyvar(,) Funktionen zum Anfordern von Speicher (nie mehr als 65000 Bytes auf ein mal !). Diese Funktionen dienen zum Anfordern von Speicher fuer den Objektbaum und fuer Speicher den die Objekte zusaetzlich brauchen. newonlymem fordert eine spezifizierte Anzahl von Bytes an, newonlytyp allociert Platz fuer einen bestimmten Typ,. newonlyuni fordert Speicherplatz fuer die Variante eines Typ (Union) an newonlyvar fordert Speicherplatz fuer die Strukture Typ und die die Variante Var an (Name der Variante = u - leider fix, z.B. newonlyvar(OBJECT,PLANEOBJ)) Dieser Speicher wird am Ende des Raytracens vom System wieder freigegeben. (Siehe auch system.f) --------------------------------File: geometr2.f------------------------------ Da VEC2 = PNT2 koennen alle Vektormacros auch auf Punkte angewendet werden u.u. Alle 2-d Macros koennen auch auf 3-d Daten angewandt werden. FLOAT v2length_2(VEC2 v) - Macro Laenge eines Vektors zum Quadrat FLOAT v2length(VEC2 v) - Macro Laenge eines Vektors FLOAT v2dot(VEC2 v1,VEC2 v2) - Macro Skalares produkt VOID v2dist_2(PNT2 p1,PNT2 p2,FLOAT dist_2) - Macro Distanz zweier Punkt zum Quadrat VOID v2dist(PNT2 p1,PNT2 p2,FLOAT dist) - Macro Distanz zweier Punkte VOID v2pmin(PNT2 p1,PNT2 p2,PNT2 p) - Macro VOID v2pmax(PNT2 p1,PNT2 p2,PNT2 p) - Macro Minimum/Maximum zweier Punkte VOID v2normalize(VEC2 v) - Macro Normalisert den Vektor VOID v2invdir(VEC2 v,VEC2 v1) - Macro Berechnet 1 / Vektor VOID v2negate(VEC2 v) - Macro Vektor in entgegengesetze Richtung VOID v2scale(VEC2 v,FLOAT s) - Macro Skaliert mit einem Faktor VOID v2divk(VEC2 v,FLOAT k) - Macro Skaliert mit 1 / Faktor VOID v2add(VEC2 v1,VEC2 v2,VEC2 v) - Macro VOID v2sub(VEC2 v1,VEC2 v2,VEC2 v) - Macro VOID v2mult(VEC2 v1,VEC2 v2,VEC2 v) - Macro Addiert/Subtrahiert/Multipliziert zwei Vektoren/Punkte VOID v2addto(VEC2 v,VEC2 v1) - Macro VOID v2subfrom(VEC2 v,VEC2 v1) - Macro Addiert zu/Subtrahiert von einem Vektor/Punkt VOID v2interpol(VEC2 v1,VEC2 v2,FLOAT t,VEC2 v) - Macro Interpoliert zwischen zwei Vektoren VOID v2addscaled(VEC2 v1,VEC2 v2,FLOAT t,VEC2 v) - Macro Addition mit skaliertem zweiten Vektor VOID v2add2scaled(VEC2 v1,FLOAT t1,VEC2 v2,FLOAT t2,VEC2 v) - Macro Addition zweier skalierter Vektoren --------------------------------File: geometr3.f----------------------------- Da VEC3 = PNT3 koennen alle Vektormacros auch auf Punkte angewendet werden u.u. FLOAT v3length_2(VEC3 v) - Macro Laenge eines Vektors zum Quadrat FLOAT v3length(VEC3 v) - Macro Laenge eines Vektors FLOAT v3dot(VEC3 v1,VEC3 v3) - Macro Skalares produkt VOID v3dist_3(PNT3 p1,PNT3 p3,FLOAT dist_2) - Macro Distanz zweier Punkt zum Quadrat VOID v3dist(PNT3 p1,PNT3 p3,FLOAT dist) - Macro Distanz zweier Punkte VOID v3pmin(PNT3 p1,PNT3 p3,PNT3 p) - Macro VOID v3pmax(PNT3 p1,PNT3 p3,PNT3 p) - Macro Minimum/Maximum zweier Punkte VOID v3normalize(VEC3 v) - Macro Normalisert den Vektor VOID v3invdir(VEC3 v,VEC3 v1) - Macro Berechnet 1 / Vektor VOID r3normalize(RAY3 r) - Macro Normalisiert einen Strahl VOID v3negate(VEC3 v) - Macro Vektor in entgegengesetze Richtung VOID v3scale(VEC3 v,FLOAT s) - Macro Skaliert mit einem Faktor VOID v3divk(VEC3 v,FLOAT k) - Macro Skaliert mit 1 / Faktor VOID v3add(VEC3 v1,VEC3 v3,VEC3 v) - Macro VOID v3sub(VEC3 v1,VEC3 v3,VEC3 v) - Macro VOID v3mult(VEC3 v1,VEC3 v3,VEC3 v) - Macro Addiert/Subtrahiert/Multipliziert zwei Vektoren/Punkte VOID v3addto(VEC3 v,VEC3 v1) - Macro VOID v3subfrom(VEC3 v,VEC3 v1) - Macro Addiert zu/Subtrahiert von einem Vektor/Punkt VOID v3multk(VEC3 v1,FLOAT k,VEC3 v) - Macro Skaliert einen Vektor VOID v3cross(VEC3 v1,VEC3 v2,VEC3 v) - Macro Kreuzprodukt zweier Vektoren (v1 != v und v2 != v) VOID v3interpol(VEC3 v1,VEC3 v3,FLOAT t,VEC3 v) - Macro Interpoliert zwischen zwei Vektoren VOID v3addscaled(VEC3 v1,VEC3 v3,FLOAT t,VEC3 v) - Macro Addition mit skaliertem zweiten Vektor VOID v3add3scaled(VEC3 v1,FLOAT t1,VEC3 v3,FLOAT t3,VEC3 v) - Macro Addition zweier skalierter Vektoren FLOAT m3det(MAT3 m) - Macro Determinante einer Matrix FLOAT v3det(VEC3 v1,VEC3 v2,VEC3 v3) - Macro Determinante dreier Vektoren VOID m3mmulm(MAT3 m1,MAT3 m2,MAT3 m) - Macro Matrizenmultiplikation (m1 != m und m2 != m) VOID v3pmulm(PNT3 p1,MAT3 m,PNT3 p) - Macro Punkt mal Matrix (p1 != p) VOID v3vmulm(VEC3 v1,MAT3 m,VEC3 v) - Macro Vektor mal Matrix (v1 != v) VOID v3vmultransm(VEC3 v1,MAT3 m,VEC3 v) - Macro Vektor mal transponierter Matrix (v1 != v) VOID m3trans(FLOAT xt,FLOAT yt,FLOAT zt,MAT3 one,MAT3 two) - Macro VOID m3rotx(FLOAT alpha,MAT3 one,MAT3 two) - Macro VOID m3roty(FLOAT alpha,MAT3 one,MAT3 two) - Macro VOID m3rotz(FLOAT alpha,MAT3 one,MAT3 two) - Macro VOID m3scale(FLOAT xs,FLOAT ys,FLOAT zs,MAT3 one,MAT3 two) - Macro VOID m3shearxy(FLOAT xs,FLOAT ys,MAT3 one,MAT3 two) - Macro VOID m3shearxz(FLOAT xs,FLOAT zs,MAT3 one,MAT3 two) - Macro VOID m3shearyz(FLOAT ys,FLOAT zs,MAT3 one,MAT3 two) - Macro transformieren die Matrizen mit der angegebenen Transformation one - Hintransformation, two - Ruecktransformation, sollten beide vor der Verwendung mit M3UNIT initialisert werden Spiegelungen mit z.B. m3scale(-1,1,1,...) VOID m3invert(MAT3 *in,MAT3 *out) Invertiert die Matrix (in != out) MAT3 M3ZERO,M3UNIT Null- und Einheitsmatrix VEC3 V3ZERO,V3ONE Null- und Einheitsvektor VEC3 V3XUNIT,V3YUNIT,V3ZUNIT,V3XNEGUNIT,V3YNEGUNIT,V3ZNEGUNIT Achsenvektoren VEC3 V3SCENE_EPS 'kleinster' Vektor VOID readpnt3(PNT3 *pnt) VOID readvec3(VEC3 *vec) VOID readmat3(MAT3 *mat) Lesen einen Punkt/Vektor/Matrix vom Datenfile VOID readtransform(MAT3 *to,MAT3 *from) Liest eine Transformation (Matrix oder expizit) vom Datenfile VOID writepnt3(PNT3 *pnt) VOID writevec3(VEC3 *vec) VOID writemat3(MAT3 *mat) Schreiben einen Punkt/Vektor/Matrix auf das Datenfile VOID writetransform(MAT3 *to,MAT3 *from) Schreibt eine Transformation (Matrix) auf das Datenfile POINTARRAY *readnamepoints(VOID) Liest den Namen eines Pointarrays vom Datenfile (d.h. den String 'points ') und gibt einen Pointer auf das Array zurueck. VOID writenamepoints(POINTARRAY *points) Schreibt den Namen eines Pointarrays auf das Datenfile (d.h. den String 'points '). --------------------------------File: hitlist.f-------------------------------- FLOAT hit_eps Epsilon fuer Hitlisten HITLIST emptyhitlist Leere Hitliste - zum Initialisieren VOID checkaddmin(ULONG hitface,FLOAT hit,ULONG tminface,FLOAT tmin,FLOAT tmax) VOID checkaddmax(ULONG hitface,FLOAT hit,ULONG tmaxface,FLOAT tmin,FLOAT tmax) Macros fuer Objekte, die durch Halbraeume definiert sind Ueberpruefen den hit mit Oberflaeche 'hitface' gegen das t-Intervall 'tmin-tmax' und speichern in 'tminface/tmaxface' die Oberflaeche falls hit groesser/kleiner als tmax/tmin - early exit (= return(FALSE)) sonst falls im Intervall tmin/tmax neu setzen und Oberflaeche merken VOID makehit(ULONG hitface,FLOAT hitt,HITINFO *hit) - Macro Anlegen eines HITINFO-Records VOID checkmakehit(ULONG face,FLOAT t,HITINFO *hit) - Macro Falls face != 0 wird ein Hit angelegt VOID makerayhit(ULONG hitface,FLOAT hitt,RAY3 ray,HITINFO *hit) - Macro Anlegen eines HITINFO-Records mit Strahl VOID checkmakerayhit(ULONG face,FLOAT t,RAY3 ray,HITINFO *hit) - Macro Falls face != 0 wird ein Hit mit Strahl angelegt VOID freehit(HITINFO *hit) - Macro Freigeben eines Hits VOID skiphit(HITINFO *hit) - Macro Ueberspringen eines Hits in einer Hitlist und freigeben des Hits VOID freelist(HITINFO *fhit,HITINFO *lhit) - Macro Gibt eine Hitlist frei (Parameter sind Zeiger auf den ersten und letzten Eintrag) BOOLEAN returnhitlist(HITLIST *hl) - Macro Gibt TRUE zurueck wenn die Hitlist nicht leer ist BOOLEAN prepare2hits(OBJECT *hitobj,HITINFO *hit1,HITINFO *hit2, HITLIST *hitlist) - Macro BOOLEAN prepare4hits(OBJECT *hitobj,HITINFO *hit1,HITINFO *hit2, HITINFO *hit3,HITINFO *hit4,HITLIST *hitlist) - Macro Legt eine Hitlist 'hitlist' mit den entsprechenden Hits an. NULL im ersten/letzten Hit (hit1/hit2(4)) signalisiert, dass die Hitlist bei tmin/tmax beginnt/endet. VOID freehitlist(HITLIST *hitlist) Gibt eine Hitliste frei VOID releasehitlists(HITLIST *hitlist) gibt die Hitliste frei, allen anderen Hitlists werden ebenfalls freigegeben, die Hitlistcopies werden alle freigegeben. VOID copyhitlist((HITLIST *fromlist, HITLIST *tolist,BOOLEAN as_normal_hits) Kopiert die Hitliste, wobei bei as_normal_hits = TRUE die Hits als normale Hits angelegt werden, ansonsten als Hitlistcopies VOID dumphitlist(HITLIST *list) Gibt eine Hitliste aus VOID initbacktransforms(VOID) legt den Speicherbereich fuer Backtransforms an. MATRIXNODE *allocbacktransform(VOID) Allokiert ein Backtransformation. VOID backtransform(VEC3 *normal,HITINFO *hit) Transformiert den Normalvektor zurueck. VOID freebacktransforms(VOID) Gibt den Speicher fuer die Backtransforms wieder frei. BOOLEAN orhitlists(HITLIST *leftlist, HITLIST *rightlist,HITLIST *combilist) BOOLEAN andhitlists(HITLIST *leftlist, HITLIST *rightlist,HITLIST *combilist) BOOLEAN subhitlists(HITLIST *leftlist, HITLIST *rightlist,HITLIST *combilist) Kombiniert zwei Hitlisten - These routines have been written with the precondition that both hit- lists are valid for the same interval. (This condition is a byproduct of the way the CSG-trees are handled.) BOOLEAN or2hits(OBJECT *obj,HITINFO *hit1,HITINFO *hit2,HITLIST *hitlist) BOOLEAN and2hits(OBJECT *obj,HITINFO *hit1,HITINFO *hit2,HITLIST *hitlist) BOOLEAN sub2hits(OBJECT *obj,HITINFO *hit1,HITINFO *hit2,HITLIST *hitlist) Kombiniert 2 Hits (IN & OUT) in eine Hitliste hinein. Das Objekt ist das getroffene Objekt. --------------------------------File: material.f-------------------------------- MATERIAL *readnamematerial(VOID) Liest den Namen eines Materials vom Datenfile (d.h. den String 'material ') und gibt einen Pointer auf das Material zurueck. --------------------------------File: numeric.f-------------------------------- FLOAT f_floor(FLOAT x) - Macro FLOAT f_abs(FLOAT x) - Macro FLOAT f_sqrt(FLOAT x) - Macro FLOAT f_cbrt(FLOAT x) - Macro FLOAT f_sin(FLOAT x) - Macro FLOAT f_cos(FLOAT x) - Macro FLOAT f_tan(FLOAT x) - Macro FLOAT f_asin(FLOAT x) - Macro FLOAT f_acos(FLOAT x) - Macro FLOAT f_atan(FLOAT x) - Macro FLOAT f_atan2(FLOAT x,FLOAT y) - Macro FLOAT f_exp(FLOAT x) - Macro FLOAT f_log(FLOAT x) - Macro FLOAT f_pow(FLOAT x,y) - Macro FLOAT f_mod(FLOAT x,y) - Macro FLOAT f_round(FLOAT x) - Macro FLOAT F_THIRD 1/3 FLOAT F_E e FLOAT F_PI pi FLOAT F_2PI 2 * pi FLOAT F_PI_HALF pi / 2 FLOAT F_SQRT2 Wurzel(2) FLOAT F_SQRT3 Wurzel(3) FLOAT F_DEG2RAD Rad = F_DEG2RAD * Grad FLOAT F_RAD2DEG Grad = F_RAD2DEG * Rad FLOAT F_SMALL Sehr klein FLOAT F_HUGE Sehr gross Mathematikfunktionen/Konstanten fuer FLOATs F_SMALL gilt als Epsilon fuer alle normalen Zwecke ! DOUBLE d_floor(DOUBLE x) - Macro DOUBLE d_abs(DOUBLE x) - Macro DOUBLE d_sqrt(DOUBLE x) - Macro DOUBLE d_cbrt(DOUBLE x) - Macro DOUBLE d_sin(DOUBLE x) - Macro DOUBLE d_cos(DOUBLE x) - Macro DOUBLE d_tan(DOUBLE x) - Macro DOUBLE d_asin(DOUBLE x) - Macro DOUBLE d_acos(DOUBLE x) - Macro DOUBLE d_atan(DOUBLE x) - Macro DOUBLE d_atan2(DOUBLE x,DOUBLE y) - Macro DOUBLE d_exp(DOUBLE x) - Macro DOUBLE d_log(DOUBLE x) - Macro DOUBLE d_pow(DOUBLE x,y) - Macro DOUBLE d_mod(DOUBLE x,y) - Macro DOUBLE d_round(DOUBLE x) - Macro DOUBLE D_THIRD 1/3 DOUBLE D_E e DOUBLE D_PI pi DOUBLE D_2PI 2 * pi DOUBLE D_PI_HALF pi / 2 DOUBLE D_SQRT2 Wurzel(2) DOUBLE D_SQRT3 Wurzel(3) DOUBLE D_DEG2RAD Rad = D_DEG2RAD * Grad DOUBLE D_RAD2DEG Grad = D_RAD2DEG * Rad DOUBLE D_SMALL Sehr klein DOUBLE D_HUGE Sehr gross Mathematikfunktionen/Konstanten fuer DOUBLEs BOOLEAN f_iszero(FLOAT x) - Macro BOOLEAN d_iszero(DOUBLE x) - Macro TRUE wenn fast oder == 0.0 ANY mini(ANY x,ANY y) - Macro ANY maxi(ANY x,ANY y) - Macro ANY abso(ANY x) - Macro ANY sign(ANY x) - Macro Minimum/Maximum/Absolutwert/Vorzeichen fuer allgemeine Zahlen ANY interpol(ANY l,ANY h,ANY t) - Macro Interpolation zwischen l und h mit dem Paramter t UINT iroundscale(UINT a,UINT b,UINT val) UINT itruncscale(UINT a,UINT b,UINT val) ULONG lroundscale(ULONG a,ULONG b,ULONG val) ULONG ltruncscale(ULONG a,ULONG b,ULONG val) The macros can be used to scale value 'val' in the range [0..a] into the range [0..b], with rounding or truncating FLOAT f_eps DOUBLE d_eps Maschinenepsilon FLOAT f_eps_factor DOUBLE d_eps_factor 1 + Maschinenepsilon = (1,00...01) UINT npol2roots(DOUBLE *pol, DOUBLE *root) UINT pol2roots(DOUBLE *pol, DOUBLE *root) UINT npol3roots(DOUBLE *pol, DOUBLE *root) UINT pol3roots(DOUBLE *pol, DOUBLE *root) UINT pol4roots(DOUBLE *pol, DOUBLE *root) Gleichungsloesungen bis 4. Grad pol ist der Array der Koeffizienten, root sind die Ergebnisse die Wurzeln sind sortiert, doppelte Wurzeln werden nicht eingetragen Zurueckgegeben wird die Anzahl der Loesungen pol*() sind fuer Allgemeine Polynome z.B.: pol[4]*x^4 + pol[3]*x^3 + pol[2]*x^2 + pol[1]*x + pol[0] = 0.0 npol*() sind Routinen fuer normalisierte Polynome z.B.: x^2 + pol[1]*x + pol[0] = 0.0 DOUBLE npol3oneroot(DOUBLE *pol) Gibt eine (beliebige) Loesung der Gleichung 3.Grades zurueck -----------------------------File: objects.f-------------------------------- OBJECT *readnameobject(VOID) Liest den Namen eines Objekts vom Datenfile (d.h. den String 'object ') und gibt einen Pointer auf das Objekt zurueck. VOID writenameobject(OBJECT *object) Schreibt den Namen eines Objekts auf das Datenfile (d.h. den String 'object '). OBJECT *readobjects(VOID) VOID writeobjects(OBJECT *) ULONG setupobjects(OBJECT *obj,BOOLEAN in_or_tree,BOOLEAN space_opt) VOID endobjects(VOID) VOID exitobjects(VOID) Diese Funktionen fuehren den rekursiven Aufruf fuer die entsprechenden Methoden durch. Alle anderen Methoden werden ueber die Methodenarrays rekursiv aufgerufen ! VOID HITBOUNDSONLY(OBJECT *obj,FLOAT tmin,FLOAT tmax, BOOLEAN ray_hit_obj) - Macro VOID HITOBJONLY(OBJECT *obj,FLOAT tmin,FLOAT tmax,HITLIST *hitlist, BOOLEAN ray_hit_obj) - Macro VOID HITOBJ(OBJECT *obj,FLOAT tmin,FLOAT tmax,HITLIST *hitlist, BOOLEAN ray_hit_obj) - Macro Schneidet einen Strahl mit den Boundingvolumen/Objekt oder mit beiden. ray_hit_obj ist TRUE wenn der Strahl trifft. VOID PRE_OBJECT(OBJECT *obj,HITLIST *hitlist) VOID POST_OBJECT(OBJECT *obj,HITLIST *hitlist) Erledigen Verwaltungsaufgaben fuer ein Primitivobjekt (z.B Hitlist kopieren, Backtransforms, usw.) POST_OBJECT ist vor returhitlist aufzurufen, wenn der Strahl trifft. ------------------------------File: parse.f-------------------------------- #### FIXME: Beschreibung fehlt, wird neu implementiert #### ------------------------------File: random.f------------------------------- VOID seed_rand PP(ULONG seed) Initialisiert den Zufallsgenerator neu. FLOAT rand01(VOID) Liefert eine gleichverteilte Zufallszahl zwischen 0 und 1. #### FIXME: Teil der Beschreibung fehlt #### -----------------------------File: readdata.f------------------------------ BOOLEAN readbool(VOID) UINT readuint(VOID) DOUBLE readreal(VOID) Liest eine Boolean/UINT/DOUBLE vom Datenfile VOID match_read_bool(UCHAR *s,BOOLEAN v) - Macro VOID match_read_uint(UCHAR *s,UINT v) - Macro VOID match_read_real(UCHAR *s,FLOAT/DOUBLE v) - Macro Liest einen String und eine BOOLEAN/UINT/FLOAT/DOUBLE vom Datenfile VOID option_read_bool(UCHAR *s,BOOLEAN v,BOOLEAN default) - Macro VOID option_read_uint(UCHAR *s,UINT v,UINT default) - Macro VOID option_read_real(UCHAR *s,FLOAT/DOUBLE v,FLOAT/DOUBLE default) - Macro Wenn der angegebene String am Datenfile steht, wird der String und eine BOOLEAN/UINT/FLOAT/DOUBLE vom File gelesen; andernfalls erhaelt 'v' den Wert 'default'. BOOLEAN nextisnumeric(VOID) Gibt TRUE zurueck, wenn das naechste Token am Datenfile eine Zahl ist BOOLEAN nextisvalidname(VOID) Gibt TRUE zurueck, wenn das naechste Token am Datenfile ein gueltiger Name ist. BOOLEAN matchconststring(UCHAR *string) Gibt TRUE zurueck, wenn am Datenfile der String seht - liest nicht vom File - nur zum Testen VOID readconststring(UCHAR *string) Liest einen String vom Datenfile BOOLEAN matchreadconststring(UCHAR *string) Wenn auf dem Datenfile der String steht wird TRUE zureuckgeben ansonsten wird FALSE zurueckgegeben und das Token nicht(!) gelesen VOID open_read(UCHAR Const *filename,UCHAR Const *includepath) VOID close_read(VOID) Oeffnen und Schliessen ein Eingabefile. Koennen zum Einlesen eigener Files verwendet werden (ASCII Format, keine Binaerdaten !). 'includepath' kann NULL sein (keine #include) oder der Pfad fuer die Dateienen (z.B. '/usr/flirt/ftl/') VOID nexttoken(VOID) Liest das naechste Token vom Datenfile UCHAR *token Zeigt auf das aktuelle Token (Bitte nicht veraendern - READONLY) Ist fuer Fehlermeldungen usw. gedacht. UINT linenumber Beinhaltet die aktuelle Zeilennummer des Datenfiles, und ist fuer Fehlermeldungen gedacht (Bitte nicht veraendern - READONLY). --------------------------------File: scene.f-------------------------------- FLOAT scene_eps Epsilon abhaengig von der Szene --------------------------------File: system.f-------------------------------- SYSTEM ist als Speicherbereichs-'id' global verfuegbar, und dient zum Anfordern von Speicher, der mit freemem(SYSTEM,ptr) wieder freigegeben werden muss. Alle anderen Speicherbereiche werden vom FLIRT am Ende wieder freigegeben. VOID getallocid(WORD bytes) Gibt eine 'id' fuer einen Speicherbereich zurueck. 'bytes' gibt an wie gross die Bloecke sein sollen, mit dem FLIRT Speicher vom Betriebssystem anfordert. (d.h. mit 'bytes' = 10000 wird bei newmem immer ein Teil der ersten 10000 bytes vergeben, falls der erste Block voll ist, wird ein zweiter Block mit 10000 Bytes angefordert usw.) VOID releaseallocid(UINT id) Gibt den Speicher eines Speicherbereichs an das Betriebssystem wieder zurueck, 'id' ist nachher keine gueltige Speicherbereichs-'id' mehr. VOIDPTR newmem(UINT id,WORD x) * newtyp(UINT id,) * newuni(UINT id,,) * newvar(UINT id,,) Funktionen zum Anfordern von Speicher (nie mehr als 65000 Bytes auf ein mal !). Diese Funktionen fordern Speicher zu einem bestimmten Bereich 'id' an. 'id' = SYSTEM fordert Speicher an, der explizit mit freemem(SYSTEM,ptr) wieder freigegeben werden muss(!). newmem fordert eine spezifizierte Anzahl von Bytes an, newtyp allociert Platz fuer einen bestimmten Typ,. newuni fordert Speicherplatz fuer die Variante eines Typ (Union) an newvar fordert Speicherplatz fuer die Strukture Typ und die die Variante Var an (Name der Variante = u - leider fix, z.B. newvar(OBJECT,PLANEOBJ)) VOID freemem(UINT id,VOIDPTR blockptr) Bei 'id' = SYSTEM wird der mit newmem(SYSTEM) allokierte Speicher wieder freigegeben. Mit freemem(id,NULL) wird der Speicher eines Bereiches 'id' wieder freigegeben, die 'id' ist aber nach wie vor gueltig. VOID screen_message(Const UCHAR *fmt,...) VOID log_message(Const UCHAR *fmt,...) VOID message(Const UCHAR *fmt,...) Printf-Meldung auf dem Bildschirm oder auf dem Logfile oder auf beidem (Ausgabe auf Logfile nur falls mit -l aktiviert) VOID fatal(Const UCHAR *fmt,...) Fehlermeldung ULONG clocktime(VOID) - Macro Gibt eine Zeitmarke (Sekunden) zurueck DOUBLE time2secs(ULONG begin,ULONG end) Gibt die Anzahl der Sekunden zwischen den zwei Zeitmarken zurueck ULONG clockticks(VOID) - Macro Gibt eine Zeitmarke (Maschinengenauigkeit) zurueck Mit ticks koennen keine langen (d.h. Stunden) Intervalle gemessen werden. DOUBLE ticks2secs(ULONG begin,ULONG end) Gibt die Anzahl der Sekunden zwischen den zwei Zeitmarken zurueck mit Sekundenbruchteilen (soweit die Uhr genau ist !) ------------------------------File: texture.f-------------------------------- TEXTURE *readnametexture(VOID) Liest den Namen einer Textur vom Datenfile (d.h. den String 'texture ') und gibt einen Pointer auf die Textur zurueck. VOID writenametexture(TEXTURE *texture) Schreibt den Namen einer Textur auf das Datenfile (d.h. den String 'texture '). ------------------------------File: writdata.f-------------------------------- Es muessen zwischen 2 Werten keine Blanks ausgegeben werden da z.B. writeuint(10); writereal(1.0); writestring("test"); folgende Ausgabe ergibt: '10 1.0 test' VOID writebool(BOOLEAN value) VOID writeuint(UINT value) VOID writereal(DOUBLE value) VOID writestring(UCHAR Const *string) Schreibt eine Boolean/UINT/DOUBLE/String auf das Ausgabefile. VOID write_string_bool(UCHAR *s,BOOLEAN v) - Macro VOID write_string_uint(UCHAR *s,UINT v) - Macro VOID write_string_real(UCHAR *s,FLOAT/DOUBLE v) - Macro Schreibt einen String, eine Boolean/UINT/DOUBLE und eine LF (Zeilenschaltung) auf das Ausgabefile. VOID writelf(VOID) Schreibt eine Zeilenschaltung auf das Ausgabefile. VOID writedata(UCHAR Const *filename) Wenn filename == NULL werden alle Daten auf ein eventuelles Logfile ausgegeben, ansonsten wird das File neu angelegt und es werden alle Daten auf das angegeben File ausgegeben. Alle Daten entspricht der vollen Szenenbeschreibung also Szene, Camera,Lq,Objekte,Materialien usw. Diese werden aber vom FLIRT sowieso auf das Logfile ausgegeben. VOID open_write(UCHAR Const *filename) VOID close_write(VOID) Oeffnen und Schliessen ein Ausgabefile. Koennen zur Erstellung eigener Files verwendet werden (ASCII Format, keine Binaerdaten !). Falls open_write(NULL) aufgerufen wird, wird die Ausgabe auf den Bildschirm umgelenkt. usgegeben. Alle Daten entspricht der vollen Szenenbeschreibung also Szene, Camera,Lq,Objekte,Materialien usw. DiesFlirt/Doc/style.doc000644 000316 000311 00000021320 06114643123 014310 0ustar00wrzlgup000000 000000 ------------------------------------------------------------------------------- Programmierstil ------------------------------------------------------------------------------- Damit nicht nur der Programmierer seinen eigenen Code versteht, und sonst niemand, gibt es einige 'Regeln', die im FLIRT eingehalten werden sollen. Schlecht lesbarer Code ist nicht brauchbar, da jeder Fehler (nobody's perfect) viel mehr Aufwand als noetig verursacht (vor allem wenn der Programmierer nicht mehr da ist), wesentlich schlechter an neue Anforderungen anpassbar ist, und daher wird dieser Code sehr schnell nicht mehr verwendet werden und in Vergessenheit geraten! Bei Konflikten gilt folgende Reihenfolge: 1) Erweiterbarkeit die Module werden nicht nur fuer Raytracing verwendet sondern auch fuer Radiosity usw. 2) Wartbarkeit des Codes siehe oben. 3) Lesbarkeit des Codes siehe oben. 4) Effizienz wir wollen schliesslich nicht ewig warten, aber besser langsamer als nicht 1-3 5) Speicherverbrauch trotzdem gilt die Devise sparen, aber Werte die schon berechnet wurden, ausser sie sind trivial zu berechnen, sind zwischenzuspeichern. ------------------------------------------------------------------------------- Beispiele ------------------------------------------------------------------------------- *.d file ------------------------------------------------------------------------------- #ifndef X_D #define X_D #include "flirt.d" /* all *.d include this */ #include "geometr3.d" /* all needed *.d files */ #define MAX_RAYS 20 /* number of rays in ray.c */ struct raystruct { PNT3 origin; /* Eyepoint */ VEC3 direction; /* direction of view */ }; typedef struct raystruct RAY3; typedef enum { LILA, ROSA, BLASSBLAU } AMPEL; #endif ------------------------------------------------------------------------------- *.f file ------------------------------------------------------------------------------- #ifndef X_F #define X_F #include "numeric.d" /* all needed *.d files */ #include "geometr3.f" /* all needed *.f files */ Extern OBJECT *global_object; /* global CSG-tree */ VOID funktion_with_no_args PP((VOID)); VOID testfunc PP((UCHAR *filename)); FLOAT funktions_aufruf_mit_vielen_argumenten PP((ULONG testwert, UCHAR *filename,UCHAR *oldfilename)); #define mini(x,y) (((x) < (y)) ? (x) : (y)) #define v3pmin(p1,p2,p) \ { \ (p).x = mini((p1).x,(p2).x); \ (p).y = mini((p1).y,(p2).y); \ (p).z = mini((p1).z,(p2).z); \ } #endif ------------------------------------------------------------------------------- *.c file ------------------------------------------------------------------------------- #include "flirt.f" /* all *.c include this */ #include "numeric.d" /* all needed *.d files */ #include "geometr3.f" /* all needed *.f files */ OBJECT *global_object; /* documented global variable */ VOID testfunc(UCHAR *filename) { UINT i; /* Stil 1 */ ULONG testwert; /* Stil 1 */ FLOAT rays_per_second; /* Stil 1 */ UCHAR oldfilename[30]; /* Stil 2 */ POINTLIST *point; /* Stil 2 */ if (global->object->u.giga_object.data->e[index1][index2] != 0 && strcmp (filename,oldfilename) == 0) { i = (1 + 2) * 3 / 4; /* das ist ein kommentar */ testtwert = 3L; /* das ist ein ULONG -> L */ for (i = 0; i < 10; i++) testwert += (ULONG) i; /* typ cast */ rays_per_second = funktions_aufruf_mit_vielen_argumenten (testwert, filename,oldfilename); } else /* hier gilt filename != oldfilename */ { printf ("Sehr langer ausfuehrlicher Text zur Beschreibung %s\n\n", filename); } do { i++; } while(testwert == 0L); } ------------------------------------------------------------------------------- Organisatorisches - Filenamen maximal 8 + 3 Zeichen lang, wegen Mess-DOS :-( - Dokumentation ist noetig (schon alleine fuer die Mathematik und dazugehoerige Skizzen) Globale Organisation der Files: - *.d files: structs,typedefs,enums und #define CONST 12 - *.f files: Globale Variablendeklarationen Prototypes Funktionsmakros (#define abs(a) (a) < 0 ? -(a) : (a)) - *.c files: Code Variablendefinitionen. - alle *.d files #include'n alle zur Kompilation benoetigten *.d files - alle *.f files #include'n alle zur Kompilation benoetigten *.d und *.f files - alle *.c files #include'n alle zur Kompilation benoetigten *.d und *.f files - alle *.d,*.f files sind gegen doppeltes #includes zu schuetzen (s.o.) Programmierstil - 1 Modul - 1 Stil ! - 1 Statement pro Zeile - max. 80 Zeichen pro Zeile, bei ueberlangen Zeilen rechtsbuendig fortsetzen - Geschwungene Klammern: folgende 2 Stile sind o.k. /* Stil 1 */ /* Stil 2*/ if ( ) do if ( ) { do { { { } } while ( ); } } else { else while ( ); } { } - Vor und nach einem Operatoren immer ein Blank - Kommentare im Code rechtsbuendig, sonst vor der Funktion - Einrueckungen 4 Spaces - keine Tabs (2 und 3 Spaces sind auch ok, aber ein Modul - ein Stil, also nicht einmal 2, einmal 4, usw.) Datendeklarationen - Moeglichst (ausser fuer Schleifenvariable) eine Deklaration pro Zeile - Bei Aufzaehlungstypen enum's verwenden nicht #define-Serien - VOIDPTR ist anstatt VOID * zu verwenden aus Portabilitaetsgruenden - UINT (16 bit), ULONG (32 bit), BYTE (8 bit) fuer alles was nicht nicht negativ werden kann. ULONG nur wenn noetig. - UCHAR fuer Strings - BOOLEAN und FALSE/TRUE fuer logische Werte und nicht UINT oder gar int ! - normalerweise FLOAT verwenden, nur bei mehr benoetigter Genauigkeit DOUBLE verwenden - Const fuer konstanten und konstante Strings - Extern fuer Deklaration globaler Variabelen (*.f files) - Static fuer statische Variablen Funktionsdeklarationen, Parameter - neuer Stil - ANSI-C, d.h UINT max(UINT a,UINT b) - Prototypes fuer alle Funktionen ! - Schrweibweise fuer Prototypes: VEC3 *megafunction PP((UINT a,VEC3 *b)); durch das PP((...)) wird Compilation mit K&R Compilern moeglich. - Funktionen die keine Parameter haben, bzw. nichts zurueckgeben mit wie folgt zu deklarieren: VOID function PP((VOID)); - UCHAR Const * fuer Parameter und Rueckgabewerte verwenden wenn moeglich - Nie einen VEC3 direkt an eine funktion uebergeben, immer VEC3 *, wenn eine Kopie verwendet werden muss, dann eine lokale Variable deklarieren, dadurch wird die Stackbelastung geringer gehalten - Rueckgabewerte immer nur BYTE,UCHAR,UINT,ULONG,FLOAT,DOUBLE und Pointer auf beliebige Werte, also nie eine Struktur/Union/Array direkt zurueckgeben. Die Rueckgabe von Strukturen erfolgt durch einen Zeiger als Parameter z.B. VOID vec_add(VEC3 *v1, VEC3 *v2, VEC3 *result) Namenskonventionen - Sprechende Variablennamen verwenden, einbuchstabige Namen nur fuer Schleifen (bzw. gut kommentierte mathematische Formeln) - Variablennamen wie 'sehr_gut_lesbar' und nicht 'iCantReadThis' - kleinbuchstaben fuer Variablennamen, Funktionen und #define(...)-Macros - Grossbuchstaben fuer enum's, Typen, #define-Konstanten Codekonventionen - Endlosschleifen: forever {...} - if (...) und nicht if(...) - Keine unnoetig komplexen anweisungen wie z.B if ((x = (UCHAR *) malloc(100)) == NULL) statt dessen x = (UCHAR *) malloc(100); if (x == NULL) ausserdem ist dieser Code leichter zu debuggen !! - Strukturzuweisungen verwenden (ja, es gibt sie, und sie funktionieren :-) - bei Pointern nicht: if (x != 0) sondern: if (x != NULL) um's, Typen, #define-Konstanten Codekonventionen - Endlosschleifen: forever {...} - if (...) und nicht if(...) - Keine unnoetig komplexen anweisungen wie z.B if ((x = (UCHAR *) malloc(100)) == NULL) statt dessen x = (UCHAR *) malloc(100); Flirt/Doc/system.doc000644 000316 000311 00000046150 06114643123 014504 0ustar00wrzlgup000000 000000 ------------------------------------------------------------------------------- Aufbau von Flirt ------------------------------------------------------------------------------- Arten von Modulen: 1) Hauptprogramm & Raytracing 2) unterstuetzende Routinen 3) Szene,Camera,Lichtquellen 4) Materialmodelle 5) Textur 6) Objektmodule 1) Hauptprogramm & Raytracing flirt.c Hauptprogramm & Commandline-parsing sampling.c Sampling methoden & Strahlgenerierung init.c Aufruf der Initialisierungsfunktionen setup.c Aufruf der Setup-routinen raytrace.c Raytracing mit Reflexion & Transparenz 2) unterstuetzende Routinen bounding.c Hilfsroutinen fuer Boundingvolumina color.c Macros und Routinen fuer Farben geometr2.f Macros fuer 2d geometr3.c Macros und Routinen fuer 3d hitlist.c Verwaltung von Hitlists numeric.c Macros fuer Mathematikfunktionen und Gleichungsloeser parse.c Expressionparser & Expressionevaluation random.c Zufallszahlen raycount.c Statistik fuer Raytracing readdata.c Dateneingabe vom File rgbinout.c Bild- Ein/Ausgabe symbols.c Symbolverwaltung fuer Datenein/ausgabe system.c Low-level Interface zum OS, Speicherverwaltung, Zeitmessung writdata.c Datenausgabe auf File 3) Szene,Camera,Lichtquellen scene.c Szeneparameter camera.c Camera light.c Lichtquellen 4) Materialmodelle material.c Hauptmodul smplmat.c Einfaches Materialmodell stdmat.c Standard Materialmodell rissmat.c RISS-Materialmodell 5) Textur texture.c Texturfunktionen Hauptmodul 6) Objektmodule objects.c Objektfunktionen Hauptmodul und Defaultfunktionen csg.c CSG-Knoten named.c 'Named'-Objects repeat.c 'Repeated'-Objects grid.c Optimierungsknoten mit regelmaessigem Raumgitter select.c Grammatiknoten calculat.c Berechnungsknoten transfor.c Transformationsknoten cube.c Wuerfel sphere.c Kugel scube.c Achsenparalleler Wuerfel ssphere.c 'Achsenparallele' Kugel cylinder.c Zylinder cone.c Kegel parabol.c Paraboliod parsweep.c Parabel-Sweep hyperbol.c Hyperboloid hypsweep.c Hyperbel-Sweep torus.c Torus hyperell.c Hyperellipsoid plane.c Konvexes Polyeder polyeder.c Konvexes Polyeder triangle.c Dreieck (Phong) bspline.c Bezier/Bspline-Flaeche Hauptmodul bsplinit.c Bezier/Bspline-Flaeche Initialiserung bsplcalc.c Bezier/Bspline-Flaeche Berechnungen bsplepi.c Bezier/Bspline-Flaeche Epipedbaum ------------------------------------------------------------------------------- Objekte im FLIRT ------------------------------------------------------------------------------- Ein Objekt hat an und fuer sich nichts mit dem eigentlichen Raytracing zu tun. Es muss nur 'Methoden' zur Verfuegung stellen, die es dem Raytracer ermoeglichen alle benoetigten Informationen zu erhalten. Dabei kann es alle Prozeduren aus den unterstuetzenden Modulen verwenden, vor allem folgende Modulen: bounding, geometr2, geometr3, hitlist, numeric, readdata, system, writdata. Prinzipiell lassen sich die Objekte in 2 Klassen einteilen - Rekursivobjekte ('Organisations-Objekte') - Primitivobjekte ('echte Objekte') 1) Rekursivobjekte haben immer ein oder mehrere Nachfolgeobjekte, die sie rekursiv behandeln, und von deren Aufbau sie nichts (!) wissen. Sie dienen hauptsaechlich zur Kombination/Optimierung von Objekten. Sie bestimmen z.B. ob ein Nachfolgeobjekt ueberhaupt geschnitten werden muss, und geben eventuelle Schnitte unveraendert (Ausnahme: CSG) weiter an die aufrufende Prozedure zurueck. CSG-Operatoren: OR,AND,SUB dienen zum Bilden von Kombinationen von Primitivobjekten durch die CSG-Operatoren. 'Named'-Objects: Existieren zur Vereinfachung der Dateneingabe (z.B 'Haus' OR 'Garten') 'Repeated'-Objects Vervielfachen ein Objekt entlang eines Vektors Optimierungsobjekte (Grid,Octree,Shadow/Eye-Buffer,5D,Cylinder-Cube) dienen zur Optimierung der Strahl-Objektschnittes, indem der Objektraum und/oder der Strahlraum unterteilt wird. Grammatikknoten,Berechnungsknoten,Transformationsknoten dienen zur Definition von Objekten die durch Grammatiken beschrieben werden koennen (z.B. Pflanzen, Fraktale) 2) Primitivobjekte sind die 'echten' Objekte. Wuerfel,Kugel,Achsenparalleler Wuerfel (schneller Schnitt) 'Achsenparallele' Kugel (schneller Schnitt),Zylinder,Kegel Paraboliod,Parabel-Sweep,Hyperboloid,Hyperbel-Sweep,Torus Hyperellipsoid,Konvexes Polyeder,Dreieck (Phong) Bezier/Bspline-Flaeche,Sweep Sie erzeugen beim Schnitt die sogenannten Hitlist's, die eine Liste aller Schnitte des Strahls mit dem Objekt darstellt. ------------------------------------------------------------------------------- Objektmethoden ------------------------------------------------------------------------------- Jedes Objekt stellt Methoden zur Verfuegung, die lokal zum Objekt definiert sind (d.h. Static, Ausnahme init). Die Methoden werden von der init-Prozedur in die Methodenarrays eingetragen. Benoetigte Methoden fuer ein Objekt sind: - wie es Daten vom Eingabefile liest - wie es im Speicher kopiert wird - wie es auf ein Ausgabefile ausgegeben wird - wie es seine Begrenzungsvolumina initialisiert - wie es sich gegebenenfalls zusaetzliche Datenstrukturen aufbaut (z.B. fuer schnellere Schnittberechnungen) - wie es in Raumunterteilungen (Grid, Octree) eingeteilt wird - wie es feststellt ob ein Punkt innerhalb liegt - wie es eine Schnitt mit einem Strahl berechnet - wie es einen Normalvektor fuer einen Schnitt berechnet - wie es einen Normalvektor fuer einen Punkt auf der Oberflaeche berechnet - wie es Texturkoordinaten eines Schnitts berechnet - wie es Texturkoordinaten eines Punktes berechnet - wie es Schnittstatistiken ausgibt VOID init(VOID) Initialisiert die Methodenarrays, allokiert alle Datenstrukturen, die einmal pro Modul vorkommen (z.B. vorausberechnete Tabellen) In nameobj[] wird ein Zeiger auf einen String, der den Namen des Objekts enthaelt eingetragen. In surfaces[] wird die Anzahl der Oberflaechen eingetragen. Falls diese erst zu Laufzeit bestimmt werden kann ist 0L einzutragen. OBJECT *read(VOID) wird aufgerufen um ein Objekt vom Datenfile zu lesen. legt das memory fuer das Objekt selbst mit newonly* an. liest die Parameter vom File validiert die Parameter setzt die Variablen des Objekts (auch den Typ). Rekursivobjekte lesen die weiteren Objekte mit '?? = readobjects()'. gibt einen Pointer auf das Objekt zurueck. OBJECT *copy(OBJECT *obj,BOOLEAN recurse,MAT3 *obj2world,MAT3 *world2obj, MATERIAL *mat,TEXTURE *tex) Kopiert ein Objekt (wird fuer benannte Objekte verwendet. falls 'obj2world' && 'world2obj' != NULL wird es zusaetzlich transformiert falls 'mat' != NULL wird das Material ueberschrieben. falls 'tex' != NULL wird die Textur ueberschrieben. Rekursivobjekte kopieren bei 'recurse' = TRUE weiter mit: 'copyobj[obj->??->typ](??,TRUE,obj2world,world2obj,mat,tex)' Fuer Objekte ohne zusaetzliche Parameter kann 'copysobj', Fuer Objekte mit einem zusaetzliche Parameter (FLOAT) kann 'copypobj', verwendet werden. gibt einen Pointer auf das neue Objekt zurueck. VOID write(OBJECT *obj) wird aufgerufen um ein Objekt auf ein File zu schreiben. schreibt genau dasselbe format das read lesen kann. Fuer Objekte ohne zusaetzliche Parameter kann 'writesobj', Fuer Objekte mit einem zusaetzliche Parameter (FLOAT) kann 'writepobj', verwendet werden. Rekursivobjekte schreiben die weiteren Objekte mit 'writeobjects(??)'. VOID bound(OBJECT *obj) Das Objekt initialisiert seine Begrenzungsvolumina. obj->text_bbox wird auf BOUNDTEST_ALL oder BOUNDTEST_NONE gesetzt. obj->test_bsphere wird auf FALSE oder TRUE gesetzt. obj->bounds wird auf NULL gesetzt. Rekursivobjekte: 'boundobj[??->typ](??)' ULONG setup(OBJECT *obj,BOOLEAN in_or_tree,BOOLEAN space_opt) Hier werden die restlichen Initialisierungen pro Objekt durchgefuerht. z.B wird hier eine adaptive Unterteilung angelegt. Datenstrukturen, die hier angelegt werden, sollen bei end wieder freigegeben werden, also kein newonly* sonder new* Liefert die Anzahl der Objekte zurueck (fuer Primitivobjekte = 1L) 'in_or_tree' ist true wenn sich das Objekt im obersten OR-Baum befindet. 'space_opt' ist true wenn sich das Objekt in einem Optimierungsknoten (Grid,Octree,...) befindet. Fuer Primitivobjekte kann 'setup_primitv' verwendet werden. Rekursivobjekte: '?? = setupobjects(??,in_or_tree,space_opt)' OBJECT * split(OBJECT *obj,VOIDPTR bound_volume, UINT (*bv_test)(OBJECT *obj,VOIDPTR bound_volume), BOOLEAN *changed,ULONG *number_of_objects); Wenn *changed false ist wird nur mit einem Aufruf von bv_test(obj,boundvolume) festgestellt wieviele Objekte mit dem bound_volume schneiden oder innerhalb sind. bv_test gibt 0 fuer keine Ueberschneidung, 1 fuer Ueberschneidung und 2 fuer innerhalb zurueck. Rueckgabewert ist 'number_of_objects', und der Zeiger auf das Objekt. Wenn *changed true ist wird wie oben getestet ob das Objekt mit dem bound_volume schneidet. Zusaetzlich wird der Knoten bei Bedarf kopiert (Rueckgabewert: Zeiger auf diesen Knoten, und *changed = true) sonst wird das objekt zurueckgegeben und *changed = false. Fuer Primitivobjekte kann 'split_primitv' verwendet werden. Rekursivobjekte: '?? = splitobj[??->typ](??,bound_vol,bv_test,??,??)' OBJECT *inside(PNT3 *pnt, OBJECT *obj) testet, ob sich ein Punkt innerhalb des Objekts befindet. der Macro 'INSIDE_BOUND_TEST(obj,pnt)' erledigt das Testen des Punktes gegenueber dem Umgebunvolumen Rekursivobjekte: ?? = inside[??->typ](pnt,??); Liefert entweder NULL oder eine Pointer auf das Objekt zurueck BOOLEAN hit(FLOAT tmin, FLOAT tmax,OBJECT *obj,HITLIST *hitlist) Schneidet eine Strahl mit dem Objekt. der Strahl ist durch 'rci.ray' gegeben. Gibt true zurueck, wenn im Intervall tmin-tmax ein Schnitt festgestellt werden kann. Der Schnitt mit den Boundingvolumina ist bereits erledigt und muss nicht mehr gemacht werden. Die Hitliste 'hitlist' ist bereits vorinitialisiert (eine leere Liste) und es muessen die Hitinfos eingetragen werden. Objekte geben alle hits im Intervall tmin/tmax zurueck, es muessen aber immer mindestens ein IN und ein OUT Schnittpunkt existieren (sie koennen aber ausserhalb des t-Intervalls liegen) PRE_OBJECT ist als erstes in der Prozedur aufzurufen POST_OBJECT ist als letztes in der Prozedur aufzurufen, wenn wirklich ein Treffer vorlag ! also vor returnhitlist aber nach prepare2(4)hits. Folgende Makros vereinfachen dabei viel: checkaddmin/max fuer early-exits bei Objekten, die durch ebene Flaechen begrenzt sind, makerayhit/makehit fuer das erzeugen von Hitinfos, checkmakerayhit/checkmakehit fuer das erzeugen von Hitinfos, prepare2hits/prepare4hits fuer die restlichen Initialisierungen der Hits returnhitlist fuer Rueckgabe der Hitlist. Folgende Variable der Hitinfos muessen initialisiert werden: 't' - Strahlparameter 'face' - Oberflaechennummer 'obj' - das geometrisch getroffenen Objekt ('Oberflaeche') 'newobj' - das getroffene Objekt ('neues Material') 'ray' - Strahl (inv_dir kann zum Speichern von Werten verwendt werden) Normalerweise wird ein Primitivobjekt 'obj' = 'newobj' setzen. Folgende Variable der Hitinfos sind optional zu initialisieren (falls die Werte als Nebenprodukt des Schnittes entstehen) 'normal' - Normalvektor 'uv' - Oberflaechenparameter 'local_point' - Schnittpunkt im lokalen Koordinatensystem 'local_normal' - Normalvektor im lokalen Koordinatensystem Nur fuer Rekursivobjekte: diese Objekte fuehren die Boundingvolume- tests durch: if (! HIT_BOUNDS(??,rci.ray,tmin,tmax)) return FALSE; hitobj[??->typ](tmin,tmax,??,hitlist) VOID normal(HITINFO *hitinfo) Wird nur fuer Primitivobjekte aufgerufen. Zu dem Hit wird der Normalvektor berechnet, falls er schon von hit() berechnet wurde, passiert nichts, und in 'hitinfo->normal' eingetragen. ('Nebenprodukte' wieder in hitinfo speichern !) VOID pntnorm(*PNTNORMFUN)(OBJECT *obj,ULONG surface,PNT2 *point, PNT3 *world,VEC3 *normal) Wird nur fuer Primitivobjekte aufgerufen. Fuer das Objekt 'obj' und dem Punkt 'point' (= u-v-Koordinaten) auf der Oberflaeche 'surface' sind folgende Daten zurueckzugeben: 'world' der entsprechende Punkt im Weltkoordinatensystem und 'normal', der Normalvektor in diesem Punkt (ebenfalls Weltkoordinatensystem). FIXME: EXPERIMENTELL ! VOID hitcoord(HITINFO *hit,GEOMPAR needed) Wird nur fuer Primitivobjekte aufgerufen. im Parameter 'needed' wird uebergeben welche parameter zurueckzugeben sind: 'texinfo.face' wird gesetzt. if (needed & LOCALPNT) - der Punkt im lokalen Koordinatensystem wird in 'texinfo.localpnt' eingetragen. if (needed & GEOM_2DCOORD) - die Koordinaten des Oberflaechenpunktes werden in 'texinfo.pnt2[0]' eingetragen. (texinfo.num2 = 1) if (needed & GEOM_1DCOORD) - eine charakteristische Koordinaten des Objekts wird in 'texinfo.pnt1[0]' eingetragen. (texinfo.num1 = 1) z.B. die z-Koordinate im lokalen Koordinatensystem. FIXME: EXPERIMENTELL ! BOOLEAN pntcoord(OBJECT *obj,GEOMPAR needed) Wird nur fuer Primitivobjekte aufgerufen. Analog zu hitcoord nur wird der Punkt 'texinfo.worldpnt', der im allgemeinen nicht auf der Oberflaeche liegt, wird auf die Oberflaeche gemappt und wie bei hitcoord zurueckgegeben. falls kein entsprechender Punkt ermittelt werden kann (z.B. fuer Bezierflaechen) ist FALSE zurueckzugeben FIXME: EXPERIMENTELL ! VOID end(OBJECT *obj) Gibt den Speicher, der zusaetzlich fuer das Objekt (also nicht mit newonly*) angelegt wurde wieder frei. Gibt optinal die Statistik des Objekts aus. (z.B. durchscnittliche Zeit pro Schnitt ...) fuer Primitivobjekte kann 'end_primitv' verwendet werden. Rekursivobjekte: 'endobj[??->typ](??)' VOID exit(VOID) Gibt den Speicher, der zusaetzlich fuer das Modulangelegt wurde wieder frei. Gibt optinal die Statistik des Moduls aus (z.B. wieviel Zeit in den Schnittprozeduren dieses Objekts verbrauct wurde...). ------------------------------------------------------------------------------- Die Aufrufe der Prozeduren geschehen in der folgenden Reihenfolge: 1) Alle inits werden einmal aufgerufen (pro Modul). 2) Alle reads und (durch namedobjects) die copys werden fuer die Objekte im Datenfile aufgerufen. 3) Der Objektbaum wird mit bound abgearbeitet. 4) Der Objektbaum wird mit setup abgearbeitet. dabei werden die split prozeduren aufgerufen. Schritte 5-7 finden fuer jeden Strahl statt. 5) Der Objektbaum wird mit hit mit einem Strahl geschnitten. 6) Fuer einen oder mehrere dieser hit's wird normal aufgerufen 7) Fuer einen oder mehrere dieser hit's wird hitcoord und pntcoord aufgerufen. 8) Der Objektbaum wird mit end abgearbeitet. 9) Alle exits werden einmal aufgerufen (pro Modul). Nach 2) kann jederzeit write aufgerufen werden. Pntnorm wird derzeit nicht benuetzt, sollte aber trotzdem definiert werden. ------------------------------------------------------------------------------- Beispiel fuer ein Objekt: cylinder.c ------------------------------------------------------------------------------- Der Zylinder ist wie folgt definiert: Steht im Ursprung Radius = 1, Hoehe = 1. Transformationen werden durch eine Transformationsmatrix definiert. readcylinder: legt den Speicherplatz fuer das einzulesende Objekt an liest die Transformationsmatrix ein liest Material und Textur ein copysobj: Als copy-Funktion wird eine Defaultfunktion aus dem objects.c verwendet. Sie legt den Speicherplatz fuer die Kopie an, kopiert die Objektdaten, veraendert eventuell Material und Texture und aendert die Transformationsmatrix writesobj: Als write-Funktion wird eine Defaultfunktion aus dem objects.c verwendet. Sie gibt die Transformationsmatrix, das Material und die Texture aus. boundcylinder: Berechnet die Boundingbox und die Boundingsphere fuer den Zylinder unter Beruecksichtigung der Transformationsmatrix. setup_primitiv: Als setup-Funktion wird eine Defaultfunktion aus dem objects.c verwendet. Diese gibt nur die Anzahl der Objekte (1) zurueck. split_primitiv: Als split-Funktion wird eine Defaultfunktion aus dem objects.c verwendet. Testet ob das Objekt mit dem angegebenen Bounding- volumen schneidet bzw innerhalb liegt. insidecylinder: Testet ob der Punkt innerhalb der Boundingvolumes liegt. Transformiert den Punkt in das lokale Koordinatensystem. Testet ob der Punkt innerhalb des 'Original'-Zylinders liegt. hitcylinder: Transformiert den Strahl in das lokale Koordinatensystem. Wenn der Strahl parallel zur Zylinderachse verlaeuft ist ein einfacher Test moeglich ! Ansonsten wird der Strahl mit einem unendlich langen Zylinder geschnitten und die Schnitte in tmin,tmax eingetragen. Danach wird der Strahl noch mit der x/y-Ebene und der x/y/z=1-Ebene geschnitten und gegebenenfalls das tmin/tmax- Intervall verkleinert. Mit checkmakerayhit werden die hit's erzeugt und mit prepare2hits zu einer Hitlist zusammengehaengt. normcylinder: Wenn der Schnitt am Mantel lag (face == 1) wird der schnittpunkt im lokalen koordinatensystem berechnet, daraus der NV berechnet. Sonst wird ein vorausberechneter NV verwendet. Der Normalvektor wird in das globale koordinatensystem transformiert und dann normalisiert. pntnormcylinder: FIXME: hitcoordcylinder: FIXME: pntcoordcylinder: FIXME: endcylinder: Als end-Funktion wird eine Defaultfunktion aus dem objects.c verwendet. exitcylinder: Da nichts zu tun ist, ist dies Funktion nicht definiert. initcylinder: Initialiuser die Methodenarrays. rechnet. Sonst wird ein vorausberechneter NV verwendet. Der Normalvektor wird in das globale koordinatensystem transformiert und dann normalisiert. pntnormcylinder: FIXME: hitcoordcylinder: FIXME: pntcoordcylinder: FIXME: endcylinder: Als end-Funktion wird eine Defaultfunktion aus dem objects.c verwendet. exitcylinder: Da nichts Flirt/Ftl/000755 000316 000311 00000000000 06114645232 012506 5ustar00wrzlgup000000 000000 Flirt/Ftl/ambient.ftl000644 000316 000311 00000003545 06114644632 014646 0ustar00wrzlgup000000 000000 % primitive testszene global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 3.0 5.0 lights local typ ambient color 1.0 1.0 1.0 end #include platonic.dat object local typ csg_or typ csg_or typ csg_or typ named object tetraeder transform rotz 30.0 rotx 12.0 trans -2.0 2.0 0.0 material rot typ named object hexaeder transform rotz 30.0 rotx 12.0 trans -2.0 -2.0 0.0 material gold typ csg_or typ named object dodecaeder transform rotz 30.0 rotx 12.0 trans 2.0 -2.0 0.0 material blau typ named object icosaeder transform rotz 30.0 rotx 12.0 trans 2.0 2.0 0.0 material violett typ named object octaeder transform rotz 30.0 rotx 12.0 trans 0.0 -4.0 1.0 material gruen end #include material.dat typ named object icosaeder transform rotz 30.0 rotxFlirt/Ftl/ant.ftl000644 000316 000311 00000002444 06114644632 014006 0ustar00wrzlgup000000 000000 % testscene for cone global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object local % typ csg_or typ csg_or typ csg_or typ sphere transform scale 1.0 0.5 0.5 trans -0.5 0.0 0.0 material rot typ sphere transform scale 0.25 0.25 0.25 trans 0.125 0.0 0.0 material rot % typ csg_or typ sphere transform scale 0.5 0.5 0.5 trans 0.5 0.0 0.0 material rot end #include material.dat -0.5 0.0 0.0 material rot typ sphere transform scale 0.25 0.25 0.25 trans 0.125 0.0 0.0 Flirt/Ftl/arealight.ftl000644 000316 000311 00000005754 06114644632 015173 0ustar00wrzlgup000000 000000 global scene smallmidpoint camera stest lights stest object s3test material air background 0.88 0.85 0.9 scene smallmidpoint xpix 128 ypix 96 shadow_rays true texturing false max_reflection 10 max_refraction 10 min_contribution 0 % 0.01 sampling midpoint camera stest eye -10.0 -10.0 10.0 zoom 0.5 % eye 0.0 0.0 10.0 % direction 0.0 0.0 -10.0 % zoom 0.1 lights stest % typ disklight % position 5.0 5.0 20.0 % direction 0.0 0.0 0.0 % accurancy 23 % radius 8.4 % color 0.99 0.83 0.9 % typ disklight % position 5.0 7.0 8.0 % direction 1.0 1.0 1.0 % accurancy 23 % radius 3.5 % color 0.5 0.3 0.4 % typ pointlight % position 0.0 0.0 1.1 % color 0.99 0.99 0.99 % typ disklight % position -0.1 -2.92 0.0 % direction 0.1 2.92 0.0 % accuracy 10 % radius 0.8 % color 0.99 0.99 0.99 typ disklight position 0.0 0.0 5 direction 0.0 0.0 -1.0 accuracy 10 radius 5.0 color 0.99 0.99 0.99 % typ triangularlight % accuracy 10 % points 3.0 -3.0 4.1 % -3.0 -3.0 4.1 % 3.0 3.0 4.1 % color 0.99 0.99 0.99 % typ spherelight % position 0.0 0.0 5.0 % accuracy 5 % radius 2 % color 0.99 0.99 0.99 end object s3test typ csg_or typ cube transform scale 20.0 20.0 1.0 trans -10.0 -10.0 0.0 material weinrotmatt typ cube min 0.0 0.0 2.5 max 10.0 10.0 2.51 material schwarz end object s2test typ csg_or typ csg_or typ sphere center -1.0 -1.0 -1.0 radius 1.0 material weinrotmatt typ cube transform scale 1.0 1.0 1.5 trans 0.0 0.1 0.3 material spiegel typ csg_or typ torus radius 1.2 material glas typ cube transform scale 1.0 0.5 0.5 trans -0.5 -0.5 0.3 material glasgruen end #include material.dat dius 1.0 Flirt/Ftl/blatt.ftl000644 000316 000311 00000001613 06114644632 014327 0ustar00wrzlgup000000 000000 % primitive testszene global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object local typ csg_sub typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material gold typ sphere center 0.0 0.0 0.5 radius 0.65 material gold end #include material.dat 0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 Flirt/Ftl/bowl.ftl000644 000316 000311 00000002560 06114644632 014166 0ustar00wrzlgup000000 000000 % a bowl global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 10.0 6.0 10.0 lights local typ pointlight position -32.0 -8.0 32.0 color 1.0 1.0 1.0 typ pointlight position -32.0 8.0 32.0 color 0.7 0.7 0.8 end object local typ csg_or typ csg_and typ csg_sub typ sphere center 0.0 0.0 4.0 radius 4.0 material gold typ sphere center 0.0 0.0 4.0 radius 3.0 material gold typ cube min -4.1 -4.1 -0.1 max 4.1 4.1 4.0 material gold typ cylinder transform scale 5.0 5.0 6.0 trans 0.0 0.0 -1.0 material glas end #include material.dat sphere center 0.0 0.0 4.0 radius 3.0 material gold Flirt/Ftl/bsptest.ftl000644 000316 000311 00000001573 06114644632 014712 0ustar00wrzlgup000000 000000 global scene smallmidpoint camera stest lights stest object stest material air background 0.48 0.6 0.9 #include scenes.dat camera stest eye 5.0 5.0 5.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest % typ csg_or % typ sphere % center 0.0 0.0 -0.5 % radius 0.5 % material gold typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material rot end #include material.dat 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7Flirt/Ftl/bwt_.ftl000644 000316 000311 00000001766 06114644632 014165 0ustar00wrzlgup000000 000000 global % scene adaptive scene smallmidpoint camera stest lights stest object stest material air % background 0.48 0.6 0.9 background 1 1 1 #include scenes.dat camera stest eye 5.0 5.0 5.0 direction -5.0 -5.0 -5.0 zoom 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ sphere center 0.0 0.0 -0.5 radius 0.5 material gold typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material rot end #include material.dat olor Flirt/Ftl/bwta.ftl000644 000316 000311 00000001770 06114644632 014162 0ustar00wrzlgup000000 000000 global % scene adaptive scene smallmidpoint camera stest lights stest object stest material air % background 0.48 0.6 0.9 background 1 1 1 #include scenes.dat camera stest eye 5.0 5.0 5.0 direction -5.0 -5.0 -5.0 zoom 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ sphere center 0.15 0.0 -0.5 radius 0.5 material gold typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material rot end #include material.dat lor Flirt/Ftl/bwtb.ftl000644 000316 000311 00000001766 06114644632 014170 0ustar00wrzlgup000000 000000 global % scene adaptive scene smallmidpoint camera stest lights stest object stest material air % background 0.48 0.6 0.9 background 1 1 1 #include scenes.dat camera stest eye 5.0 5.0 5.0 direction -5.0 -5.0 -5.0 zoom 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ sphere center 0.0 0.0 -0.5 radius 0.5 material gold typ cube min -0.3 -0.5 0.0 max 0.7 0.5 1.0 material rot end #include material.dat olor Flirt/Ftl/cone.ftl000644 000316 000311 00000001242 06114644632 014143 0ustar00wrzlgup000000 000000 % testscene for cone global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object local typ cone transform rotx 180 material rot end #include material.dat ir background 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color Flirt/Ftl/cyclube1.ftl000644 000316 000311 00000013001 06114644632 014722 0ustar00wrzlgup000000 000000 % :-) % a 2-dimensional picture of % a 3-dimensional projection of % a 4-dimensional hypercube global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 8.0 -24.0 16.0 lights local typ pointlight position 16.0 -16.0 16.0 color 1.0 1.0 1.0 typ pointlight position -16.0 16.0 16.0 color 1.0 1.0 1.0 end object verbind typ cube % min -0.2 -0.2 0.0 % max 0.2 0.2 2.0 min -0.1 -0.1 0.0 max 0.1 0.1 2.0 material rot end object stab typ csg_or typ sphere center 0.0 0.0 0.0 % radius 0.5 radius 0.2 material gold typ named object verbind end object halbrahmen typ csg_or typ named object stab typ named object stab transform roty 90.0 trans 0.0 0.0 2.0 end object rahmen typ csg_or typ named object halbrahmen typ named object halbrahmen transform roty 180.0 trans 2.0 0.0 2.0 end object wuerfel typ csg_or typ csg_or typ named object rahmen typ named object rahmen transform trans 0.0 2.0 0.0 typ csg_or typ csg_or typ named object verbind transform rotx -90.0 typ named object verbind transform rotx -90.0 trans 0.0 0.0 2.0 typ csg_or typ named object verbind transform rotx -90.0 trans 2.0 0.0 0.0 typ named object verbind transform rotx -90.0 trans 2.0 0.0 2.0 end object wuerfel4d typ csg_or typ csg_or typ named object wuerfel typ named object wuerfel transform trans 1.0 1.0 1.0 typ csg_or typ csg_or typ csg_or typ named object verbind transform rotx -54.74 rotz -45.0 typ named object verbind transform rotx -54.74 rotz -45.0 trans 0.0 0.0 2.0 typ csg_or typ named object verbind transform rotx -54.74 rotz -45.0 trans 2.0 0.0 0.0 typ named object verbind transform rotx -54.74 rotz -45.0 trans 2.0 0.0 2.0 typ csg_or typ csg_or typ named object verbind transform rotx -54.74 rotz -45.0 trans 0.0 2.0 0.0 typ named object verbind transform rotx -54.74 rotz -45.0 trans 0.0 2.0 2.0 typ csg_or typ named object verbind transform rotx -54.74 rotz -45.0 trans 2.0 2.0 0.0 typ named object verbind transform rotx -54.74 rotz -45.0 trans 2.0 2.0 2.0 end object local typ cylcube subdivisions 3 % typ csg_or % typ sphere % center -5.0 0.0 0.0 % radius 2.0 % material rot typ named % object wuerfel4d object wuerfel transform trans -2.0 0.0 -1.0 scale 4.0 4.0 4.0 end #include material.dat rotz -45.0 trans 2.0 2.0 2.0 end object local typ cylcube subdivisions 3 % typ csg_or % typ sphere % center -5.0 0.0 0.0 % radius 2.0 % material rot typ named % object wuerfel4d object wuerfel transform trans -2.0 0.0 -1.0 scale 4.0 4.0 4.0 end #include material.dat Flirt/Ftl/diamond.ftl000644 000316 000311 00000042267 06114644632 014646 0ustar00wrzlgup000000 000000 % a diamond, what else ? global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 20.0 11.0 15.0 zoom 2.0 lights local typ pointlight position -8.0 8.0 4.0 color 1.0 1.0 1.0 typ pointlight position -1.0 -9.0 3.0 color 1.0 1.0 1.0 end points diamond number 41 0.000000 0.000000 0.010000 % 0,0 0.347573 0.000000 0.531418 % 1,1 0.371364 0.153824 0.515849 % 2,1 0.500000 0.000000 0.431672 % 3,1 0.461940 0.191342 0.431672 % 4,1 0.329241 0.136376 0.284258 % 5,1 0.245771 0.245771 0.531418 % 1,2 0.153824 0.371364 0.515849 % 2,2 0.353553 0.353553 0.431672 % 3,2 0.191342 0.461940 0.431672 % 4,2 0.136376 0.329241 0.284258 % 5,2 0.000000 0.347573 0.531418 % 1,3 -0.153824 0.371364 0.515849 % 2,3 0.000000 0.500000 0.431672 % 3,3 -0.191342 0.461940 0.431672 % 4,3 -0.136376 0.329241 0.284258 % 5,3 -0.245771 0.245771 0.531418 % 1,4 -0.371364 0.153824 0.515849 % 2,4 -0.353553 0.353553 0.431672 % 3,4 -0.461940 0.191342 0.431672 % 4,4 -0.329241 0.136376 0.284258 % 5,4 -0.347573 0.000000 0.531418 % 1,5 -0.371364 -0.153824 0.515849 % 2,5 -0.500000 0.000000 0.431672 % 3,5 -0.461940 -0.191342 0.431672 % 4,5 -0.329241 -0.136376 0.284258 % 5,5 -0.245771 -0.245771 0.531418 % 1,6 -0.153824 -0.371364 0.515849 % 2,6 -0.353553 -0.353553 0.431672 % 3,6 -0.191342 -0.461940 0.431672 % 4,6 -0.136376 -0.329241 0.284258 % 5,6 -0.000000 -0.347573 0.531418 % 1,7 0.153824 -0.371364 0.515849 % 2,7 -0.000000 -0.500000 0.431672 % 3,7 0.191342 -0.461940 0.431672 % 4,7 0.136376 -0.329241 0.284258 % 5,7 0.245771 -0.245771 0.531418 % 1,8 0.371364 -0.153824 0.515849 % 2,8 0.353553 -0.353553 0.431672 % 3,8 0.461940 -0.191342 0.431672 % 4,8 0.329241 -0.136376 0.284258 % 5,8 object diamond typ csg_and typ cylinder transform scale 0.49039 0.49039 0.532 material default typ planes points diamond number 57 %1 plane 7 2 12 % 17 22 27 32 37 % A top upper plane %2 plane 3 2 7 % B top upper triangle plane 8 7 12 % B top upper triangle plane 13 12 17 % B top upper triangle plane 18 17 22 % B top upper triangle plane 23 22 27 % B top upper triangle plane 28 27 32 % B top upper triangle plane 33 32 37 % B top upper triangle plane 38 37 2 % B top upper triangle %10 plane 2 4 38 % 3 % C top quadrilateral plane 7 9 3 % 8 % C top quadrilateral plane 12 14 8 % 13 % C top quadrilateral plane 17 19 13 % 18 % C top quadrilateral plane 22 24 18 % 23 % C top quadrilateral plane 27 29 23 % 28 % C top quadrilateral plane 32 34 28 % 33 % C top quadrilateral plane 37 39 33 % 38 % C top quadrilateral %18 plane 4 3 5 % D1 top lower triangle plane 9 8 10 % D1 top lower triangle plane 14 13 15 % D1 top lower triangle plane 19 18 20 % D1 top lower triangle plane 24 23 25 % D1 top lower triangle plane 29 28 30 % D1 top lower triangle plane 34 33 35 % D1 top lower triangle plane 39 38 40 % D1 top lower triangle %26 plane 5 3 9 % D2 top lower triangle plane 10 8 14 % D2 top lower triangle plane 15 13 19 % D2 top lower triangle plane 20 18 24 % D2 top lower triangle plane 25 23 29 % D2 top lower triangle plane 30 28 34 % D2 top lower triangle plane 35 33 39 % D2 top lower triangle plane 40 38 4 % D2 top lower triangle %34 plane 4 5 6 % E1 bottom triangle plane 9 10 11 % E1 bottom triangle plane 14 15 16 % E1 bottom triangle plane 19 20 21 % E1 bottom triangle plane 24 25 26 % E1 bottom triangle plane 29 30 31 % E1 bottom triangle plane 34 35 36 % E1 bottom triangle plane 39 40 41 % E1 bottom triangle %42 plane 5 9 6 % E2 bottom triangle plane 10 14 11 % E2 bottom triangle plane 15 19 16 % E2 bottom triangle plane 20 24 21 % E2 bottom triangle plane 25 29 26 % E2 bottom triangle plane 30 34 31 % E2 bottom triangle plane 35 39 36 % E2 bottom triangle plane 40 4 41 % E2 bottom triangle %50 plane 4 6 41 % 1 % F bottom quadrilateral plane 9 11 6 % 1 % F bottom quadrilateral plane 14 16 11 % 1 % F bottom quadrilateral plane 19 21 16 % 1 % F bottom quadrilateral plane 24 26 21 % 1 % F bottom quadrilateral plane 29 31 26 % 1 % F bottom quadrilateral plane 34 36 31 % 1 % F bottom quadrilateral plane 39 41 36 % 1 % F bottom quadrilateral material default end object local typ csg_or typ named object diamond transform scale 4.0 4.0 4.0 trans 0.0 0.0 0.1 material diamond % the sixty-four fields typ csg_or typ csg_or typ csg_or typ csg_or typ csg_or typ csg_or typ cube min -8.0 -8.0 -0.5 max -6.0 -6.0 0.0 material gold typ cube min -6.0 -8.0 -0.5 max -4.0 -6.0 0.0 material rot typ csg_or typ cube min -8.0 -6.0 -0.5 max -6.0 -4.0 0.0 material rot typ cube min -6.0 -6.0 -0.5 max -4.0 -4.0 0.0 material gold typ csg_or typ csg_or typ cube min -4.0 -8.0 -0.5 max -2.0 -6.0 0.0 material gold typ cube min -2.0 -8.0 -0.5 max 0.0 -6.0 0.0 material rot typ csg_or typ cube min -4.0 -6.0 -0.5 max -2.0 -4.0 0.0 material rot typ cube min -2.0 -6.0 -0.5 max 0.0 -4.0 0.0 material gold typ csg_or typ csg_or typ csg_or typ cube min -8.0 -4.0 -0.5 max -6.0 -2.0 0.0 material gold typ cube min -6.0 -4.0 -0.5 max -4.0 -2.0 0.0 material rot typ csg_or typ cube min -8.0 -2.0 -0.5 max -6.0 0.0 0.0 material rot typ cube min -6.0 -2.0 -0.5 max -4.0 0.0 0.0 material gold typ csg_or typ csg_or typ cube min -4.0 -4.0 -0.5 max -2.0 -2.0 0.0 material gold typ cube min -2.0 -4.0 -0.5 max 0.0 -2.0 0.0 material rot typ csg_or typ cube min -4.0 -2.0 -0.5 max -2.0 0.0 0.0 material rot typ cube min -2.0 -2.0 -0.5 max 0.0 0.0 0.0 material gold typ csg_or typ csg_or typ csg_or typ csg_or typ cube min 0.0 -8.0 -0.5 max 2.0 -6.0 0.0 material gold typ cube min 2.0 -8.0 -0.5 max 4.0 -6.0 0.0 material rot typ csg_or typ cube min 0.0 -6.0 -0.5 max 2.0 -4.0 0.0 material rot typ cube min 2.0 -6.0 -0.5 max 4.0 -4.0 0.0 material gold typ csg_or typ csg_or typ cube min 4.0 -8.0 -0.5 max 6.0 -6.0 0.0 material gold typ cube min 6.0 -8.0 -0.5 max 8.0 -6.0 0.0 material rot typ csg_or typ cube min 4.0 -6.0 -0.5 max 6.0 -4.0 0.0 material rot typ cube min 6.0 -6.0 -0.5 max 8.0 -4.0 0.0 material gold typ csg_or typ csg_or typ csg_or typ cube min 0.0 -4.0 -0.5 max 2.0 -2.0 0.0 material gold typ cube min 2.0 -4.0 -0.5 max 4.0 -2.0 0.0 material rot typ csg_or typ cube min 0.0 -2.0 -0.5 max 2.0 0.0 0.0 material rot typ cube min 2.0 -2.0 -0.5 max 4.0 0.0 0.0 material gold typ csg_or typ csg_or typ cube min 4.0 -4.0 -0.5 max 6.0 -2.0 0.0 material gold typ cube min 6.0 -4.0 -0.5 max 8.0 -2.0 0.0 material rot typ csg_or typ cube min 4.0 -2.0 -0.5 max 6.0 0.0 0.0 material rot typ cube min 6.0 -2.0 -0.5 max 8.0 0.0 0.0 material gold typ csg_or typ csg_or typ csg_or typ csg_or typ csg_or typ cube min -8.0 0.0 -0.5 max -6.0 2.0 0.0 material gold typ cube min -6.0 0.0 -0.5 max -4.0 2.0 0.0 material rot typ csg_or typ cube min -8.0 2.0 -0.5 max -6.0 4.0 0.0 material rot typ cube min -6.0 2.0 -0.5 max -4.0 4.0 0.0 material gold typ csg_or typ csg_or typ cube min -4.0 0.0 -0.5 max -2.0 2.0 0.0 material gold typ cube min -2.0 0.0 -0.5 max 0.0 2.0 0.0 material rot typ csg_or typ cube min -4.0 2.0 -0.5 max -2.0 4.0 0.0 material rot typ cube min -2.0 2.0 -0.5 max 0.0 4.0 0.0 material gold typ csg_or typ csg_or typ csg_or typ cube min -8.0 4.0 -0.5 max -6.0 6.0 0.0 material gold typ cube min -6.0 4.0 -0.5 max -4.0 6.0 0.0 material rot typ csg_or typ cube min -8.0 6.0 -0.5 max -6.0 8.0 0.0 material rot typ cube min -6.0 6.0 -0.5 max -4.0 8.0 0.0 material gold typ csg_or typ csg_or typ cube min -4.0 4.0 -0.5 max -2.0 6.0 0.0 material gold typ cube min -2.0 4.0 -0.5 max 0.0 6.0 0.0 material rot typ csg_or typ cube min -4.0 6.0 -0.5 max -2.0 8.0 0.0 material rot typ cube min -2.0 6.0 -0.5 max 0.0 8.0 0.0 material gold typ csg_or typ csg_or typ csg_or typ csg_or typ cube min 0.0 0.0 -0.5 max 2.0 2.0 0.0 material gold typ cube min 2.0 0.0 -0.5 max 4.0 2.0 0.0 material rot typ csg_or typ cube min 0.0 2.0 -0.5 max 2.0 4.0 0.0 material rot typ cube min 2.0 2.0 -0.5 max 4.0 4.0 0.0 material gold typ csg_or typ csg_or typ cube min 4.0 0.0 -0.5 max 6.0 2.0 0.0 material gold typ cube min 6.0 0.0 -0.5 max 8.0 2.0 0.0 material rot typ csg_or typ cube min 4.0 2.0 -0.5 max 6.0 4.0 0.0 material rot typ cube min 6.0 2.0 -0.5 max 8.0 4.0 0.0 material gold typ csg_or typ csg_or typ csg_or typ cube min 0.0 4.0 -0.5 max 2.0 6.0 0.0 material gold typ cube min 2.0 4.0 -0.5 max 4.0 6.0 0.0 material rot typ csg_or typ cube min 0.0 6.0 -0.5 max 2.0 8.0 0.0 material rot typ cube min 2.0 6.0 -0.5 max 4.0 8.0 0.0 material gold typ csg_or typ csg_or typ cube min 4.0 4.0 -0.5 max 6.0 6.0 0.0 material gold typ cube min 6.0 4.0 -0.5 max 8.0 6.0 0.0 material rot typ csg_or typ cube min 4.0 6.0 -0.5 max 6.0 8.0 0.0 material rot typ cube min 6.0 6.0 -0.5 max 8.0 8.0 0.0 material gold end #include material.dat max 6.0 6.0 0.0 material gold typ cube min 6.0 4.0 -0.5 max 8.0 6.0 0.0 material rot typ csg_or typ cube min 4.0 6.0 -0.5 max 6.0 8.0 0.0 Flirt/Ftl/edditest.ftl000644 000316 000311 00000001522 06114644632 015025 0ustar00wrzlgup000000 000000 global scene smallmidpoint camera stest lights stest object stest material air background 0.48 0.6 0.9 #include scenes.dat camera stest eye 5.0 5.0 5.0 direction -5.0 -5.0 -5.0 zoom 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ cylinder material glas typ cube min -0.5 -0.5 -0.5 max 0.5 0.5 0.5 material gold end #include material.dat ights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight poFlirt/Ftl/glascube.ftl000644 000316 000311 00000025403 06114644633 015012 0ustar00wrzlgup000000 000000 % a glasscube upon a chessboard global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 8.0 -24.0 16.0 lights local typ pointlight position -32.0 -8.0 32.0 color 1.0 1.0 1.0 typ pointlight position -32.0 8.0 32.0 color 0.7 0.7 0.8 end object local typ csg_or % the sixty-four fields typ csg_or typ csg_or typ csg_or typ csg_or typ csg_or typ csg_or typ cube min -8.0 -8.0 -0.5 max -6.0 -6.0 0.0 material gold typ cube min -6.0 -8.0 -0.5 max -4.0 -6.0 0.0 material rot typ csg_or typ cube min -8.0 -6.0 -0.5 max -6.0 -4.0 0.0 material rot typ cube min -6.0 -6.0 -0.5 max -4.0 -4.0 0.0 material gold typ csg_or typ csg_or typ cube min -4.0 -8.0 -0.5 max -2.0 -6.0 0.0 material gold typ cube min -2.0 -8.0 -0.5 max 0.0 -6.0 0.0 material rot typ csg_or typ cube min -4.0 -6.0 -0.5 max -2.0 -4.0 0.0 material rot typ cube min -2.0 -6.0 -0.5 max 0.0 -4.0 0.0 material gold typ csg_or typ csg_or typ csg_or typ cube min -8.0 -4.0 -0.5 max -6.0 -2.0 0.0 material gold typ cube min -6.0 -4.0 -0.5 max -4.0 -2.0 0.0 material rot typ csg_or typ cube min -8.0 -2.0 -0.5 max -6.0 0.0 0.0 material rot typ cube min -6.0 -2.0 -0.5 max -4.0 0.0 0.0 material gold typ csg_or typ csg_or typ cube min -4.0 -4.0 -0.5 max -2.0 -2.0 0.0 material gold typ cube min -2.0 -4.0 -0.5 max 0.0 -2.0 0.0 material rot typ csg_or typ cube min -4.0 -2.0 -0.5 max -2.0 0.0 0.0 material rot typ cube min -2.0 -2.0 -0.5 max 0.0 0.0 0.0 material gold typ csg_or typ csg_or typ csg_or typ csg_or typ cube min 0.0 -8.0 -0.5 max 2.0 -6.0 0.0 material gold typ cube min 2.0 -8.0 -0.5 max 4.0 -6.0 0.0 material rot typ csg_or typ cube min 0.0 -6.0 -0.5 max 2.0 -4.0 0.0 material rot typ cube min 2.0 -6.0 -0.5 max 4.0 -4.0 0.0 material gold typ csg_or typ csg_or typ cube min 4.0 -8.0 -0.5 max 6.0 -6.0 0.0 material gold typ cube min 6.0 -8.0 -0.5 max 8.0 -6.0 0.0 material rot typ csg_or typ cube min 4.0 -6.0 -0.5 max 6.0 -4.0 0.0 material rot typ cube min 6.0 -6.0 -0.5 max 8.0 -4.0 0.0 material gold typ csg_or typ csg_or typ csg_or typ cube min 0.0 -4.0 -0.5 max 2.0 -2.0 0.0 material gold typ cube min 2.0 -4.0 -0.5 max 4.0 -2.0 0.0 material rot typ csg_or typ cube min 0.0 -2.0 -0.5 max 2.0 0.0 0.0 material rot typ cube min 2.0 -2.0 -0.5 max 4.0 0.0 0.0 material gold typ csg_or typ csg_or typ cube min 4.0 -4.0 -0.5 max 6.0 -2.0 0.0 material gold typ cube min 6.0 -4.0 -0.5 max 8.0 -2.0 0.0 material rot typ csg_or typ cube min 4.0 -2.0 -0.5 max 6.0 0.0 0.0 material rot typ cube min 6.0 -2.0 -0.5 max 8.0 0.0 0.0 material gold typ csg_or typ csg_or typ csg_or typ csg_or typ csg_or typ cube min -8.0 0.0 -0.5 max -6.0 2.0 0.0 material gold typ cube min -6.0 0.0 -0.5 max -4.0 2.0 0.0 material rot typ csg_or typ cube min -8.0 2.0 -0.5 max -6.0 4.0 0.0 material rot typ cube min -6.0 2.0 -0.5 max -4.0 4.0 0.0 material gold typ csg_or typ csg_or typ cube min -4.0 0.0 -0.5 max -2.0 2.0 0.0 material gold typ cube min -2.0 0.0 -0.5 max 0.0 2.0 0.0 material rot typ csg_or typ cube min -4.0 2.0 -0.5 max -2.0 4.0 0.0 material rot typ cube min -2.0 2.0 -0.5 max 0.0 4.0 0.0 material gold typ csg_or typ csg_or typ csg_or typ cube min -8.0 4.0 -0.5 max -6.0 6.0 0.0 material gold typ cube min -6.0 4.0 -0.5 max -4.0 6.0 0.0 material rot typ csg_or typ cube min -8.0 6.0 -0.5 max -6.0 8.0 0.0 material rot typ cube min -6.0 6.0 -0.5 max -4.0 8.0 0.0 material gold typ csg_or typ csg_or typ cube min -4.0 4.0 -0.5 max -2.0 6.0 0.0 material gold typ cube min -2.0 4.0 -0.5 max 0.0 6.0 0.0 material rot typ csg_or typ cube min -4.0 6.0 -0.5 max -2.0 8.0 0.0 material rot typ cube min -2.0 6.0 -0.5 max 0.0 8.0 0.0 material gold typ csg_or typ csg_or typ csg_or typ csg_or typ cube min 0.0 0.0 -0.5 max 2.0 2.0 0.0 material gold typ cube min 2.0 0.0 -0.5 max 4.0 2.0 0.0 material rot typ csg_or typ cube min 0.0 2.0 -0.5 max 2.0 4.0 0.0 material rot typ cube min 2.0 2.0 -0.5 max 4.0 4.0 0.0 material gold typ csg_or typ csg_or typ cube min 4.0 0.0 -0.5 max 6.0 2.0 0.0 material gold typ cube min 6.0 0.0 -0.5 max 8.0 2.0 0.0 material rot typ csg_or typ cube min 4.0 2.0 -0.5 max 6.0 4.0 0.0 material rot typ cube min 6.0 2.0 -0.5 max 8.0 4.0 0.0 material gold typ csg_or typ csg_or typ csg_or typ cube min 0.0 4.0 -0.5 max 2.0 6.0 0.0 material gold typ cube min 2.0 4.0 -0.5 max 4.0 6.0 0.0 material rot typ csg_or typ cube min 0.0 6.0 -0.5 max 2.0 8.0 0.0 material rot typ cube min 2.0 6.0 -0.5 max 4.0 8.0 0.0 material gold typ csg_or typ csg_or typ cube min 4.0 4.0 -0.5 max 6.0 6.0 0.0 material gold typ cube min 6.0 4.0 -0.5 max 8.0 6.0 0.0 material rot typ csg_or typ cube min 4.0 6.0 -0.5 max 6.0 8.0 0.0 material rot typ cube min 6.0 6.0 -0.5 max 8.0 8.0 0.0 material gold typ cube min -4.0 -4.0 0.0 max 4.0 4.0 8.0 material glas end #include material.dat max 8.0 6.0 0.0 material rot typ csg_or typ cube min 4.0 6.0 -0.5 max 6.0 8.0 0.0 material rot typ cube minFlirt/Ftl/glastest.ftl000644 000316 000311 00000003645 06114644633 015057 0ustar00wrzlgup000000 000000 global scene smallmidpoint camera stest lights stest object stest material air background 0.48 0.6 0.9 scene smallmidpoint xpix 128 ypix 96 shadow_rays true texturing true max_reflection 10 max_refraction 10 min_contribution 0.003906 sampling midpoint camera stest eye 5.0 3.0 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end texture goldchecker typ checker3d width 0.5 0.5 0.3 typ materialarray1d number 1 material gold end object stest typ csg_or typ csg_or typ csg_sub typ cube min -1.0 -1.0 -0.01 max 1.0 1.0 1.0 material glasgruen typ cube min -0.9 -0.9 0.1 max 0.9 0.9 0.9 material glasgruen typ sphere center 0.0 0.0 0.5 radius 0.48 material rot typ csg_or typ cube min -2.9 -2.9 -0.3 max 1.1 1.1 0.0 material rot texture goldchecker typ cube min -3.0 -3.0 0.0 max -2.9 1.1 1.5 material spiegel end #include material.dat sphere center 0.0 0.0 0.5 radius 0.48 Flirt/Ftl/glt.ftl000644 000316 000311 00000003646 06114644633 014020 0ustar00wrzlgup000000 000000 global scene smallmidpoint camera stest lights stest object stest material air background 0.48 0.6 0.9 scene smallmidpoint xpix 128 ypix 96 shadow_rays true texturing true max_reflection 10 max_refraction 10 min_contribution 0.003906 sampling midpoint camera stest eye 5.0 3.0 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end texture goldchecker typ checker3d width 0.5 0.5 0.3 typ materialarray1d number 1 material gold end object stest typ csg_or typ csg_or typ csg_sub typ cube min -1.0 -1.0 -0.01 max 1.0 1.0 1.0 material glasgruen typ cube min -0.9 -0.9 0.1 max 0.9 0.9 0.9 material glasgruen typ sphere center 0.0 0.0 0.5 radius 0.48 material rot typ csg_or typ cube min -2.9 -2.9 -0.3 max 1.1 1.1 0.0 material rot texture goldchecker typ cube min -3.0 -3.0 0.0 max -2.9 1.1 1.5 material spiegel end #include material.dat sphere center 0.0 0.0 0.5 radius 0.48 Flirt/Ftl/hexaeder.ftl000644 000316 000311 00000004244 06114644633 015012 0ustar00wrzlgup000000 000000 % platonische .... ? global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 20.0 12.0 20.0 lights local typ pointlight position 5.0 -5.0 5.0 color 1.0 1.0 1.0 typ pointlight position -6.0 6.0 6.0 color 0.5 0.5 0.5 typ pointlight position -6.0 0.0 -3.0 color 0.5 0.5 0.5 end #include platonicpoly.dat object local typ csg_or % typ csg_or % typ csg_or % typ named % object dodecaeder % transform rotz -30.0 % rotx -12.0 % trans 2.0 -2.0 0.0 % material rot % typ named % object icosaeder % transform rotz -30.0 % rotx -12.0 % trans 2.0 2.0 0.0 % material rot typ csg_or typ named object tetraeder transform rotz 30.0 rotx 12.0 trans -2.0 2.0 0.0 material rot typ named object hexaeder transform rotz 30.0 rotx 12.0 trans -2.0 -2.0 0.0 material rot typ named object tetraeder transform rotz 30.0 rotx 12.0 trans 0.0 -4.0 1.0 material rot end #include material.dat typ named object hexaeder transform rotz 30.0 rotx 12.0 trans -2.0 -2.0 0.0 material rot typ named object tetraeder transform Flirt/Ftl/hyper.ftl000644 000316 000311 00000001274 06114644633 014354 0ustar00wrzlgup000000 000000 % a hyperellipsoid global scene smallmidpoint camera hyper lights hyper object hyper material air background 0.48 0.6 0.9 #include scenes.dat camera hyper eye 5.0 3.0 5.0 lights hyper typ pointlight position 5.0 -5.0 5.0 color 1.0 1.0 1.0 typ pointlight position -6.0 6.0 6.0 color 1.0 1.0 1.0 end object hyper typ hyperellipsoid order 10.0 10.0 10.0 material rot end #include material.dat 0.6 0.9 #include scenes.dat camera hyper eye 5.0 3.0 5.0 lights hyper typ pointlight position 5.0 -5.0 5.0 color 1.0 1.0 1.0 typ pointlight position -6.0 6.0 6.0 color Flirt/Ftl/hyperbol.ftl000644 000316 000311 00000001473 06114644633 015052 0ustar00wrzlgup000000 000000 % testscene for hyperboloid global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object local typ csg_sub typ hyperboloid radius 0.5 material rot typ hyperboloid radius -0.5 material rot end #include material.dat local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position Flirt/Ftl/hypsweep.ftl000644 000316 000311 00000001504 06114644633 015065 0ustar00wrzlgup000000 000000 % testscene for hyperbolasweep global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object local typ csg_sub typ hyperbolasweep radius 0.5 material rot typ hyperbolasweep radius -0.5 material rot end #include material.dat local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position Flirt/Ftl/jtest.ftl000644 000316 000311 00000002157 06114644633 014357 0ustar00wrzlgup000000 000000 Global scene smallmidpoint camera stest lights stest object local material air background 0.48 0.6 0.9 #include scenes.dat camera stest eye 5.0 5.0 5.0 direction -5.0 -5.0 -5.0 zoom 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ sphere center 0.0 0.0 -0.5 radius 0.5 material gold typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material rot end object local %typ cylcube %subdivisions 6 %typ grid % dimension 6 6 6 typ named object stest end #include material.dat p csg_or typ sphere center 0.0 0.0 -0.5 radius 0.5 material gold typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material rot end object local %typ cylcube %subdivisions 6 %typ grid Flirt/Ftl/kinzim.ftl000644 000316 000311 00000031122 06114644633 014521 0ustar00wrzlgup000000 000000 % zimmer global % scene smallmidpoint scene smalladaptive camera local lights local object local material air background 0.95 0.95 0.9 camera local eye 11 0 16 direction 0.2 1 0 % eye 13 10 16 % direction 0.1 1 0 % eye 28 28 33.5 % direction -1 1 -1 % eye 2 44.5 7 % direction 4 -1 3 zoom 0.4 % eye 15 23 70.5 % direction 0 0 -1 % eye 30 8 16 % direction -1 1.6 0 % zoom 0.5 lights local typ pointlight position 0 -100 100 color 1.0 1.0 1.0 typ pointlight position 15 22 30 color 0.3 0.3 0.3 typ ambient color 0.9 0.9 0.9 end #include scenes.dat object bett typ csg_or typ cube %bettkasten min 0 0 0 max 9 20 1.5 material holz typ cube %bettauflage min 0.2 0.2 1.4 max 8.8 19.8 1.7 material blau end object leiter typ csg_or typ csg_or % sprossen typ csg_or % 1-4 typ csg_or % 1,2 typ cylinder transform scale 0.2 0.2 6 rotx -90 trans 24.25 24 2.4 material holz typ cylinder transform scale 0.2 0.2 6 rotx -90 trans 24.25 24 4.8 material holz typ csg_or % 3,4 typ cylinder transform scale 0.2 0.2 6 rotx -90 trans 24.25 24 7.2 material holz typ cylinder transform scale 0.2 0.2 6 rotx -90 trans 24.25 24 9.6 material holz typ csg_or %5,6 typ cylinder transform scale 0.2 0.2 6 rotx -90 trans 24.25 24 12 material holz typ cylinder transform scale 0.2 0.2 6 rotx -90 trans 24.25 24 14.4 material holz typ csg_or typ csg_or % seitenwand typ csg_or typ cube %leiterstange min 24 24 0 max 24.5 24.5 23.5 material holz typ csg_or typ cylinder %gangendestange transform scale 0.2 0.2 5.5 roty -90 trans 30 24.25 23.25 material holz typ cube %gangendebrett min 24.5 24 20 max 30 24.2 21.5 material holz typ cube %leiterwand min 26.5 24 0 max 30 24.2 17.5 material holz % typ cube %leiterwand % min 24.5 24.15 0 % max 30 24.35 23.5 % material holz typ csg_or %fachbretter typ csg_or typ csg_or typ cube min 26.5 24.2 3.3 max 30 30 3.5 material holz typ cube min 26.5 24.2 6.8 max 30 30 7 material holz typ csg_or typ cube min 26.5 24.2 10.3 max 30 30 10.5 material holz typ cube min 26.5 24.2 13.8 max 30 30 14 material holz typ cube %leiterdeckel min 24 24.2 16.8 max 30 30 17 material holz end object leiter1 % typ csg_or % typ cylinder % transform % scale 0.4 0.4 17 % trans 23 29 0 % material holz typ csg_and typ csg_or typ cube transform scale 1.5 0.3 20 trans 23 24 0 shearxy 0.35 0 material gruen typ csg_or typ csg_or % sprossen typ csg_or % 1-4 typ csg_or % 1,2 typ cylinder transform scale 0.2 0.2 6 rotx 90 trans 24.25 30 2.4 material holz typ cylinder transform scale 0.2 0.2 7 rotx 90 rotz 7 trans 24.25 30 4.8 material holz typ csg_or % 3,4 typ cylinder transform scale 0.2 0.2 7 rotx 90 rotz 15 trans 24.25 30 7.2 material holz typ cylinder transform scale 0.2 0.2 8 rotx 90 rotz 22 trans 24.25 30 9.6 material holz typ csg_or %5,6 typ cylinder transform scale 0.2 0.2 8 rotx 90 rotz 30 trans 24.25 30 12 material holz typ cylinder transform scale 0.2 0.2 8 rotx 90 rotz 37 trans 24.25 30 14.4 material holz typ cube %leiterdeckel transform scale 8 8 0.2 rotz -45 trans 24 30 16.8 material holz typ cube min 24 24 0 max 30 30 20 material holz end object hochbett typ csg_or typ csg_or typ named object bett transform trans 15.5 30 20 typ csg_or %rahmen typ csg_or typ cube %saeule min 15.5 30 20 max 16 30.5 23.5 material holz typ cylinder %lange stange transform scale 0.2 0.2 20 rotx -90 trans 15.75 30 23.25 material holz typ cylinder %kurze stange transform scale 0.2 0.2 8.5 roty 90 trans 16 30.25 23.25 material holz typ csg_or typ csg_or typ cube %traeger horizontal min 0 29.9 20 max 24.5 30.2 20.45 material schwarz typ cube %traeger vertikal min 24 29.5 0 max 24.5 30 23.5 material holz typ csg_or typ csg_or typ cube %tiefer kasten min 24 30 0 max 30 50 17 material holz typ cube %nachtkastl min 24.5 46 17 max 30 50 24 material holz typ csg_or typ named object leiter1 % transform % shearxy 0.2 0 typ cube %gangbrett min 24 30 17.0 max 24.2 50 17.5 material holz end object regal typ csg_or typ csg_or typ cube min 0.2 0 0.8 max 9.8 3 1 material holz typ csg_or typ cube min 0.2 0 4 max 9.8 2.7 4.2 material holz typ cube min 0.2 0 7.2 max 9.8 3 7.4 material holz typ csg_or typ cube min 0 0 0 max 0.2 3 7.4 material holz typ cube min 9.8 0 0 max 10 3 7.4 material holz end object kastl typ cube min 0 0 0 max 10 3 7.4 material holz end object tisch typ csg_or typ cube min 0 0 7.1 max 8 11 7.5 material holz typ csg_or typ csg_or typ cylinder transform scale 0.2 0.2 7.1 trans 0.8 0.8 0 material schwarz typ cylinder transform scale 0.2 0.2 7.1 trans 7.2 0.8 0 material schwarz typ csg_or typ cylinder transform scale 0.2 0.2 7.1 trans 0.8 10.2 0 material schwarz typ cylinder transform scale 0.2 0.2 7.1 trans 7.2 10.2 0 material schwarz end object waschtisch typ csg_or typ cube min 0.4 0.5 0 max 10.1 5.2 7.8 material holz typ csg_or typ cube min 0 0 7.8 max 10.5 5.2 7.9 material grau40 typ cube min 0 4 8 max 10.5 5.2 8.1 material grau40 end object zimmer typ csg_or typ csg_sub typ csg_sub typ csg_sub typ csg_sub typ csg_sub typ csg_sub typ cube min -5 -9 -1 %waende max 32 55 72 material fastweiss typ cube %raum min 0 -4 0 max 30 50 35 % max 30 50 37 material air typ cube %raum darueber min -1 -5 36 max 31 51 71 material air typ cube %fensternische unten min 8 -5.5 0 max 19 -3.9 8.5 material air typ cube %fensternische oben min 8 -7 8.4 max 19 -3.9 30 material air typ cube %fenster min 8.7 -19.1 9 max 18.3 -6.9 29.2 material air typ cube %tuer min 29.9 3 0 max 32.1 12 20 material air typ cube min 0 -5.5 0 max 32 50 0.1 material graublau end object variante1 typ csg_or typ csg_or typ named object bett transform rotz -90 trans 0 50 2.5 typ cube min 19.8 41 0 max 20 50 2.5 material holz typ csg_or typ cube min 0 37 0 max 5.5 41 7 material holz typ cube min 0 25 0 max 5.5 37 35 material holz end object variante2 typ csg_or typ csg_or typ named object bett transform trans 0 30 2.5 typ csg_or typ cube min 0 15 0 max 3 30 7.4 material holz typ cube min 0 30 0 max 9 30.2 2.5 material holz typ csg_or typ cube min 9 44 0 max 15.5 50 7.4 material holz typ cube min 15.5 44 0 max 24 50 20 material holz end object variante3 typ csg_or typ csg_or %bett typ named object bett transform trans 0 27 2.5 typ cube min 0 27 0 max 9 27.2 2.5 material holz typ csg_or typ cube %kastl min 0 15 0 max 3 27 7.4 material holz typ csg_or %rueckwand typ csg_or %kasten tief typ cube min 9 44 20 max 15.5 50 23.5 material holz typ cube min 9 44 0 max 24 50 20 material holz typ csg_or %kasten hinter bett typ csg_or typ cube min 0 47 0 max 9 50 8 material holz typ cube min 0 47 11 max 9 50 11.2 material holz typ csg_or typ cube min 0 47 14.3 max 9 50 14.5 material holz typ csg_or typ cube min 0 44 0 max 0.2 50 17.5 material holz typ cube min 0 44 17.5 max 9 50 23.5 material holz end object local typ cylcube subdivisions 5 typ csg_or typ named object zimmer typ csg_or typ named object hochbett typ csg_or typ named % object variante1 % object variante2 object variante3 typ csg_or typ csg_or typ named object tisch typ named object waschtisch transform scale 1 -1 1 trans 19.5 1.5 0 typ named object regal transform scale 0.9 1 1 rotz -90 trans 27 24 0 end #include material.dat material graublau ambient 0.4 0.4 0.5 diffuse 0.4 0.4 0.5 specular 0 0 0 material grau40 ambient 0.4 0.4 0.4 diffuse 0.4 0.4 0.4 specular 0 0 0 material holz ambient 0.48 0.35 0.2 diffuse 0.6 0.4 0.21 specular 0.05 0.05 0.05 specpow 10 tz -90 trans 27 24 0 end #include material.dat material graublau ambient 0.4 0.4 0.5 diffuse 0.4 0.4 0.5 specular 0 0 0 material grau40 ambient 0.4 0.4 0.4 diffuse 0.4 0.4 0.4 specular 0 0 0 material holz ambient 0.48 0.35 0.2 diffuse 0.6Flirt/Ftl/kinzima.ftl000644 000316 000311 00000016426 06114644633 014674 0ustar00wrzlgup000000 000000 % teapot global scene smallmidpoint % scene adaptive camera local lights local object local material air background 0.95 0.95 0.9 camera local eye 11 0 16 direction 0.2 1 0 % eye 13 10 16 % direction 0.1 1 0 % eye 28 28 33.5 % direction -1 1 -1 zoom 0.4 % eye 15 22 70.5 % direction 0 0 -1 % eye 30 8 16 % direction -1 1.6 0 % zoom 0.5 lights local typ pointlight position 0 -100 100 color 1.0 1.0 1.0 typ pointlight position 15 22 30 color 0.3 0.3 0.3 typ ambient color 0.9 0.9 0.9 end #include scenes.dat object bett typ csg_or typ cube %bettkasten min 0 0 0 max 9 20 1.5 material holz typ cube %bettauflage min 0.2 0.2 1.4 max 8.8 19.8 1.7 material blau end object hochbett typ csg_or typ csg_or typ named object bett transform rotz -90 trans 0 44.5 20 typ csg_or %rahmen typ csg_or typ cube %saeule min 19.5 35.5 20 max 20 36 23.5 material holz typ cylinder %lange stange transform scale 0.2 0.2 20 roty 90 trans 0 35.75 23.25 material holz typ cylinder %kurze stange transform scale 0.2 0.2 8 rotx 90 trans 19.75 44 23.25 material holz typ csg_or typ csg_or typ cube %traeger horizontal min 0 35.5 19.8 max 30 36 20.5 material holz typ cube %traeger vertikal min 19.5 44 0 max 20 44.5 23.5 material holz typ csg_or typ csg_or typ cube %standboden min 0 44.5 17.3 max 30 50 17.5 material holz typ csg_or typ csg_or typ cube %leiterstange min 24.5 44 0 max 25 44.5 23.5 material holz typ csg_or typ cylinder %gangendestange transform scale 0.2 0.2 5 roty 90 trans 25 44.25 23.25 material holz typ cube min 24 44 20 max 30 44.2 21.5 material holz typ csg_or typ csg_or %leiter typ csg_or typ csg_or typ cylinder transform scale 0.2 0.2 5 roty 90 trans 20 44.25 2.5 material holz typ cylinder transform scale 0.2 0.2 5 roty 90 trans 20 44.25 5 material holz typ csg_or typ cylinder transform scale 0.2 0.2 5 roty 90 trans 20 44.25 7.5 material holz typ cylinder transform scale 0.2 0.2 5 roty 90 trans 20 44.25 10 material holz typ csg_or typ cylinder transform scale 0.2 0.2 5 roty 90 trans 20 44.25 12.5 material holz typ cylinder transform scale 0.2 0.2 5 roty 90 trans 20 44.25 15 material holz typ csg_or typ csg_or typ cube min 0 47 3.3 max 30 50 3.5 material holz typ cube min 0 47 6.8 max 30 50 7 material holz typ csg_or typ cube min 0 47 10.3 max 30 50 10.5 material holz typ cube min 0 47 13.8 max 30 50 14 material holz typ cube min 0 44.5 17.5 max 20 44.7 18.3 material holz end object zimmer typ csg_or typ csg_sub typ csg_sub typ csg_sub typ csg_sub typ csg_sub typ cube min -5 -10 -1 %waende max 32 55 72 material fastweiss typ cube %raum min 0 -5 0 max 30 50 35 % max 30 50 37 material air typ cube %raum darueber min -1 -6 36 max 31 51 71 material air typ cube %fensternische min 9 -7.2 0 max 21 -4.9 30 material air typ cube %fenster min 10 -10.1 8.2 max 20 -7.1 29.2 material air typ cube %tuer min 29.9 5 0 max 32.1 14 20 material air typ cube min 0 -7.2 0 max 32 50 0.1 material graublau end object variante1 typ csg_or typ csg_or typ named object bett transform rotz -90 trans 0 47 2.5 typ cube min 19.8 38 0 max 20 47 2.5 material holz typ cube min 0 25 0 max 5.5 35.5 35 material holz end object variante2 typ csg_or typ csg_or typ named object bett transform trans 0 30 2.5 typ cube min 30 0 0 max 30.2 9 2.5 material holz typ csg_sub typ cube min 9 44 0 max 24,5 50 20 material holz typ cube min 16.72 39.9 0 max 16.78 40.1 20 material air end object local typ csg_or typ named object zimmer typ csg_or typ csg_or typ named object hochbett typ csg_or typ csg_or typ cylinder transform scale 0.7 0.7 20 rotx -90 trans 29.2 30 18.7 material rot typ sphere transform scale 0.7 0.7 0.7 trans 29.2 30 18.7 material rot typ csg_or typ cylinder transform scale 0.7 0.7 12 trans 29.2 30 6.7 material rot typ cube min 24 26.5 0 max 28 31.5 9 material rot typ named object variante1 % object variante2 end #include material.dat material graublau ambient 0.4 0.4 0.5 diffuse 0.4 0.4 0.5 specular 0 0 0 material holz ambient 0.48 0.35 0.2 diffuse 0.6 0.4 0.21 specular 0.05 0.05 0.05 specpow 10 rot typ cube min 24 26.5 0 max 28 31.5 9 material rot typ named object variante1 % object variante2 end #include material.dat material graublau ambient Flirt/Ftl/material.dat000644 000316 000311 00000034415 06114644633 015011 0ustar00wrzlgup000000 000000 % some selected materials for the flirt raytracer #if standard % ************************* Standard materials ***************************** material air diffuse 0.0 0.0 0.0 transparency 1.0 refract_index 1.0 material weiss ambient 0.9 0.9 0.9 diffuse 0.9 0.9 0.9 material fastweiss ambient 0.9 0.84 0.8 diffuse 0.9 0.84 0.8 material wood ambient 0.3 0.12 0.04 diffuse 0.5 0.36 0.09 specular 0.05 0.05 0.05 specpow 10 material gold ambient 0.81 0.834 0.244 diffuse 0.81 0.834 0.244 specular 0.45 0.45 0.15 specpow 20 reflectivity 0.3 material rot ambient 0.8 0.1 0.05 diffuse 0.8 0.1 0.05 specular 0.05 0.05 0.05 specpow 10 material glas ambient 0.02 0.02 0.02 diffuse 0.1 0.1 0.1 specular 0.8 0.8 0.8 specpow 200 reflectivity 0.3 transparency 1.0 refract_index 1.4 material glas1 ambient 0.02 0.02 0.02 diffuse 0.1 0.1 0.1 specular 0.8 0.8 0.8 specpow 200 reflectivity 1.0 transparency 1.0 refract_index 1.04 material glasgruen ambient 0.02 0.02 0.02 diffuse 0.1 0.1 0.1 specular 0.8 0.8 0.8 specpow 200 transparency 0.95 body 0.5 1.0 0.5 refract_index 1.1 material diamond ambient 0.02 0.02 0.02 diffuse 0.1 0.1 0.1 specular 0.8 0.8 0.8 specpow 200 reflectivity 1.0 transparency 1.0 body 0.9 0.9 1.0 refract_index 2.42 material weinrotmatt ambient 0.8 0.1 0.05 diffuse 0.8 0.1 0.05 material spiegel diffuse 0.05 0.05 0.1 specular 0.9 0.9 1.0 specpow 200 reflectivity 0.9 material gruen ambient 0.1 0.8 0.05 diffuse 0.1 0.8 0.05 specular 0.05 0.05 0.05 specpow 20 material blau ambient 0.1 0.1 0.8 diffuse 0.1 0.1 0.8 specular 0.05 0.05 0.05 specpow 20 material schwarz ambient 0.0 0.0 0.0 diffuse 0.0 0.0 0.0 specular 0.5 0.5 0.5 specpow 20 material braun ambient 0.3 0.2 0.0 diffuse 0.3 0.2 0.0 specular 0.3 0.2 0.0 specpow 20 material goldrobi ambient 0.867 0.834 0.244 diffuse 0.867 0.834 0.244 specular 0.45 0.45 0.15 specpow 20 reflectivity 0.3 material glasrobi ambient 0.02 0.02 0.02 diffuse 0.1 0.1 0.1 specular 0.8 0.8 0.8 specpow 200 reflectivity 1.0 transparency 1.0 refract_index 1.1 material glasrobi2 ambient 0.02 0.02 0.02 diffuse 0.1 0.1 0.1 specular 0.8 0.8 0.8 specpow 200 reflectivity 1.0 transparency 1.0 refract_index 1.4 material glasrobi3 ambient 0.02 0.02 0.02 diffuse 0.1 0.1 0.1 specular 0.8 0.8 0.8 specpow 200 reflectivity 1.0 transparency 0.98 refract_index 1.4 material hellrot ambient 0.95 0.1 0.1 diffuse 0.95 0.1 0.1 specular 0.05 0.05 0.05 specpow 20 material hellgruen diffuse 0.1 0.95 0.1 specular 0.05 0.05 0.05 specpow 20 material hellblau diffuse 0.1 0.1 0.95 specular 0.05 0.05 0.05 specpow 20 material weissmatt ambient 0.9 0.9 0.9 diffuse 0.9 0.9 0.9 #endif #if simple % *************************** simple materials **************************** material air smoothness 0.0 metalness 0.0 transparency 1.0 refract_index 1.0 color 1.0 1.0 1.0 material gold smoothness 0.491071 metalness 1.0 transparency 0.0 refract_index 2.13076 color 0.81 0.834 0.244 material rot smoothness 0.0 metalness 0.0 transparency 0.0 refract_index 4.6 color 0.65 0.15 0.15 material glas smoothness 1.0 metalness 0.0 transparency 1.0 refract_index 1.4 color 1.0 1.0 1.0 material glas1 smoothness 1.0 metalness 0.0 transparency 1.0 refract_index 1.04 color 1.0 1.0 1.0 material glasgruen smoothness 1.0 metalness 1.0 transparency 0.95 refract_index 1.1 color 0.5 1.0 0.5 material diamond smoothness 1.0 metalness 0.0 transparency 0.95 refract_index 2.42 color 1.0 1.0 0.95 material weinrotmatt smoothness 0.111 metalness 0.0 transparency 0.0 refract_index 1.955 color 0.65 0.15 0.15 material spiegel smoothness 1.0 metalness 1.0 transparency 0.0 refract_index 100.0 color 0.9 0.9 1.0 material gruen smoothness 0.0 metalness 0.0 transparency 0.0 refract_index 4.6 color 0.15 0.65 0.15 material blau smoothness 0.0 metalness 0.0 transparency 0.0 refract_index 4.6 color 0.15 0.15 0.65 material schwarz smoothness 0.0 metalness 0.0 transparency 0.0 refract_index 4.6 color 0.0 0.0 0.0 material goldrobi smoothness 0.72341 metalness 1.0 transparency 0.0 refract_index 2.13076 color 0.867 0.834 0.244 material glasrobi smoothness 1.0 metalness 0.0 transparency 1.0 refract_index 1.1 color 1.0 0.992 0.98 material weissmatt smoothness 0.111 metalness 0.0 transparency 0.0 refract_index 1.955 color 0.9 0.9 0.9 material hellgruen smoothness 0.0 metalness 0.0 transparency 0.0 refract_index 4.6 color 0.15 0.95 0.15 material hellrot smoothness 0.0 metalness 0.0 transparency 0.0 refract_index 4.6 color 0.95 0.15 0.15 material hellblau smoothness 0.0 metalness 0.0 transparency 0.0 refract_index 4.6 color 0.15 0.15 0.95 material visualizeborder smoothness 0.0 metalness 0.0 transparency 0.8 refract_index 1.0 color 1.0 1.0 1.0 material visualizeinside smoothness 0.0 metalness 0.0 transparency 0.9 refract_index 1.0 color 1.0 1.0 1.0 material glasrobi2 smoothness 1.0 metalness 0.0 transparency 1.0 refract_index 1.4 color 0.998 0.998 0.998 material glasrobi3 smoothness 1.0 metalness 0.0 transparency 0.98 refract_index 1.4 color 0.98 0.98 0.98 #endif #if riss % ************************* RISS-materials ******************************** material air specular 0.0 refract_index 1.0 diffuse 0.0 0.0 0.0 extinction 0.0 0.0 0.0 absorption 1.0 1.0 1.0 emission 0.0 0.0 0.0 refraction 1.0 1.0 1.0 facets 1.0 6.6E-2 3.8E-3 1.8E-4 7.3E-6 2.3E-7 5.7E-9 1.1E-10 1.3E-12 1.1E-14 5.9E-17 1.6E-19 2.1E-22 9.3E-26 1.0E-29 1.4E-34 0.0 0.0 0.0 0.0 material gold specular 0.491071 refract_index 2.13076 diffuse 0.81 0.834 0.244 extinction 7.0 7.0 1.0 absorption 0.0 0.0 0.0 emission 0.0 0.0 0.0 refraction 3.0 3.0 1.0 facets 1.0 8.7E-1 5.7E-1 2.8E-1 1.0E-1 2.7E-2 5.2E-3 6.7E-4 5.7E-5 3.0E-6 9.0E-8 1.3E-9 8.8E-12 1.9E-14 9.9E-18 6.3E-22 1.5E-27 9.8E-36 0.0 0.0 material rot specular 0.0 refract_index 4.6 diffuse 0.65 0.15 0.15 extinction 0.0 0.0 0.0 absorption 0.0 0.0 0.0 emission 0.0 0.0 0.0 refraction 9.3 2.2 2.2 facets 1.0 5.8E-1 3.3E-1 1.8E-1 9.4E-2 4.7E-2 2.2E-2 1.0E-2 4.2E-3 1.6E-3 5.6E-4 1.7E-4 4.6E-5 9.8E-6 1.5E-6 1.7E-7 9.6E-9 1.6E-10 1.6E-13 0.0 material glas specular 1.0 refract_index 1.2 diffuse 0.04 0.04 0.04 extinction 0.0 0.0 0.0 absorption 0.95 0.95 0.95 emission 0.0 0.0 0.0 refraction 1.2 1.2 1.2 facets 1.0 6.6E-2 3.8E-3 1.8E-4 7.3E-6 2.3E-7 5.7E-9 1.1E-10 1.3E-12 1.1E-14 5.9E-17 1.6E-19 2.1E-22 9.3E-26 1.0E-29 1.4E-34 0.0 0.0 0.0 0.0 material glas1 specular 1.0 refract_index 1.04 diffuse 0.04 0.04 0.04 extinction 0.0 0.0 0.0 absorption 0.95 0.95 0.95 emission 0.0 0.0 0.0 refraction 1.04 1.04 1.04 facets 1.0 6.6E-2 3.8E-3 1.8E-4 7.3E-6 2.3E-7 5.7E-9 1.1E-10 1.3E-12 1.1E-14 5.9E-17 1.6E-19 2.1E-22 9.3E-26 1.0E-29 1.4E-34 0.0 0.0 0.0 0.0 material glasgruen specular 1.0 refract_index 1.1 diffuse 0.1 0.1 0.1 extinction 0.0 0.0 0.0 absorption 0.5 1.0 0.5 emission 0.0 0.0 0.0 refraction 1.1 1.1 1.1 facets 1.0 6.6E-2 3.8E-3 1.8E-4 7.3E-6 2.3E-7 5.7E-9 1.1E-10 1.3E-12 1.1E-14 5.9E-17 1.6E-19 2.1E-22 9.3E-26 1.0E-29 1.4E-34 0.0 0.0 0.0 0.0 material weinrotmatt specular 0.111 refract_index 1.955 diffuse 0.65 0.15 0.15 extinction 0.0 0.0 0.0 absorption 1.0 1.0 1.0 emission 0.0 0.0 0.0 refraction 9.3 2.2 2.2 facets 1.0 5.8E-1 3.3E-1 1.8E-1 9.4E-2 4.7E-2 2.2E-2 1.0E-2 4.2E-3 1.6E-3 5.6E-4 1.7E-4 4.6E-5 1.6E-5 9.8E-6 1.5E-6 1.7E-7 9.6E-9 1.6E-10 1.6E-13 material spiegel specular 1.0 refract_index 1000.0 diffuse 0.996 0.996 0.996 extinction 0.0 0.0 0.0 absorption 1.0 1.0 1.0 emission 0.0 0.0 0.0 refraction 1000.0 1000.0 1000.0 facets 1.0 6.6E-2 3.8E-3 1.8E-4 7.3E-6 2.3E-7 5.7E-9 1.1E-10 1.3E-12 1.1E-14 5.9E-17 1.6E-19 2.1E-22 9.3E-26 1.0E-29 1.4E-34 0.0 0.0 0.0 0.0 % defined in lack of other stuff material gruen specular 0.0 refract_index 4.6 diffuse 0.15 0.65 0.15 extinction 0.0 0.0 0.0 absorption 1.0 1.0 1.0 emission 0.0 0.0 0.0 refraction 2.2 9.3 2.2 facets 1.0 5.8E-1 3.3E-1 1.8E-1 9.4E-2 4.7E-2 2.2E-2 1.0E-2 4.2E-3 1.6E-3 5.6E-4 1.7E-4 4.6E-5 9.8E-6 1.5E-6 1.7E-7 9.6E-9 1.6E-10 1.6E-13 0.0 material blau specular 0.0 refract_index 4.6 diffuse 0.15 0.15 0.65 extinction 0.0 0.0 0.0 absorption 1.0 1.0 1.0 emission 0.0 0.0 0.0 refraction 2.2 2.2 9.3 facets 1.0 5.8E-1 3.3E-1 1.8E-1 9.4E-2 4.7E-2 2.2E-2 1.0E-2 4.2E-3 1.6E-3 5.6E-4 1.7E-4 4.6E-5 9.8E-6 1.5E-6 1.7E-7 9.6E-9 1.6E-10 1.6E-13 0.0 material violett specular 0.0 refract_index 6.9 diffuse 0.65 0.15 0.65 extinction 0.0 0.0 0.0 absorption 1.0 1.0 1.0 emission 0.0 0.0 0.0 refraction 9.3 2.2 9.3 facets 1.0 5.8E-1 3.3E-1 1.8E-1 9.4E-2 4.7E-2 2.2E-2 1.0E-2 4.2E-3 1.6E-3 5.6E-4 1.7E-4 4.6E-5 9.8E-6 1.5E-6 1.7E-7 9.6E-9 1.6E-10 1.6E-13 0.0 material glasrobi2 specular 1.0 refract_index 1.15 diffuse 0.05 0.05 0.05 extinction 0.0 0.0 0.0 absorption 0.95 0.95 0.95 emission 0.0 0.0 0.0 refraction 1.15 1.15 1.15 facets 1.0 6.6E-2 3.8E-3 1.8E-4 7.3E-6 2.3E-7 5.7E-9 1.1E-10 1.3E-12 1.1E-14 5.9E-17 1.6E-19 2.1E-22 9.3E-26 1.0E-29 1.4E-34 0.0 0.0 0.0 0.0 #endif glasrobi2 specular 1.0 refract_index 1.15 diffuse 0.05 0.05 0.05 extinction 0.0 0.0 0.0 absorption 0.95 0.95 0.95 emission 0.0 0.0 0.0 refraction Flirt/Ftl/mozart.ftl000644 000316 000311 00000002005 06114644634 014533 0ustar00wrzlgup000000 000000 global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 8.0 -24.0 16.0 lights local typ pointlight position 16.0 -16.0 16.0 color 1.0 1.0 1.0 typ pointlight position -16.0 16.0 16.0 color 1.0 1.0 1.0 end object local typ csg_and typ csg_or typ csg_or typ sphere center 0 0 0 radius 0.5 material gruen typ sphere center 0 0 0 radius 0.8 material gold typ sphere center 0 0 0 radius 1.0 material braun typ cube min -3 -3 -3 max 0 3 3 material rot end #include material.dat 1.0 1.0 1.0 end object local typ csg_and typ csg_or typ csg_or typ sphere center 0 0 0 radius 0.5 material gruen typ sphere center 0 0 0 radius 0.8 material gold typ sphere center 0 0 0 radius 1.0 material braun typ cube min -3 -3 -3 max 0 3 3 material rot end #include material.Flirt/Ftl/named.ftl000644 000316 000311 00000003223 06114644634 014306 0ustar00wrzlgup000000 000000 % primitive testszene global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object mist typ csg_or typ sphere center 0.0 0.0 -0.5 radius 0.5 material gold typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material rot end object local typ csg_or typ csg_or typ named object mist transform scale 0.5 0.5 1.0 trans -0.3 -0.3 0.0 shearxy -0.3 -0.3 typ named object mist transform scale 0.5 0.5 1.0 trans -0.3 0.3 0.0 shearxy -0.3 0.3 typ csg_or typ named object mist transform scale 0.5 0.5 1.0 trans 0.3 -0.3 0.0 shearxy 0.3 -0.3 typ named object mist transform scale 0.5 0.5 1.0 trans 0.3 0.3 0.0 shearxy 0.3 0.3 end #include material.dat mist transform scale 0.5 0.5 1.0 trans -0.3 0.3 0.0 shearxy -0.3 0.3 typ csg_or typ named object mist transform scale 0.5 0.5 1.0 trans 0.3 -0.3 0.0 shearxy 0.3 -0.3 typ named object Flirt/Ftl/newcone.ftl000644 000316 000311 00000001212 06114644634 014654 0ustar00wrzlgup000000 000000 % testscene for cone global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object local typ cone material rot end #include material.dat al material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color Flirt/Ftl/octaeder.ftl000644 000316 000311 00000001746 06114644634 015020 0ustar00wrzlgup000000 000000 % platonische .... ? global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 20.0 12.0 20.0 lights local typ pointlight position 5.0 -5.0 5.0 color 1.0 1.0 1.0 typ pointlight position -6.0 6.0 6.0 color 0.5 0.5 0.5 typ pointlight position -6.0 0.0 -3.0 color 0.5 0.5 0.5 end #include platonicpoly.dat object local typ named object octaeder transform rotz 30.0 rotx 12.0 trans 0.0 -4.0 1.0 material rot end #include material.dat position -6.0 Flirt/Ftl/para.ftl000644 000316 000311 00000002353 06114644634 014150 0ustar00wrzlgup000000 000000 % testscene for paraboloid global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 3.0 3.0 4.0 lights local typ pointlight position -5.0 -6.0 6.0 color 1.0 1.0 1.0 typ pointlight position 6.0 6.0 6.0 color 0.8 1.0 0.8 end object local typ csg_or typ csg_or typ cube transform scale 2.0 0.4 0.4 trans 0.0 -0.1 -0.1 material rot typ cube transform scale 0.4 2.0 0.4 trans -0.1 0.0 -0.1 material gruen typ csg_or typ cube transform scale 0.4 0.4 4.0 trans -0.1 -0.1 0.0 material blau typ paraboloid transform scale 1.0 1.0 3.0 trans 0.0 0.0 0.0 % rotz 180.0 material hellrot end #include material.dat material rot typ cube transform scale 0.4 2.0 0.4 trans -0.1 0.0 -0.1 material gruen typ csg_or typ cube transform scale 0.4 0.4 4.0 trans Flirt/Ftl/parabol.ftl000644 000316 000311 00000001262 06114644634 014643 0ustar00wrzlgup000000 000000 % testscene for paraboloid global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object local typ paraboloid material rot end #include material.dat kground 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position Flirt/Ftl/parsweep.ftl000644 000316 000311 00000001271 06114644634 015051 0ustar00wrzlgup000000 000000 % testscene for parabola sweep global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object local typ parabolasweep material rot end #include material.dat ound 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position Flirt/Ftl/plane.ftl000644 000316 000311 00000004224 06114644634 014323 0ustar00wrzlgup000000 000000 % platonische .... ? global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 20.0 12.0 20.0 lights local typ pointlight position 5.0 -5.0 5.0 color 1.0 1.0 1.0 typ pointlight position -6.0 6.0 6.0 color 0.5 0.5 0.5 typ pointlight position -6.0 0.0 -3.0 color 0.5 0.5 0.5 end #include platonic.dat object local typ csg_or typ csg_or typ csg_or typ named object dodecaeder transform rotz -30.0 rotx -12.0 trans 2.0 -2.0 0.0 material rot typ named object icosaeder transform rotz -30.0 rotx -12.0 trans 2.0 2.0 0.0 material rot typ csg_or typ named object tetraeder transform rotz 30.0 rotx 12.0 trans -2.0 2.0 0.0 material rot typ named object hexaeder transform rotz 30.0 rotx 12.0 trans -2.0 -2.0 0.0 material rot typ named object octaeder transform rotz 30.0 rotx 12.0 trans 0.0 -4.0 1.0 material rot end #include material.dat typ named object hexaeder transform rotz 30.0 rotx 12.0 trans -2.0 -2.0 0.0 material rot typ named object octaeder transform rotz 30Flirt/Ftl/platonic.dat000644 000316 000311 00000007627 06114644634 015032 0ustar00wrzlgup000000 000000 % the 5 platonic solids points tetraeder number 4 1.0 1.0 1.0 1.0 -1.0 -1.0 -1.0 1.0 -1.0 -1.0 -1.0 1.0 points hexaeder % aka cube number 8 1.0 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0 1.0 1.0 -1.0 -1.0 -1.0 1.0 1.0 -1.0 1.0 -1.0 -1.0 -1.0 1.0 -1.0 -1.0 -1.0 points octaeder number 6 1.0 0.0 0.0 -1.0 0.0 0.0 0.0 1.0 0.0 0.0 -1.0 0.0 0.0 0.0 1.0 0.0 0.0 -1.0 points icosaeder number 12 0.0 1.618 1.0 0.0 1.618 -1.0 0.0 -1.618 1.0 0.0 -1.618 -1.0 1.0 0.0 1.618 1.0 0.0 -1.618 -1.0 0.0 1.618 -1.0 0.0 -1.618 1.618 1.0 0.0 1.618 -1.0 0.0 -1.618 1.0 0.0 -1.618 -1.0 0.0 points dodecaeder number 20 0.0 0.618 1.618 0.0 0.618 -1.618 0.0 -0.618 1.618 0.0 -0.618 -1.618 1.618 0.0 0.618 1.618 0.0 -0.618 -1.618 0.0 0.618 -1.618 0.0 -0.618 0.618 1.618 0.0 0.618 -1.618 0.0 -0.618 1.618 0.0 -0.618 -1.618 0.0 1.0 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0 1.0 1.0 -1.0 -1.0 -1.0 1.0 1.0 -1.0 1.0 -1.0 -1.0 -1.0 1.0 -1.0 -1.0 -1.0 object tetraeder typ planes points tetraeder number 4 plane 1 3 2 plane 1 2 4 plane 1 4 3 plane 2 3 4 material default end object octaeder typ planes points octaeder number 4 doubleplane 1 3 6 2 doubleplane 1 5 3 2 doubleplane 1 4 5 2 doubleplane 1 6 4 2 material default end object hexaeder typ planes points hexaeder number 3 doubleplane 1 2 3 6 doubleplane 1 5 2 4 doubleplane 1 7 5 8 material default end object icosaeder typ planes points icosaeder number 10 doubleplane 1 2 9 4 doubleplane 1 9 5 4 doubleplane 1 5 7 4 doubleplane 1 7 11 4 doubleplane 1 11 2 4 doubleplane 10 5 9 8 doubleplane 9 6 10 12 doubleplane 6 9 2 7 doubleplane 2 8 6 3 doubleplane 8 2 11 5 material default end % very complicated to define, because of rounding errors % that's why not all points are used object dodecaeder typ planes points dodecaeder number 6 doubleplane 13 1 17 20 doubleplane 5 13 14 8 doubleplane 18 2 14 15 doubleplane 7 18 17 6 doubleplane 15 13 5 18 doubleplane 14 16 6 7 material default end 7 doubleplane 2 8 6 3 doubleplane 8 2 11 5 material default end % very cFlirt/Ftl/polyeder.ftl000644 000316 000311 00000014040 06114644634 015044 0ustar00wrzlgup000000 000000 % platonische .... ? global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 20.0 12.0 20.0 lights local typ pointlight position 5.0 -5.0 5.0 color 1.0 1.0 1.0 typ pointlight position -6.0 6.0 6.0 color 0.5 0.5 0.5 typ pointlight position -6.0 0.0 -3.0 color 0.5 0.5 0.5 end % the 5 platonic solids points tetraeder number 4 1.0 1.0 1.0 1.0 -1.0 -1.0 -1.0 1.0 -1.0 -1.0 -1.0 1.0 points hexaeder % aka cube number 8 1.0 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0 1.0 1.0 -1.0 -1.0 -1.0 1.0 1.0 -1.0 1.0 -1.0 -1.0 -1.0 1.0 -1.0 -1.0 -1.0 points octaeder number 6 1.0 0.0 0.0 -1.0 0.0 0.0 0.0 1.0 0.0 0.0 -1.0 0.0 0.0 0.0 1.0 0.0 0.0 -1.0 points icosaeder number 12 0.0 1.618 1.0 0.0 1.618 -1.0 0.0 -1.618 1.0 0.0 -1.618 -1.0 1.0 0.0 1.618 1.0 0.0 -1.618 -1.0 0.0 1.618 -1.0 0.0 -1.618 1.618 1.0 0.0 1.618 -1.0 0.0 -1.618 1.0 0.0 -1.618 -1.0 0.0 points dodecaeder number 20 0.0 0.618 1.618 0.0 0.618 -1.618 0.0 -0.618 1.618 0.0 -0.618 -1.618 1.618 0.0 0.618 1.618 0.0 -0.618 -1.618 0.0 0.618 -1.618 0.0 -0.618 0.618 1.618 0.0 0.618 -1.618 0.0 -0.618 1.618 0.0 -0.618 -1.618 0.0 1.0 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0 1.0 1.0 -1.0 -1.0 -1.0 1.0 1.0 -1.0 1.0 -1.0 -1.0 -1.0 1.0 -1.0 -1.0 -1.0 object tetraeder typ polyeder points tetraeder number 4 plane 1 3 2 plane 1 2 4 plane 1 4 3 plane 2 3 4 material default end object octaeder typ polyeder points octaeder number 4 doubleplane 1 3 6 2 doubleplane 1 5 3 2 doubleplane 1 4 5 2 doubleplane 1 6 4 2 material default end object hexaeder typ polyeder points hexaeder number 3 doubleplane 1 2 3 6 doubleplane 1 5 2 4 doubleplane 1 7 5 8 material default end object icosaeder typ polyeder points icosaeder number 10 doubleplane 1 2 9 4 doubleplane 1 9 5 4 doubleplane 1 5 7 4 doubleplane 1 7 11 4 doubleplane 1 11 2 4 doubleplane 10 5 9 8 doubleplane 9 6 10 12 doubleplane 6 9 2 7 doubleplane 2 8 6 3 doubleplane 8 2 11 5 material default end % very complicated to define, because of rounding errors % that's why not all points are used object dodecaeder typ polyeder points dodecaeder number 6 doubleplane 13 1 17 20 doubleplane 5 13 14 8 doubleplane 18 2 14 15 doubleplane 7 18 17 6 doubleplane 15 13 5 18 doubleplane 14 16 6 7 material default end object local typ csg_or typ csg_or typ csg_or typ named object dodecaeder transform rotz -30.0 rotx -12.0 trans 2.0 -2.0 0.0 material rot typ named object icosaeder transform rotz -30.0 rotx -12.0 trans 2.0 2.0 0.0 material rot typ csg_or typ named object tetraeder transform rotz 30.0 rotx 12.0 trans -2.0 2.0 0.0 material rot typ named object hexaeder transform rotz 30.0 rotx 12.0 trans -2.0 -2.0 0.0 material rot typ named object octaeder transform rotz 30.0 rotx 12.0 trans 0.0 -4.0 1.0 material rot end #include material.dat typ named object hexaeder transform rotz 30.0 rotx 12.0 trans -2.0 -2.0 0.0 material rot typ named object octaeder transform rotz 30.0 rotx 12.0 trans 0.0 -4.0 1.0 material Flirt/Ftl/repeat.ftl000644 000316 000311 00000001514 06114644634 014503 0ustar00wrzlgup000000 000000 % repeated object test global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 10.0 10.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object local typ repeat number 4 vector -0.2 0.2 1.0 typ sphere center 0.3 -0.3 -1.5 radius 0.80 material rot end #include material.dat typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.Flirt/Ftl/rft.ftl000644 000316 000311 00000006436 06114644634 014026 0ustar00wrzlgup000000 000000 global scene smallmidpoint camera rft lights two object rft material air background 0.48 0.6 0.9 #include scenes.dat camera rft eye 0.0 -10.0 20.0 lights two typ pointlight position 20.0 20.0 20.0 color 1.0 1.0 1.0 typ pointlight position 0.0 -10.0 20.0 color 0.7 0.7 0.8 end lights ambient typ ambient color 0.1 0.1 0.1 end object arc typ csg_and typ torus radius 0.2 material rot typ cube transform scale 1.25 1.25 0.5 trans 0.0 0.0 -0.25 material rot end object cylx typ cylinder transform scale 0.2 0.2 1.0 roty 90.0 material rot end object cyly typ cylinder transform scale 0.2 0.2 1.0 rotx -90.0 material rot end object rft typ csg_or % all together typ csg_or % r + vertical (f) typ csg_or % letter r typ named % vertical part (r) object cyly transform scale 1.0 1.2 1.0 trans 0.0 -0.2 0.0 typ named % arc (r) object arc transform rotz -90.0 trans 1.0 1.0 0.0 typ named % vertical part (f) object cyly transform scale 1.0 2.2 1.0 trans 1.0 -0.2 0.0 typ csg_or % full t + half f typ csg_or % upper part (f) typ named % arc (f) object arc transform rotz -90.0 trans 2.0 2.0 0.0 typ sphere % upper end (f) transform scale 0.2 0.2 0.2 trans 2.0 3.0 0.0 material rot typ csg_or % full (t),upper (f) typ csg_or % cross typ named % horizontal (t,f) object cylx transform scale 2.0 1.0 1.0 trans 1.0 2.0 0.0 typ named % vertical (t) object cyly transform scale 1.0 2.0 1.0 trans 2.0 1.0 0.0 typ named % arc (t) object arc transform scale -1.0 -1.0 1.0 trans 3.0 1.0 0.0 end #include material.dat cylx transform scale 2.0 1.0 1.0 trans 1.0 2.0 0.0 typ named % vertical (t) object cyly transform scaleFlirt/Ftl/rissplat.dat000644 000316 000311 00000007770 06114644635 015062 0ustar00wrzlgup000000 000000 % the 5 platonic solids (riss definition (not adapted yet)) % if you need'em do it yourself :-> (sadistic dracula grin) points tetraeder number 4 1.0 1.0 1.0 1.0 -1.0 -1.0 -1.0 1.0 -1.0 -1.0 -1.0 1.0 points hexaeder % aka cube number 8 1.0 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0 1.0 1.0 -1.0 -1.0 -1.0 1.0 1.0 -1.0 1.0 -1.0 -1.0 -1.0 1.0 -1.0 -1.0 -1.0 points octaeder number 6 1.0 0.0 0.0 -1.0 0.0 0.0 0.0 1.0 0.0 0.0 -1.0 0.0 0.0 0.0 1.0 0.0 0.0 -1.0 points icosaeder number 12 0.0 1.618 1.0 0.0 1.618 -1.0 0.0 -1.618 1.0 0.0 -1.618 -1.0 1.0 0.0 1.618 1.0 0.0 -1.618 -1.0 0.0 1.618 -1.0 0.0 -1.618 1.618 1.0 0.0 1.618 -1.0 0.0 -1.618 1.0 0.0 -1.618 -1.0 0.0 points dodecaeder number 20 0.0 0.618 1.618 0.0 0.618 -1.618 0.0 -0.618 1.618 0.0 -0.618 -1.618 1.618 0.0 0.618 1.618 0.0 -0.618 -1.618 0.0 0.618 -1.618 0.0 -0.618 0.618 1.618 0.0 0.618 -1.618 0.0 -0.618 1.618 0.0 -0.618 -1.618 0.0 1.0 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0 1.0 1.0 -1.0 -1.0 -1.0 1.0 1.0 -1.0 1.0 -1.0 -1.0 -1.0 1.0 -1.0 -1.0 -1.0 object tetraeder typ planes points tetraeder number 4 plane 1 3 2 plane 1 2 4 plane 1 4 3 plane 2 3 4 material default end object octaeder typ planes points octaeder number 4 doubleplane 1 3 6 2 doubleplane 1 5 3 2 doubleplane 1 4 5 2 doubleplane 1 6 4 2 material default end object hexaeder typ planes points hexaeder number 3 doubleplane 1 2 3 6 doubleplane 1 5 2 4 doubleplane 1 7 5 8 material default end object icosaeder typ planes points icosaeder number 10 doubleplane 1 2 9 4 doubleplane 1 9 5 4 doubleplane 1 5 7 4 doubleplane 1 7 11 4 doubleplane 1 11 2 4 doubleplane 10 5 9 8 doubleplane 9 6 10 12 doubleplane 6 9 2 7 doubleplane 2 8 6 3 doubleplane 8 2 11 5 material default end % very complicated to define, because of rounding errors % that's why not all points are used object dodecaeder typ planes points dodecaeder number 6 doubleplane 13 1 17 20 doubleplane 5 13 14 8 doubleplane 18 2 14 15 doubleplane 7 18 17 6 doubleplane 15 13 5 18 doubleplane 14 16 6 7 material default end douFlirt/Ftl/scenes.dat000644 000316 000311 00000005016 06114644635 014470 0ustar00wrzlgup000000 000000 % some scenes % recommended resolutions: % foto : 1000x 750 % farbsublimationsdrucker: 1452x1184 % --"-- / 2 : 1184x 725 % --"-- / 4 : 725x 590 % farbdrucker : 750x 500 % VGA : 800x 600 % --"-- : 640x 480 scene smallmidpoint xpix 128 ypix 96 shadow_rays true texturing false max_reflection 10 max_refraction 10 min_contribution 0.01 sampling midpoint scene smallmidpointtex xpix 128 ypix 96 shadow_rays true texturing true max_reflection 10 max_refraction 10 min_contribution 0.01 sampling midpoint scene smalladaptive xpix 128 ypix 96 shadow_rays true texturing false max_reflection 10 max_refraction 10 min_contribution 0.05 sampling adaptive max_level 2 scene midmidpoint xpix 256 ypix 192 shadow_rays true texturing false max_reflection 10 max_refraction 10 min_contribution 0.01 sampling midpoint scene midadaptive xpix 256 ypix 192 shadow_rays true texturing false max_reflection 10 max_refraction 10 min_contribution 0.01 sampling adaptive max_level 2 scene midmidpointtex xpix 256 ypix 192 shadow_rays true texturing true max_reflection 10 max_refraction 10 min_contribution 0.01 sampling midpoint scene adaptive xpix 725 ypix 590 shadow_rays true texturing false max_reflection 100 max_refraction 100 min_contribution 0.01 sampling adaptive max_level 2 scene adaptivetex xpix 725 ypix 590 shadow_rays true texturing true max_reflection 10 max_refraction 10 min_contribution 0.01 sampling adaptive max_level 2 590 shadow_rays true texturing false max_reflection 100 max_refraction 100 min_contribution 0.01 sampling adaptive max_level 2 scene adaptivetex xpix 725 ypix 590 shadow_rays true texturing true max_reflection 10 max_refraction 10 min_contribution 0.01 sampling adaptive max_leveFlirt/Ftl/smplmat1.ftl000644 000316 000311 00000013232 06114644636 014763 0ustar00wrzlgup000000 000000 global scene nosecondary camera smplmat1 lights smplmat1 object smplmat1 material air background 0.48 0.6 0.9 scene nosecondary xpix 128 ypix 128 shadow_rays true max_reflection 0 max_refraction 0 min_contribution 0.003906 sampling midpoint camera smplmat1 eye 0.0 -200.0 0.0 lights smplmat1 typ pointlight position 0.0 -200.0 0.0 color 0.5 0.5 0.5 typ pointlight position 200.0 -200.0 200.0 color 0.4 0.4 0.4 end object smplmat1 typ csg_or typ csg_or typ csg_or typ csg_or typ sphere center -3.0 0.0 3.0 radius 0.8 material mat1 typ sphere center -1.0 0.0 3.0 radius 0.8 material mat2 typ csg_or typ sphere center 1.0 0.0 3.0 radius 0.8 material mat3 typ sphere center 3.0 0.0 3.0 radius 0.8 material mat4 typ csg_or typ csg_or typ sphere center -3.0 0.0 1.0 radius 0.8 material mat5 typ sphere center -1.0 0.0 1.0 radius 0.8 material mat6 typ csg_or typ sphere center 1.0 0.0 1.0 radius 0.8 material mat7 typ sphere center 3.0 0.0 1.0 radius 0.8 material mat8 typ csg_or typ csg_or typ csg_or typ sphere center -3.0 0.0 -1.0 radius 0.8 material mat9 typ sphere center -1.0 0.0 -1.0 radius 0.8 material mat10 typ csg_or typ sphere center 1.0 0.0 -1.0 radius 0.8 material mat11 typ sphere center 3.0 0.0 -1.0 radius 0.8 material mat12 typ csg_or typ csg_or typ sphere center -3.0 0.0 -3.0 radius 0.8 material mat13 typ sphere center -1.0 0.0 -3.0 radius 0.8 material mat14 typ csg_or typ sphere center 1.0 0.0 -3.0 radius 0.8 material mat15 typ sphere center 3.0 0.0 -3.0 radius 0.8 material mat16 end material mat1 smoothness 0.00000 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat2 smoothness 0.06666 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat3 smoothness 0.13333 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat4 smoothness 0.20000 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat5 smoothness 0.26666 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat6 smoothness 0.33333 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat7 smoothness 0.40000 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat8 smoothness 0.46666 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat9 smoothness 0.53333 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat10 smoothness 0.60000 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat11 smoothness 0.66666 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat12 smoothness 0.73333 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat13 smoothness 0.80000 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat14 smoothness 0.86666 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat15 smoothness 0.93333 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat16 smoothness 1.00000 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 #include material.dat mat14 smoothness 0.86666 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat15 smoothness 0.93333 metalness 0.5 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat16 smoothFlirt/Ftl/smplmat2.ftl000644 000316 000311 00000016314 06114644636 014770 0ustar00wrzlgup000000 000000 global scene noreflection camera smplmat2 lights smplmat2 object smplmat2 material air background 0.48 0.6 0.9 scene noreflection xpix 128 ypix 128 shadow_rays true max_reflection 0 max_refraction 10 min_contribution 0.003906 sampling midpoint camera smplmat2 eye 0.0 -200.0 0.0 lights smplmat2 typ pointlight position 0.0 -200.0 0.0 color 0.5 0.5 0.5 typ pointlight position 200.0 -200.0 200.0 color 0.4 0.4 0.4 end object cylx typ cylinder transform scale 0.2 0.2 8.0 roty 90 trans -4.0 0.0 0.0 material mat0 end object cylz typ cylinder transform scale 0.2 0.2 8.0 trans 0.0 0.0 -4.0 material mat0 end object simplmat2 typ csg_or typ csg_or typ csg_or typ csg_or typ csg_or typ sphere center -3.0 0.0 3.0 radius 0.8 material mat1 typ sphere center -1.0 0.0 3.0 radius 0.8 material mat2 typ csg_or typ sphere center 1.0 0.0 3.0 radius 0.8 material mat3 typ sphere center 3.0 0.0 3.0 radius 0.8 material mat4 typ csg_or typ csg_or typ sphere center -3.0 0.0 1.0 radius 0.8 material mat5 typ sphere center -1.0 0.0 1.0 radius 0.8 material mat6 typ csg_or typ sphere center 1.0 0.0 1.0 radius 0.8 material mat7 typ sphere center 3.0 0.0 1.0 radius 0.8 material mat8 typ csg_or typ csg_or typ csg_or typ sphere center -3.0 0.0 -1.0 radius 0.8 material mat9 typ sphere center -1.0 0.0 -1.0 radius 0.8 material mat10 typ csg_or typ sphere center 1.0 0.0 -1.0 radius 0.8 material mat11 typ sphere center 3.0 0.0 -1.0 radius 0.8 material mat12 typ csg_or typ csg_or typ sphere center -3.0 0.0 -3.0 radius 0.8 material mat13 typ sphere center -1.0 0.0 -3.0 radius 0.8 material mat14 typ csg_or typ sphere center 1.0 0.0 -3.0 radius 0.8 material mat15 typ sphere center 3.0 0.0 -3.0 radius 0.8 material mat16 typ csg_or typ csg_or typ csg_or typ named object cylz transform trans 3.0 2.0 0.0 typ named object cylz transform trans 1.0 2.0 0.0 typ csg_or typ named object cylz transform trans -1.0 2.0 0.0 typ named object cylz transform trans -3.0 2.0 0.0 typ csg_or typ csg_or typ named object cylx transform trans 0.0 2.0 3.0 typ named object cylx transform trans 0.0 2.0 1.0 typ csg_or typ named object cylx transform trans 0.0 2.0 -1.0 typ named object cylx transform trans 0.0 2.0 -3.0 end material mat0 smoothness 0.0 metalness 0.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat1 smoothness 0.5 metalness 0.0 transparency 0.00000 refract_index 1.0 color 0.8 0.8 0.8 material mat2 smoothness 0.5 metalness 0.0 transparency 0.06666 refract_index 1.0 color 0.8 0.8 0.8 material mat3 smoothness 0.5 metalness 0.0 transparency 0.13333 refract_index 1.0 color 0.8 0.8 0.8 material mat4 smoothness 0.5 metalness 0.0 transparency 0.20000 refract_index 1.0 color 0.8 0.8 0.8 material mat5 smoothness 0.5 metalness 0.0 transparency 0.26666 refract_index 1.0 color 0.8 0.8 0.8 material mat6 smoothness 0.5 metalness 0.0 transparency 0.33333 refract_index 1.0 color 0.8 0.8 0.8 material mat7 smoothness 0.5 metalness 0.0 transparency 0.40000 refract_index 1.0 color 0.8 0.8 0.8 material mat8 smoothness 0.5 metalness 0.0 transparency 0.46666 refract_index 1.0 color 0.8 0.8 0.8 material mat9 smoothness 0.5 metalness 0.0 transparency 0.53333 refract_index 1.0 color 0.8 0.8 0.8 material mat10 smoothness 0.5 metalness 0.0 transparency 0.60000 refract_index 1.0 color 0.8 0.8 0.8 material mat11 smoothness 0.5 metalness 0.0 transparency 0.66666 refract_index 1.0 color 0.8 0.8 0.8 material mat12 smoothness 0.5 metalness 0.0 transparency 0.73333 refract_index 1.0 color 0.8 0.8 0.8 material mat13 smoothness 0.5 metalness 0.0 transparency 0.80000 refract_index 1.0 color 0.8 0.8 0.8 material mat14 smoothness 0.5 metalness 0.0 transparency 0.86666 refract_index 1.0 color 0.8 0.8 0.8 material mat15 smoothness 0.5 metalness 0.0 transparency 0.93333 refract_index 1.0 color 0.8 0.8 0.8 material mat16 smoothness 0.5 metalness 0.0 transparency 1.00000 refract_index 1.0 color 0.8 0.8 0.8 #include material.dat mat14 smoothness 0.5 metalness 0.0 transparency 0.86666 refract_index 1.0 color 0.8 0.8 0.8 material mat15 smoothness 0.5 metalness 0.0 transparency 0.93333 refract_index 1.0 color 0.8 Flirt/Ftl/smplmat3.ftl000644 000316 000311 00000016247 06114644636 014776 0ustar00wrzlgup000000 000000 global scene noreflection camera smplmat3 lights smplmat3 object smplmat3 material air background 0.48 0.6 0.9 scene noreflection xpix 128 ypix 128 shadow_rays true max_reflection 0 max_refraction 10 min_contribution 0.003906 sampling midpoint camera smplmat3 eye 0.0 -200.0 0.0 lights smplmat3 typ pointlight position 0.0 -200.0 0.0 color 0.5 0.5 0.5 typ pointlight position 200.0 -200.0 200.0 color 0.4 0.4 0.4 end object cylx typ cylinder transform scale 0.2 0.2 8.0 roty 90 trans -4.0 0.0 0.0 material mat0 end object cylz typ cylinder transform scale 0.2 0.2 8.0 trans 0.0 0.0 -4.0 material mat0 end object simplmat3 typ csg_or typ csg_or typ csg_or typ csg_or typ csg_or typ sphere center -3.0 0.0 3.0 radius 0.8 material mat1 typ sphere center -1.0 0.0 3.0 radius 0.8 material mat2 typ csg_or typ sphere center 1.0 0.0 3.0 radius 0.8 material mat3 typ sphere center 3.0 0.0 3.0 radius 0.8 material mat4 typ csg_or typ csg_or typ sphere center -3.0 0.0 1.0 radius 0.8 material mat5 typ sphere center -1.0 0.0 1.0 radius 0.8 material mat6 typ csg_or typ sphere center 1.0 0.0 1.0 radius 0.8 material mat7 typ sphere center 3.0 0.0 1.0 radius 0.8 material mat8 typ csg_or typ csg_or typ csg_or typ sphere center -3.0 0.0 -1.0 radius 0.8 material mat9 typ sphere center -1.0 0.0 -1.0 radius 0.8 material mat10 typ csg_or typ sphere center 1.0 0.0 -1.0 radius 0.8 material mat11 typ sphere center 3.0 0.0 -1.0 radius 0.8 material mat12 typ csg_or typ csg_or typ sphere center -3.0 0.0 -3.0 radius 0.8 material mat13 typ sphere center -1.0 0.0 -3.0 radius 0.8 material mat14 typ csg_or typ sphere center 1.0 0.0 -3.0 radius 0.8 material mat15 typ sphere center 3.0 0.0 -3.0 radius 0.8 material mat16 typ csg_or typ csg_or typ csg_or typ named object cylz transform trans 3.0 2.0 0.0 typ named object cylz transform trans 1.0 2.0 0.0 typ csg_or typ named object cylz transform trans -1.0 2.0 0.0 typ named object cylz transform trans -3.0 2.0 0.0 typ csg_or typ csg_or typ named object cylx transform trans 0.0 2.0 3.0 typ named object cylx transform trans 0.0 2.0 1.0 typ csg_or typ named object cylx transform trans 0.0 2.0 -1.0 typ named object cylx transform trans 0.0 2.0 -3.0 end material mat0 smoothness 0.0 metalness 0.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat1 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 0.5 color 0.8 0.8 0.8 material mat2 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 0.548 color 0.8 0.8 0.8 material mat3 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 0.602 color 0.8 0.8 0.8 material mat4 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 0.660 color 0.8 0.8 0.8 material mat5 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 0.724 color 0.8 0.8 0.8 material mat6 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 0.794 color 0.8 0.8 0.8 material mat7 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 0.871 color 0.8 0.8 0.8 material mat8 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 0.955 color 0.8 0.8 0.8 material mat9 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 1.047 color 0.8 0.8 0.8 material mat10 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 1.149 color 0.8 0.8 0.8 material mat11 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 1.260 color 0.8 0.8 0.8 material mat12 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 1.382 color 0.8 0.8 0.8 material mat13 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 1.516 color 0.8 0.8 0.8 material mat14 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 1.662 color 0.8 0.8 0.8 material mat15 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 1.823 color 0.8 0.8 0.8 material mat16 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 2.0 color 0.8 0.8 0.8 #include material.dat rial mat14 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 1.662 color 0.8 0.8 0.8 material mat15 smoothness 0.5 metalness 0.0 transparency 1.0 refract_index 1.823 color 0.8 0.8 0.8 material Flirt/Ftl/smplmat4.ftl000644 000316 000311 00000013224 06114644636 014767 0ustar00wrzlgup000000 000000 global scene smplmat4 camera smplmat4 lights smplmat4 object smplmat4 material air background 0.3 0.3 0.3 scene smplmat4 xpix 128 ypix 128 shadow_rays true max_reflection 10 max_refraction 10 min_contribution 0.003906 sampling midpoint camera smplmat4 eye 0.0 -200.0 0.0 lights smplmat4 typ pointlight position 0.0 -200.0 0.0 color 0.5 0.5 0.5 typ pointlight position 200.0 -200.0 200.0 color 0.4 0.4 0.4 end object smplmat4 typ csg_or typ csg_or typ csg_or typ csg_or typ sphere center -3.0 0.0 3.0 radius 0.8 material mat1 typ sphere center -1.0 0.0 3.0 radius 0.8 material mat2 typ csg_or typ sphere center 1.0 0.0 3.0 radius 0.8 material mat3 typ sphere center 3.0 0.0 3.0 radius 0.8 material mat4 typ csg_or typ csg_or typ sphere center -3.0 0.0 1.0 radius 0.8 material mat5 typ sphere center -1.0 0.0 1.0 radius 0.8 material mat6 typ csg_or typ sphere center 1.0 0.0 1.0 radius 0.8 material mat7 typ sphere center 3.0 0.0 1.0 radius 0.8 material mat8 typ csg_or typ csg_or typ csg_or typ sphere center -3.0 0.0 -1.0 radius 0.8 material mat9 typ sphere center -1.0 0.0 -1.0 radius 0.8 material mat10 typ csg_or typ sphere center 1.0 0.0 -1.0 radius 0.8 material mat11 typ sphere center 3.0 0.0 -1.0 radius 0.8 material mat12 typ csg_or typ csg_or typ sphere center -3.0 0.0 -3.0 radius 0.8 material mat13 typ sphere center -1.0 0.0 -3.0 radius 0.8 material mat14 typ csg_or typ sphere center 1.0 0.0 -3.0 radius 0.8 material mat15 typ sphere center 3.0 0.0 -3.0 radius 0.8 material mat16 material mat1 smoothness 0.00000 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat2 smoothness 0.06666 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat3 smoothness 0.13333 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat4 smoothness 0.20000 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat5 smoothness 0.26666 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat6 smoothness 0.33333 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat7 smoothness 0.40000 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat8 smoothness 0.46666 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat9 smoothness 0.53333 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat10 smoothness 0.60000 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat11 smoothness 0.66666 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat12 smoothness 0.73333 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat13 smoothness 0.80000 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat14 smoothness 0.86666 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat15 smoothness 0.93333 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat16 smoothness 1.00000 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 #include material.dat mat14 smoothness 0.86666 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat15 smoothness 0.93333 metalness 1.0 transparency 0.0 refract_index 1.0 color 1.0 1.0 1.0 material mat16 smoothness Flirt/Ftl/test.ftl000644 000316 000311 00000001671 06114644636 014210 0ustar00wrzlgup000000 000000 global scene smallmidpoint camera stest lights stest object stest material air background 0.48 0.6 0.9 #include scenes.dat camera stest eye 5.0 5.0 5.0 % direction -5.0 -5.0 -5.0 % zoom 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ sphere center 0.0 0.0 -0.5 radius 0.5 material gold typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material rot end #include material.dat olor 1.0 1.0 1.0 typ pointlight Flirt/Ftl/test_.ftl000644 000316 000311 00000001662 06114644636 014347 0ustar00wrzlgup000000 000000 global scene adaptive camera stest lights stest object stest material air background 0.48 0.6 0.9 #include scenes.dat camera stest eye 5.0 5.0 5.0 direction -5.0 -5.0 -5.0 zoom 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ sphere center 0.0 0.0 -0.5 radius 0.5 material gold typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material rot end #include material.dat olor 1.0 1.0 1.0 typ pointlight positioFlirt/Ftl/testa.ftl000644 000316 000311 00000001663 06114644636 014352 0ustar00wrzlgup000000 000000 global scene adaptive camera stest lights stest object stest material air background 0.48 0.6 0.9 #include scenes.dat camera stest eye 5.0 5.0 5.0 direction -5.0 -5.0 -5.0 zoom 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ sphere center 0.15 0.0 -0.5 radius 0.5 material gold typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material rot end #include material.dat lor 1.0 1.0 1.0 typ pointlight positioFlirt/Ftl/testand.ftl000644 000316 000311 00000001611 06114644636 014665 0ustar00wrzlgup000000 000000 % primitive testszene global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object local typ csg_and typ sphere center 0.0 0.0 0.5 radius 0.7 material gold typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material rot end #include material.dat 2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 Flirt/Ftl/testb.ftl000644 000316 000311 00000001662 06114644636 014352 0ustar00wrzlgup000000 000000 global scene adaptive camera stest lights stest object stest material air background 0.48 0.6 0.9 #include scenes.dat camera stest eye 5.0 5.0 5.0 direction -5.0 -5.0 -5.0 zoom 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ sphere center 0.0 0.0 -0.5 radius 0.5 material gold typ cube min -0.3 -0.5 0.0 max 0.7 0.5 1.0 material rot end #include material.dat olor 1.0 1.0 1.0 typ pointlight positioFlirt/Ftl/testc.ftl000644 000316 000311 00000001662 06114644636 014353 0ustar00wrzlgup000000 000000 global scene adaptive camera stest lights stest object stest material air background 0.48 0.6 0.9 #include scenes.dat camera stest eye 5.0 5.0 4.0 direction -5.0 -5.0 -4.0 zoom 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ sphere center 0.0 0.0 -0.5 radius 0.5 material gold typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material rot end #include material.dat olor 1.0 1.0 1.0 typ pointlight positioFlirt/Ftl/testd.ftl000644 000316 000311 00000001662 06114644636 014354 0ustar00wrzlgup000000 000000 global scene adaptive camera stest lights stest object stest material air background 0.48 0.6 0.9 #include scenes.dat camera stest eye 5.0 5.0 5.0 direction -5.0 -5.0 -5.0 zoom 2.3 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ sphere center 0.0 0.0 -0.5 radius 0.5 material gold typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material rot end #include material.dat olor 1.0 1.0 1.0 typ pointlight positioFlirt/Ftl/teste.ftl000644 000316 000311 00000001662 06114644636 014355 0ustar00wrzlgup000000 000000 global scene adaptive camera stest lights stest object stest material air background 0.48 0.6 0.9 #include scenes.dat camera stest eye 5.0 5.0 5.0 direction -5.0 -5.0 -5.0 zoom 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ sphere center 0.0 0.0 -0.7 radius 0.7 material gold typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material rot end #include material.dat olor 1.0 1.0 1.0 typ pointlight positioFlirt/Ftl/tested.ftl000644 000316 000311 00000001667 06114644636 014526 0ustar00wrzlgup000000 000000 global scene smallmidpoint camera stest lights stest object stest material air background 0.48 0.6 0.9 #include scenes.dat camera stest eye 5.0 5.0 5.0 direction -5.0 -5.0 -5.0 zoom 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ sphere center 0.0 0.0 -0.5 radius 0.5 material glas typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material rot end #include material.dat olor 1.0 1.0 1.0 typ pointlight poFlirt/Ftl/testf.ftl000644 000316 000311 00000001662 06114644636 014356 0ustar00wrzlgup000000 000000 global scene adaptive camera stest lights stest object stest material air background 0.48 0.6 0.9 #include scenes.dat camera stest eye 5.0 5.0 5.0 direction -5.0 -5.0 -5.0 zoom 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ sphere center 0.0 0.0 -0.5 radius 0.5 material gold typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material rot end #include material.dat olor 1.0 1.0 1.0 typ pointlight positioFlirt/Ftl/testg.ftl000644 000316 000311 00000001663 06114644636 014360 0ustar00wrzlgup000000 000000 global scene adaptive camera stest lights stest object stest material air background 0.48 0.6 0.9 #include scenes.dat camera stest eye 5.0 5.0 5.0 direction -5.0 -5.0 -5.0 zoom 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ sphere center 0.15 0.0 -0.5 radius 0.5 material gold typ cube min -0.7 -0.5 0.0 max 0.3 0.5 1.0 material rot end #include material.dat lor 1.0 1.0 1.0 typ pointlight positioFlirt/Ftl/testrot.ftl000644 000316 000311 00000001675 06114644636 014741 0ustar00wrzlgup000000 000000 % primitive testszene mit transformationen global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object local typ csg_or typ sphere transform scale 0.3 0.7 0.5 trans 0.0 0.0 -0.5 material gold typ cube transform rotx 45 trans -0.5 -0.5 0.0 material rot end #include material.dat 1.0 1.0 1.0 typ pointlight posiFlirt/Ftl/testsub.ftl000644 000316 000311 00000001613 06114644636 014716 0ustar00wrzlgup000000 000000 % primitive testszene global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object local typ csg_sub typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material gold typ sphere center 0.0 0.0 0.5 radius 0.65 material gold end #include material.dat 0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 Flirt/Ftl/testtex.ftl000644 000316 000311 00000003745 06114644637 014736 0ustar00wrzlgup000000 000000 global scene smallmidpoint camera stest lights stest object stest material air background 0.48 0.6 0.9 scene smallmidpoint xpix 128 ypix 48 shadow_rays true texturing true max_reflection 10 max_refraction 10 min_contribution 0.003906 sampling midpoint camera stest eye 10.0 10.0 6.0 direction -10.0 -10.0 -5.0 zoom 1.1 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end points test number 3 -1.0 1.0 0.0 -1.5 1.5 1.0 -2.0 2.0 0.0 texture goldchecker typ checker2d number_u 7 number_v 7 typ materialarray1d number 1 material gold end object stest typ csg_or typ csg_or typ cylinder transform trans 3.0 -3.0 0.0 material rot texture goldchecker typ cone transform rotx 180.0 trans 1.0 -1.0 1.0 material rot texture goldchecker typ csg_or typ torus radius 0.5 transform scale 0.7 0.7 0.7 trans -3.0 3.0 0.0 material rot texture goldchecker typ triangle points test vertices 1 2 3 material rot % texture goldchecker end #include material.dat rot texture Flirt/Ftl/testw.ftl000644 000316 000311 00000001662 06114644637 014400 0ustar00wrzlgup000000 000000 global scene adaptive camera stest lights stest object stest material air background 0.48 0.6 0.9 #include scenes.dat camera stest eye 5.0 5.0 5.0 direction -5.0 -5.0 -5.0 zoom 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ sphere center 0.0 0.0 -0.7 radius 0.7 material gold typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material rot end #include material.dat olor 1.0 1.0 1.0 typ pointlight positioFlirt/Ftl/testx.ftl000644 000316 000311 00000001664 06114644637 014403 0ustar00wrzlgup000000 000000 global scene adaptive camera stest lights stest object stest material air background 0.48 0.6 0.9 #include scenes.dat camera stest eye 5.0 5.0 5.0 direction -5.0 -5.0 -5.0 zoom 2.0 lights stest typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ pointlight position 5.0 0.0 0.0 color 0.7 0.7 0.8 end object stest typ csg_or typ sphere center 0.0 0.0 -0.7 radius 0.7 material gold typ cube min -0.5 -0.5 0.0 max 0.5 0.5 1.0 material glas1 end #include material.dat or 1.0 1.0 1.0 typ pointlight positioFlirt/Ftl/tetraede.ftl000644 000316 000311 00000004245 06114644637 015027 0ustar00wrzlgup000000 000000 % platonische .... ? global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 20.0 12.0 20.0 lights local typ pointlight position 5.0 -5.0 5.0 color 1.0 1.0 1.0 typ pointlight position -6.0 6.0 6.0 color 0.5 0.5 0.5 typ pointlight position -6.0 0.0 -3.0 color 0.5 0.5 0.5 end #include platonicpoly.dat object local typ csg_or % typ csg_or % typ csg_or % typ named % object dodecaeder % transform rotz -30.0 % rotx -12.0 % trans 2.0 -2.0 0.0 % material rot % typ named % object icosaeder % transform rotz -30.0 % rotx -12.0 % trans 2.0 2.0 0.0 % material rot typ csg_or typ named object tetraeder transform rotz 30.0 rotx 12.0 trans -2.0 2.0 0.0 material rot typ named object tetraeder transform rotz 30.0 rotx 12.0 trans -2.0 -2.0 0.0 material rot typ named object tetraeder transform rotz 30.0 rotx 12.0 trans 0.0 -4.0 1.0 material rot end #include material.dat typ named object tetraeder transform rotz 30.0 rotx 12.0 trans -2.0 -2.0 0.0 material rot typ named object tetraeder transformFlirt/Ftl/torus.ftl000644 000316 000311 00000001337 06114644637 014405 0ustar00wrzlgup000000 000000 % testscene for torus global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ ambient color 0.1 0.1 0.1 end object local typ csg_and typ cube min -2 -2 -2 max 2 2 0 material rot typ torus radius 1.2 material rot end #include material.dat dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ ambient color 0.1 Flirt/Ftl/torus1.ftl000644 000316 000311 00000001276 06114644637 014470 0ustar00wrzlgup000000 000000 % testscene for torus global scene smallmidpoint camera local lights local object local material air background 0.48 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ ambient color 0.1 0.1 0.1 end object local typ torus radius 0.05 transform scale 1.0 1.0 10.0 material gold end #include material.dat 0.6 0.9 #include scenes.dat camera local eye 5.0 5.0 5.0 lights local typ pointlight position 2.0 -2.0 5.0 color 1.0 1.0 1.0 typ ambient color 0.1 Flirt/Ftl/torusbox.ftl000644 000316 000311 00000002301 06114644637 015106 0ustar00wrzlgup000000 000000 % test bspline global scene bspline camera bspline lights bspline object bspline material air background 0.48 0.6 0.9 scene bspline xpix 512 ypix 512 shadow_rays true max_reflection 10 max_refraction 10 min_contribution 0.003906 % 1/256 sampling midpoint % sampling adaptive % max_level 2 camera bspline % eye 1.0 1.0 30.0 eye 6.0 8.5 8.0 lights bspline typ pointlight position 0.0 0.0 10.0 color 1.0 1.0 1.0 typ pointlight position 15.0 -10.0 15.0 color 1.0 1.0 1.0 end object bspline typ csg_or typ torus radius 0.5 material rot typ csg_or typ cube min -1.5 -1.5 -0.5 max 1.5 1.5 0.0 material visualizeinside typ cube min -1.6 -1.6 -0.6 max 1.6 1.6 0.1 material visualizeborder end #include material.dat pointlight position 15.0 -10.0 15.0 color 1.0 1.0 1.0 end object bspline typ csg_or typ torus radius 0.5 material rot typ csg_or typ cube min -1.5 -1.5 -0.5 max Flirt/Ftl/triangle.ftl000644 000316 000311 00000004771 06114644637 015043 0ustar00wrzlgup000000 000000 % dreieckstests global scene smallmidpoint % scene smalladaptive camera tri lights tri object tri material air background 0.48 0.6 0.9 #include scenes.dat camera tri eye 5.0 0.0 2.0 lights tri typ pointlight position 5.0 0.0 5.0 color 0.6 0.6 0.6 typ pointlight position 5.0 0.0 -6.0 color 0.4 0.4 0.4 end points tesselated_sphere number 6 1.0 0.0 0.0 -1.0 0.0 0.0 0.0 1.0 0.0 0.0 -1.0 0.0 0.0 0.0 1.0 0.0 0.0 -1.0 object tri1 typ csg_or typ csg_or typ triangle points tesselated_sphere vertices 5 3 1 normals 5 3 1 material rot typ triangle points tesselated_sphere vertices 5 4 1 normals 5 4 1 material rot typ csg_or typ triangle points tesselated_sphere vertices 1 3 6 normals 1 3 6 material rot typ triangle points tesselated_sphere vertices 4 1 6 normals 4 1 6 material rot end object tri2 typ csg_or typ csg_or typ triangle points tesselated_sphere vertices 5 1 3 % normals 5 1 3 material rot typ triangle points tesselated_sphere vertices 5 1 4 % normals 5 1 4 material rot typ csg_or typ triangle points tesselated_sphere vertices 6 3 1 % normals 6 3 1 material rot typ triangle points tesselated_sphere vertices 6 1 4 % normals 6 1 4 material rot end object tri typ csg_or typ named object tri1 transform trans 0.0 1.0 0.0 typ named object tri2 transform trans 0.0 -1.0 0.0 end #include material.dat ed_spheFlirt/Makefile000644 000316 000311 00000003421 06114645505 013424 0ustar00wrzlgup000000 000000 ############################################################################### # Standard-Makefile for FLIRT ############################################################################### TARGET = flirt LDFLAGS = -lm LOCALLIBS = ## if you have GCC use the Macros below #CC = gcc #CFLAGS = -Wall -Wtraditional -Wshadow -Wpointer-arith -Wcast-qual \ # -Wcast-align -Wconversion -Wmissing-prototypes -Wwrite-strings \ # -funsigned-char \ # -g # -O2 -fomit-frame-pointer -ffast-math -finline-functions ##if you have an ANSI-C Compiler use the Macros below CC = cc CFLAGS = -g -fullwarn SRCS = camera.c bounding.c color.c flirt.c geometr3.c hitlist.c init.c \ light.c material.c numeric.c objects.c random.c raycount.c \ raytrace.c readdata.c rgbinout.c rissmat.c sampling.c scene.c \ setup.c smplmat.c stdmat.c symbols.c system.c texture.c writdata.c \ akimanoise.c \ csg.c mcsg.c named.c repeat.c grid.c octree.c cylcube.c esbuf.c \ scube.c ssphere.c cube.c sphere.c cone.c cylinder.c parabol.c \ parsweep.c hyperbol.c hypsweep.c torus.c hyperell.c plane.c \ triangle.c environm.c fived.cc OBJS = camera.o bounding.o color.o flirt.o geometr3.o hitlist.o init.o \ light.o material.o numeric.o objects.o random.o raycount.o \ raytrace.o readdata.o rgbinout.o rissmat.o sampling.o scene.o \ setup.o smplmat.o stdmat.o symbols.o system.o texture.o writdata.o \ akimanoise.o \ csg.o mcsg.o named.o repeat.o grid.o octree.o cylcube.o esbuf.o \ scube.o ssphere.o cube.o sphere.o cone.o cylinder.o parabol.o \ parsweep.o hyperbol.o hypsweep.o torus.o hyperell.o plane.o \ triangle.o environm.o fived.o .c.o: $(CC) $(CFLAGS) -c $< $(TARGET) : $(OBJS) $(LOCALLIBS) if [ -f $@ ]; then rm -f $@~; mv $@ $@~; fi $(CC) -o $@ $(OBJS) $(LDFLAGS) $(LOCALLIBS) clean: rm *.o flirt g.o scene.o \ setup.o smplmat.o stdmat.o symbols.o system.o texture.o writdata.o \ akimanoise.o \ csg.o mcsg.o named.o repeat.o grid.o octree.o cylcube.o esbuf.o \ scube.o ssphere.o cube.o sphere.o cone.o cylinder.o parabol.o \ Flirt/README000644 000316 000311 00000001701 06114645425 012644 0ustar00wrzlgup000000 000000 Software available here is provided without any guarantees. All software is provided for non-comerical use only (!), though comercial agreements are possible on request. If you want to use parts of this software please feel free, but include the copyright notice below: ----------------------------------------------------------------------- Copyright (c) by Wolfgang Stuerzlinger (wRZL), 1991-1996. This code may be used only for non-commercial purposes! ----------------------------------------------------------------------- As this software is still evolving, I know of a few bugs in the version available here, which I have fixed since. If you stumble across one and get stuck, send me a message. ----------------------------------------------------------------------- FLIRT Raytracer: usage of the script file for ray tracing to make life easier: f [options] for further documentation see the Doc/ directory - but the files are in German! urposes! -----------------------------------------------------Flirt/akimanoise.c000644 000316 000311 00000013721 06103226504 014244 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : akimanoise.c used for procedure d3wood and d3marble in texture.c DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "random.f" #include "numeric.f" #include "geometr3.f" #include "material.f" #include "readdata.f" #include "symbols.f" #include "writdata.f" #include "texture.f" #include "objects.d" #include "system.f" #include "akimanoise.f" #include "akimanoise.d" void read_trans(TEXTURE *tex) { UINT i, j; for(i=0; i<4; i++) for(j=0; j<3; j++) if(i == j) tex->solidtex.world2tex.e[i][j] = 1.0; else tex->solidtex.world2tex.e[i][j] = 0.0; if(matchconststring("transform")) { nexttoken(); readmat3(&(tex->solidtex.world2tex)); } } FLOAT noise_weight(FLOAT t) { FLOAT tabs; tabs = f_abs(t); return ((tabs+tabs-3.0)*tabs*tabs + 1.0); } void noise_init(TEXTURE* tex) { short i1,i2,tmp; short i; tex->solidtex.noise.n = 4096; tex->solidtex.noise.P = (short*)smalloc(SYSTEM,sizeof(short)*tex->solidtex.noise.n); tex->solidtex.noise.N = (FLOAT**)smalloc(SYSTEM,sizeof(FLOAT*)*tex->solidtex.noise.n); for(i=0; isolidtex.noise.n; i++) tex->solidtex.noise.N[i] = (FLOAT*)smalloc(SYSTEM,sizeof(FLOAT[3])); seed_rand(clockticks()); for(i=0; isolidtex.noise.n; i++) tex->solidtex.noise.P[i] = i; for(i=0; i<7*tex->solidtex.noise.n; i++) { i1 = (short)(rand01()*((tex->solidtex.noise.n)-1)); i2 = (short)(rand01()*((tex->solidtex.noise.n)-1)); tmp=tex->solidtex.noise.P[i1]; tex->solidtex.noise.P[i1]=tex->solidtex.noise.P[i2]; tex->solidtex.noise.P[i2]=tmp; } for(i=0; isolidtex.noise.n; i++) { FLOAT x,y,z,len; do { x = rand01()*2.0 - 1.0; y = rand01()*2.0 - 1.0; z = rand01()*2.0 - 1.0; len = f_sqrt(x*x + y*y + z*z); } while(len > 1.0); tex->solidtex.noise.N[i][0] = x/len; tex->solidtex.noise.N[i][1] = y/len; tex->solidtex.noise.N[i][2] = z/len; } message("Initialisation for n=%d done \n", tex->solidtex.noise.n); } FLOAT noise_get(TEXTURE tex,FLOAT x, FLOAT y, FLOAT z) { short a, b, c, i; FLOAT sum = 0.0, u, v, w, we; INT n; for(a=(short)x; a <= ((short)x)+1; a++) for(b=(short)(y); b <= ((short)y)+1; b++) for(c=(short)z; c <= ((short)z)+1; c++) { u = (x-a); v = (y-b); w = (z-c); n = tex.solidtex.noise.n; we = noise_weight(u) * noise_weight(v) * noise_weight(w); i = tex.solidtex.noise.P[(a+tex.solidtex.noise.P[(b+tex.solidtex.noise.P[c%n]) % n]) % n]; if ((i > n) || (i < 0)){ i = n-1; } sum += we * (tex.solidtex.noise.N[i][0] * u + tex.solidtex.noise.N[i][1] * v + tex.solidtex.noise.N[i][2] * w); } return(sum); } FLOAT noise_get_T(TEXTURE tex,FLOAT x, FLOAT y, FLOAT z) { FLOAT sum = 0.0, f; for(f=2.0; f<=256.0; f*=2.0) sum += 1/f*noise_get(tex,f*x, f*y, f*z); return (sum); } FLOAT noise_get_absT(TEXTURE tex,FLOAT x, FLOAT y, FLOAT z) { FLOAT sum = 0.0, f; for(f=2.0; f<=256.0; f*=2.0) sum += 1/f*f_abs(noise_get(tex, f*x, f*y, f*z)); return (sum); } AKIMA akima_read(AKIMA *akima) { short j; short i; FLOAT *q, *dy; akima->num = (short)readuint() + 1; akima->cpnt = (PNT2*)smalloc(SYSTEM,sizeof(PNT2)*akima->num); for(j=0; jnum-1; j++) { akima->cpnt[j].x = readreal(); message("%lf ", akima->cpnt[j].x); } message(" \n"); for(j=0; jnum-1; j++) { akima->cpnt[j].y = readreal(); message("%lf ", akima->cpnt[j].y); } message(" \n"); /* Initteil vo Akima-Spline */ q = (FLOAT*)smalloc(SYSTEM,sizeof(FLOAT)*akima->num+3); dy = (FLOAT*)smalloc(SYSTEM,sizeof(FLOAT)*akima->num); akima->pp[0] = (FLOAT*)smalloc(SYSTEM,sizeof(FLOAT)*akima->num); akima->pp[1] = (FLOAT*)smalloc(SYSTEM,sizeof(FLOAT)*akima->num); akima->cpnt[akima->num-1].x = 1.0; akima->cpnt[akima->num-1].y = akima->cpnt[0].y; for(i=2; inum+1; i++) q[i] = (akima->cpnt[i-1].y - akima->cpnt[i-2].y) / (akima->cpnt[i-1].x - akima->cpnt[i-2].x); q[1] = q[akima->num]; q[0] = q[akima->num-1]; q[akima->num+1] = q[2]; q[akima->num+2] = q[3]; for(i=0; inum; i++) { FLOAT ql, qr; ql = f_abs(q[i+3]-q[i+2]); qr = f_abs(q[i+1]-q[i]); if((ql == 0.0) && (qr == 0.0)) dy[i] = (q[i+1] + q[i+2]) / 2.0; else dy[i] = (q[i+1]*ql + q[i+2]*qr) / (ql+qr); } for(i=0; inum-1; i++) { FLOAT diff; diff = (akima->cpnt[i+1].x - akima->cpnt[i].x); akima->pp[0][i] = diff * dy[i]; akima->pp[1][i] = diff * dy[i+1]; } if ((q == NULL) || (dy == NULL)) message("Fehler in Akima_read\n"); message("Akima-Spline initialized.\n"); } short akima_find_i(AKIMA akima, FLOAT x, short l, short r) { short idx; idx = (l+r)/2; if(idx == l) if(x >= akima.cpnt[idx].x) return idx; else return idx-1; else if(x >= akima.cpnt[idx].x) return(akima_find_i(akima,x,idx,r)); else return(akima_find_i(akima,x,l,idx)); } FLOAT akima_g0(FLOAT t) { FLOAT temp; temp = t-0.5; return(0.5 - 1.5*temp + 2.0*temp*temp*temp); } FLOAT akima_g1(FLOAT t) { return(1.0 - akima_g0(t)); } FLOAT akima_h0(FLOAT t) { return((t*t - (t+t) + 1.0) * t); } FLOAT akima_h1(FLOAT t) { return(t*t*(t - 1.0)); } FLOAT akima_evaluate(AKIMA* akima, FLOAT x) { INT i; FLOAT val, t; i = akima_find_i(*akima, x, 0, akima->num); t = (x - akima->cpnt[i].x) / (akima->cpnt[i+1].x - akima->cpnt[i].x); val = akima->cpnt[i].y * akima_g0(t) + akima->cpnt[i+1].y * akima_g1(t) + akima->pp[0][i] * akima_h0(t) + akima->pp[1][i] * akima_h1(t); return(val); } urn(1.0 - akima_g0(t)); } FLOAT akima_h0(FLOATFlirt/akimanoise.d000644 000316 000311 00000001435 06103226550 014245 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : akimanoise.d declarations used for akimanoise.c DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef AKIMANOISE_D #define AKIMANOISE_D #include "flirt.d" #include "material.d" #include "geometr2.d" #include "geometr3.d" #include "numeric.f" typedef struct { int num; PNT2 *cpnt; FLOAT *pp[2]; } AKIMA; typedef struct { short n,m,*P; FLOAT **N; } NOISE; typedef struct { NOISE noise; INT mat_num; FLOAT range; MATERIAL **material; MAT3 world2tex; } SOLIDTEX; #endif 010391 wrzl,rft first version *****************************************************************************/ #ifndef AKIMANOISE_D #define AKIMANOISE_D #include "flirt.d" #include "material.d" #include "geometr2.d" #includFlirt/akimanoise.f000644 000316 000311 00000002322 06103226600 014237 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : akimanoise.f used for procedure d3wood and d3marble in texture.c DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef AKIMANOISE_F #define AKIMANOISE_F #include "akimanoise.d" #include "flirt.d" #include "material.d" #include "geometr2.d" #include "geometr3.d" #include "numeric.f" #include "texture.d" short akima_find_i(AKIMA akima, FLOAT x, short l, short r); FLOAT akima_g0(FLOAT t); FLOAT akima_g1(FLOAT t); FLOAT akima_evaluate(AKIMA* akima, FLOAT x); FLOAT akima_h0(FLOAT t); FLOAT akima_h1(FLOAT t); AKIMA akima_read(AKIMA *akima); FLOAT noise_weight(FLOAT t); void noise_init(TEXTURE* tex); FLOAT noise_get(TEXTURE tex,FLOAT x, FLOAT y, FLOAT z); FLOAT noise_get_T(TEXTURE tex,FLOAT x, FLOAT y, FLOAT z); FLOAT noise_get_absT(TEXTURE tex,FLOAT x, FLOAT y, FLOAT z); void copy_mat(MATERIAL *from_mat, MATERIAL *to_mat); void trans(TEXTURE *tex, PNT3 *p1, PNT3 *p2); void read_trans(TEXTURE *tex); #endif LOAT akima_evaluate(AKIMA* akima, FLOAT x); FLOAT akima_h0(FLOAT t); FLOAT akima_h1(FLOAT t); AKIMA akima_read(AKIMA *akima); FLOAT noise_weight(FLOAT t); void noise_init(TEXTURE* tex); FLOAT noise_get(TEXTURE tex,FLOAT x, FLOAT y, FLOAT z); FLOAT noise_get_T(TEXTURE tex,FLOAT x, FLOAT y, FLOAFlirt/bounding.c000644 000316 000311 00000044612 06103226504 013734 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : bounding.c Tests of different bounding volumes DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "hitlist.f" #include "bounding.f" VEC3 box_normal[7] = /* normals for box */ { { 0.0, 0.0, 0.0 }, { -1.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, -1.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, -1.0 }, { 0.0, 0.0, 1.0 } }; BYTE otherbboxside(BYTE mask) { if ((mask & BOUNDTEST_X) && ((mask & BOUNDTEST_X) != BOUNDTEST_X)) mask ^= BOUNDTEST_X; if ((mask & BOUNDTEST_Y) && ((mask & BOUNDTEST_Y) != BOUNDTEST_Y)) mask ^= BOUNDTEST_Y; if ((mask & BOUNDTEST_Z) && ((mask & BOUNDTEST_Z) != BOUNDTEST_Z)) mask ^= BOUNDTEST_Z; return(mask); } BOOLEAN hitbbox(RAY3 *ray, FLOAT *tmin, FLOAT *tmax, BYTE mask, BOX3* box) { FLOAT hit; /* ------------------------------------------------ the bounding box text */ if (mask & BOUNDTEST_X) { if (ray->inv_dir.x > 0.0) { if (mask & BOUNDTEST_XMAX) { hit = (box->max.x - ray->origin.x) * ray->inv_dir.x; if (hit <= *tmin) return FALSE; if (hit <= *tmax) *tmax = hit; } if (mask & BOUNDTEST_XMIN) { hit = (box->min.x - ray->origin.x) * ray->inv_dir.x; if (hit >= *tmax) return FALSE; if (hit >= *tmin) *tmin = hit; } } else if (ray->inv_dir.x < 0.0) { if (mask & BOUNDTEST_XMIN) { hit = (box->min.x - ray->origin.x) * ray->inv_dir.x; if (hit <= *tmin) return FALSE; if (hit <= *tmax) *tmax = hit; } if (mask & BOUNDTEST_XMAX) { hit = (box->max.x - ray->origin.x) * ray->inv_dir.x; if (hit >= *tmax) return FALSE; if (hit >= *tmin) *tmin = hit; } } else /* ray parallel to x-planes */ { if (ray->origin.x <= box->min.x || ray->origin.x >= box->max.x) return FALSE; } } if (mask & BOUNDTEST_Y) { if (ray->inv_dir.y > 0.0) { if (mask & BOUNDTEST_YMAX) { hit = (box->max.y - ray->origin.y) * ray->inv_dir.y; if (hit <= *tmin) return FALSE; if (hit <= *tmax) *tmax = hit; } if (mask & BOUNDTEST_YMIN) { hit = (box->min.y - ray->origin.y) * ray->inv_dir.y; if (hit >= *tmax) return FALSE; if (hit >= *tmin) *tmin = hit; } } else if (ray->inv_dir.y < 0.0) { if (mask & BOUNDTEST_YMIN) { hit = (box->min.y - ray->origin.y) * ray->inv_dir.y; if (hit <= *tmin) return FALSE; if (hit <= *tmax) *tmax = hit; } if (mask & BOUNDTEST_YMAX) { hit = (box->max.y - ray->origin.y) * ray->inv_dir.y; if (hit >= *tmax) return FALSE; if (hit >= *tmin) *tmin = hit; } } else /* ray parallel to y-planes */ { if (ray->origin.y <= box->min.y || ray->origin.y >= box->max.y) return FALSE; } } if (mask & BOUNDTEST_Z) { if (ray->inv_dir.z > 0.0) { if (mask & BOUNDTEST_ZMAX) { hit = (box->max.z - ray->origin.z) * ray->inv_dir.z; if (hit <= *tmin) return FALSE; if (hit <= *tmax) *tmax = hit; } if (mask & BOUNDTEST_ZMIN) { hit = (box->min.z - ray->origin.z) * ray->inv_dir.z; if (hit >= *tmax) return FALSE; if (hit >= *tmin) *tmin = hit; } } else if (ray->inv_dir.z < 0.0) { if (mask & BOUNDTEST_ZMIN) { hit = (box->min.z - ray->origin.z) * ray->inv_dir.z; if (hit <= *tmin) return FALSE; if (hit <= *tmax) *tmax = hit; } if (mask & BOUNDTEST_ZMAX) { hit = (box->max.z - ray->origin.z) * ray->inv_dir.z; if (hit >= *tmax) return FALSE; if (hit >= *tmin) *tmin = hit; } } else /* ray parallel to z-planes */ { if (ray->origin.z <= box->min.z || ray->origin.z >= box->max.z) return FALSE; } } return TRUE; } BOOLEAN hitbox(RAY3 *ray,FLOAT *tmin1,FLOAT *tmax1,ULONG *tminface1, ULONG *tmaxface1,BOX3 *box) { ULONG tminface,tmaxface; FLOAT t,tmin,tmax; tmin = -F_HUGE; tmax = F_HUGE; tminface = 0L; tmaxface = 0L; if (ray->direction.x > 0.0) { t = (box->min.x - ray->origin.x) * ray->inv_dir.x; checkaddmin(1L,t,tminface,tmin,tmax); t = (box->max.x - ray->origin.x) * ray->inv_dir.x; checkaddmax(2L,t,tmaxface,tmin,tmax); } else if (ray->direction.x < 0.0) { t = (box->max.x - ray->origin.x) * ray->inv_dir.x; checkaddmin(2L,t,tminface,tmin,tmax); t = (box->min.x - ray->origin.x) * ray->inv_dir.x; checkaddmax(1L,t,tmaxface,tmin,tmax); } else /* ray parallel to x-planes ? */ { if (ray->origin.x <= box->min.x || ray->origin.x >= box->max.x) return FALSE; } if (ray->direction.y > 0.0) { t = (box->min.y - ray->origin.y) * ray->inv_dir.y; checkaddmin(3L,t,tminface,tmin,tmax); t = (box->max.y - ray->origin.y) * ray->inv_dir.y; checkaddmax(4L,t,tmaxface,tmin,tmax); } else if (ray->direction.y < 0.0) { t = (box->max.y - ray->origin.y) * ray->inv_dir.y; checkaddmin(4L,t,tminface,tmin,tmax); t = (box->min.y - ray->origin.y) * ray->inv_dir.y; checkaddmax(3L,t,tmaxface,tmin,tmax); } else /* ray parallel to y-planes ? */ { if (ray->origin.y <= box->min.y || ray->origin.y >= box->max.y) return FALSE; } if (ray->direction.z > 0.0) { t = (box->min.z - ray->origin.z) * ray->inv_dir.z; checkaddmin(5L,t,tminface,tmin,tmax); t = (box->max.z - ray->origin.z) * ray->inv_dir.z; checkaddmax(6L,t,tmaxface,tmin,tmax); } else if (ray->direction.z < 0.0) { t = (box->max.z - ray->origin.z) * ray->inv_dir.z; checkaddmin(6L,t,tminface,tmin,tmax); t = (box->min.z - ray->origin.z) * ray->inv_dir.z; checkaddmax(5L,t,tmaxface,tmin,tmax); } else /* ray parallel to x-planes ? */ { if (ray->origin.z <= box->min.z || ray->origin.z >= box->max.z) return FALSE; } *tmin1 = tmin; *tmax1 = tmax; *tminface1 = tminface; *tmaxface1 = tmaxface; return(TRUE); } BOOLEAN hitshiftbbox(RAY3 *ray,FLOAT *tmin,FLOAT *tmax,BYTE mask, VEC3 *vec,BOX3* box) { FLOAT hit; /* ------------------------------------------------ the bounding box text */ if (mask & BOUNDTEST_X) { if (ray->inv_dir.x == 0.0) /* ray parallel to x-planes ? */ { if (ray->origin.x <= box->min.x + vec->x || ray->origin.x >= box->max.x + vec->x) return FALSE; } else if (ray->inv_dir.x > 0.0) { if (mask & BOUNDTEST_XMAX) { hit = (box->max.x + vec->x - ray->origin.x) * ray->inv_dir.x; if (hit <= *tmin) return FALSE; if (hit <= *tmax) *tmax = hit; } if (mask & BOUNDTEST_XMIN) { hit = (box->min.x + vec->x - ray->origin.x) * ray->inv_dir.x; if (hit >= *tmax) return FALSE; if (hit >= *tmin) *tmin = hit; } } else { if (mask & BOUNDTEST_XMIN) { hit = (box->min.x + vec->x - ray->origin.x) * ray->inv_dir.x; if (hit <= *tmin) return FALSE; if (hit <= *tmax) *tmax = hit; } if (mask & BOUNDTEST_XMAX) { hit = (box->max.x + vec->x - ray->origin.x) * ray->inv_dir.x; if (hit >= *tmax) return FALSE; if (hit >= *tmin) *tmin = hit; } } } if (mask & BOUNDTEST_Y) { if (ray->inv_dir.y == 0.0) /* ray parallel to y-planes ? */ { if (ray->origin.y <= box->min.y + vec->y || ray->origin.y >= box->max.y + vec->y) return FALSE; } else if (ray->inv_dir.y > 0.0) { if (mask & BOUNDTEST_YMAX) { hit = (box->max.y + vec->y - ray->origin.y) * ray->inv_dir.y; if (hit <= *tmin) return FALSE; if (hit <= *tmax) *tmax = hit; } if (mask & BOUNDTEST_YMIN) { hit = (box->min.y + vec->y - ray->origin.y) * ray->inv_dir.y; if (hit >= *tmax) return FALSE; if (hit >= *tmin) *tmin = hit; } } else { if (mask & BOUNDTEST_YMIN) { hit = (box->min.y + vec->y - ray->origin.y) * ray->inv_dir.y; if (hit <= *tmin) return FALSE; if (hit <= *tmax) *tmax = hit; } if (mask & BOUNDTEST_YMAX) { hit = (box->max.y + vec->y - ray->origin.y) * ray->inv_dir.y; if (hit >= *tmax) return FALSE; if (hit >= *tmin) *tmin = hit; } } } if (mask & BOUNDTEST_Z) { if (ray->inv_dir.z == 0.0) /* ray parallel to z-planes ? */ { if (ray->origin.z <= box->min.z + vec->z || ray->origin.z >= box->max.z + vec->z) return FALSE; } else if (ray->inv_dir.z > 0.0) { if (mask & BOUNDTEST_ZMAX) { hit = (box->max.z + vec->z - ray->origin.z) * ray->inv_dir.z; if (hit <= *tmin) return FALSE; if (hit <= *tmax) *tmax = hit; } if (mask & BOUNDTEST_ZMIN) { hit = (box->min.z + vec->z - ray->origin.z) * ray->inv_dir.z; if (hit >= *tmax) return FALSE; if (hit >= *tmin) *tmin = hit; } } else { if (mask & BOUNDTEST_ZMIN) { hit = (box->min.z + vec->z - ray->origin.z) * ray->inv_dir.z; if (hit <= *tmin) return FALSE; if (hit <= *tmax) *tmax = hit; } if (mask & BOUNDTEST_ZMAX) { hit = (box->max.z + vec->z - ray->origin.z) * ray->inv_dir.z; if (hit >= *tmax) return FALSE; if (hit >= *tmin) *tmin = hit; } } } return TRUE; } BOOLEAN insidebbox(PNT3 *pnt,BOX3 *box) { if (box->min.x < pnt->x && pnt->x < box->max.x && box->min.y < pnt->y && pnt->y < box->max.y && box->min.z < pnt->z && pnt->z < box->max.z) return(TRUE); return(FALSE); } BOOLEAN insideshiftbbox(PNT3 *pnt,VEC3 *vec,BOX3 *box) { if (box->min.x + vec->x < pnt->x && pnt->x < box->max.x + vec->x && box->min.y + vec->y < pnt->y && pnt->y < box->max.y + vec->y && box->min.z + vec->z < pnt->z && pnt->z < box->max.z + vec->z) return(TRUE); return(FALSE); } BOOLEAN hitbsphere(RAY3 *ray,FLOAT *tmin,FLOAT *tmax,SPHERE3 *sphere) { FLOAT v,t,discr; VEC3 eye2mid; v3sub(sphere->center,ray->origin,eye2mid); v = v3dot(eye2mid,ray->direction); discr = sphere->radius_2 - (v3length_2(eye2mid) - v * v); if (discr <= F_SMALL) return(FALSE); discr = f_sqrt(discr); t = v - discr; if (t >= *tmin) *tmin = t; t = v + discr; if (t <= *tmax) *tmax = t; if (*tmin >= *tmax) return(FALSE); return TRUE; } BOOLEAN insidebsphere(PNT3 *pnt,SPHERE3 *sphere) { FLOAT dist_2; v3dist_2(sphere->center,*pnt,dist_2); if (dist_2 < sphere->radius_2) return(TRUE); return(FALSE); } /*lint -e715 not referenced */ BOOLEAN hitbounds(RAY3 *ray,FLOAT *tmin,FLOAT *tmax,BOUNDLIST *bounds) { return(FALSE); /* not implemented yet */ } BOOLEAN insidebounds(PNT3 *pnt,BOUNDLIST *bounds) { return(FALSE); /* not implemented yet */ } /*lint +e715 not referenced */ VOID boundsphere4box(BOX3 *box,SPHERE3 *sphere) { v3add(box->min,box->max,sphere->center); v3scale(sphere->center,0.5); v3dist_2(sphere->center,box->min,sphere->radius_2); } VOID bounds4points(UINT number,PNT3 *points,BOX3 *box,SPHERE3 *sphere, PNT3 *center,MAT3 *mat) { UINT i,j; FLOAT r,r_2,newr; PNT3 *locpnt,*work; PNT3 p,minpnt[3],maxpnt[3]; VEC3 delta; newr = 0.0; locpnt = NULL; if (mat != NULL) { locpnt = (PNT3 *)newmem(SYSTEM,sizeof(PNT3) * number); work = locpnt; for (i = 0; i < number; i++) { v3pmulm(points[i],*mat,work[i]); } } else work = points; if (box != NULL) { box->min.x = F_HUGE; box->min.y = F_HUGE; box->min.z = F_HUGE; box->max.x = -F_HUGE; box->max.y = -F_HUGE; box->max.z = -F_HUGE; } if (sphere != NULL) { if (center == NULL) { minpnt[0].x = F_HUGE; minpnt[1].y = F_HUGE; minpnt[2].z = F_HUGE; maxpnt[0].x = -F_HUGE; maxpnt[1].y = -F_HUGE; maxpnt[2].z = -F_HUGE; for (i = 0; i < number; i++) { if (work[i].x < minpnt[0].x) minpnt[0] = work[i]; if (work[i].y < minpnt[1].y) minpnt[1] = work[i]; if (work[i].z < minpnt[2].z) minpnt[2] = work[i]; if (work[i].x > maxpnt[0].x) maxpnt[0] = work[i]; if (work[i].y > maxpnt[1].y) maxpnt[1] = work[i]; if (work[i].z > maxpnt[2].z) maxpnt[2] = work[i]; } r = 0.0; j = 0; for (i = 0; i < 3; i++) /* find max dist */ { v3dist_2(minpnt[i],maxpnt[i],newr); if (newr >= r) { r = newr; j = i; } } v3add(minpnt[j],maxpnt[j],sphere->center); v3scale(sphere->center,0.5); /* guessing center */ newr = 0.0; } else { /* center is given */ if (mat != NULL) { p = *center; v3pmulm(p,*mat,sphere->center); } else sphere->center = *center; } sphere->radius_2 = 0.0; } for (i = 0; i < number; i++) { p = work[i]; if (box != NULL) { v3pmin(box->min,p,box->min); v3pmax(box->max,p,box->max); } if (sphere != NULL) { if (center == NULL) /* center guessing */ { v3sub(p,sphere->center,delta); r_2 = v3length_2(delta); if (sphere->radius_2 < r_2) /* not inside */ { r = f_sqrt(r_2); newr = (newr + r) / 2.0; sphere->radius_2 = newr * newr; r = (r - newr) / r; v3addscaled(sphere->center,delta,r,sphere->center); } } else /* fixed center */ { v3dist_2(p,sphere->center,r_2); sphere->radius_2 = maxi(sphere->radius_2,r_2); } } } if (mat != NULL) freemem(SYSTEM,locpnt); } sphere->radius_2 = newr * newr; r = (r - newr) / r; v3adFlirt/bounding.d000644 000316 000311 00000002277 06103226550 013737 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : bounding.d tests of different bounding volumes DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef BOUNDING_D #define BOUNDING_D #include "system.d" #include "flirt.d" #define BOUNDTEST_NONE ((BYTE) 0x00) #define BOUNDTEST_XMIN ((BYTE) 0x02) #define BOUNDTEST_XMAX ((BYTE) 0x04) #define BOUNDTEST_X ((BYTE) 0x06) #define BOUNDTEST_YMIN ((BYTE) 0x08) #define BOUNDTEST_YMAX ((BYTE) 0x10) #define BOUNDTEST_Y ((BYTE) 0x18) #define BOUNDTEST_ZMIN ((BYTE) 0x20) #define BOUNDTEST_ZMAX ((BYTE) 0x40) #define BOUNDTEST_Z ((BYTE) 0x60) #define BOUNDTEST_ALL ((BYTE) 0x7E) #define BOUNDTEST_NOOPT ((BYTE) 0xFE) typedef enum { BOUND_UNKNOWN, BOUND_PLANES /* not implemented yet */ } BOUNDTYP; typedef struct boundlist { BOUNDTYP typ; struct boundlist *next; /* union is missing now */ } BOUNDLIST; #endif efine BOUNDTEST_Y ((BYTE) 0x18) #define BOUNDTEST_ZMIN ((BYTE) 0x20) #define BOUNDTEST_ZMAX ((BYTE) 0x40) #define BOUNDTEST_Z ((BYTE) 0x60) #define BOUNDTEST_ALL ((BYTE) 0x7E) #define BOUNDTEST_NOOPT ((BYTE) 0xFE) typedef enum { BOUND_UNKNOWN, BOUND_PLANES /* not implementFlirt/bounding.f000644 000316 000311 00000004442 06103226600 013731 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : bounding.f tests of different bounding volumes DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef BOUNDING_F #define BOUNDING_F #include "geometr3.f" #include "bounding.d" Extern VEC3 box_normal[7]; /* normals for box, index by face 1-6 */ BYTE otherbboxside PP((BYTE mask)); BOOLEAN hitbbox PP((RAY3 *ray, FLOAT *tmin, FLOAT *tmax, BYTE mask, BOX3 *box)); BOOLEAN insidebbox PP((PNT3 *pnt,BOX3 *box)); BOOLEAN hitbox PP((RAY3 *ray,FLOAT *tmin1,FLOAT *tmax1,ULONG *tminface1, ULONG *tmaxface1,BOX3 *box)); BOOLEAN hitshiftbbox PP((RAY3 *ray,FLOAT *tmin,FLOAT *tmax,BYTE mask, VEC3 *vec,BOX3* box)); BOOLEAN insideshiftbbox PP((PNT3 *pnt,VEC3 *vec,BOX3 *box)); BOOLEAN hitbsphere PP((RAY3 *ray,FLOAT *tmin,FLOAT *tmax,SPHERE3 *sphere)); BOOLEAN insidebsphere PP((PNT3 *pnt,SPHERE3 *sphere)); BOOLEAN hitbounds PP((RAY3 *ray,FLOAT *tmin,FLOAT *tmax,BOUNDLIST *bounds)); BOOLEAN insidebounds PP((PNT3 *pnt,BOUNDLIST *bounds)); VOID boundsphere4box PP((BOX3 *box,SPHERE3 *sphere)); VOID bounds4points PP((UINT number,PNT3 *points,BOX3 *box,SPHERE3 *sphere, PNT3 *center,MAT3 *mat)); #define HIT_BOUNDS(obj,ray,tmin,tmax) \ (((obj)->test_bbox == 0 || \ hitbbox(&(ray),&(tmin),&(tmax),(obj)->test_bbox,&((obj)->bbox))) && \ (! (obj)->test_bsphere || \ hitbsphere(&(ray),&(tmin),&(tmax),&((obj)->bsphere))) && \ ((obj)->bounds == NULL || hitbounds(&(ray),&(tmin),&(tmax),(obj)->bounds))) #define INSIDE_BOUND_TEST(obj,pnt) \ if ((obj)->test_bbox && ! insidebbox((pnt),&((obj)->bbox))) \ return(NULL); \ if ((obj)->test_bsphere && ! insidebsphere((pnt),&((obj)->bsphere))) \ return(NULL); \ if ((obj)->bounds != NULL && ! insidebounds((pnt),(obj)->bounds)) \ return(NULL); #endif (tmax),(obj)->bounds))) #define INSIDE_BOUND_TEST(obj,pnt) \ if ((obj)->test_bbox && ! insidebbox((pnt),&((obj)->bbox))) \ return(NULL); Flirt/camera.c000644 000316 000311 00000015205 06103226504 013353 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : camera.c Camera manipulation DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "geometr2.f" #include "geometr3.f" #include "objects.f" #include "readdata.f" #include "symbols.f" #include "writdata.f" #include "camera.f" #define FRAMEFACTOR 1.05 /* to make pictures a little larger */ CAMERA *global_camera; Static VOID do_autoscale PP((CAMERA *cam)); VOID readcamera(CAMERA *cam) { readconststring("eye"); readpnt3(&(cam->eye)); if (matchreadconststring("direction")) readvec3(&(cam->direction)); else cam->direction = V3ZERO; /* autocenter */ option_read_real("zoom", cam->zoom,0.0); /* autozoom */ option_read_real("twist", cam->twist,0.0); option_read_bool("parallel", cam->parallel,FALSE); if (matchreadconststring("depth_of_field")) { cam->depth_of_field = readbool(); if (cam->depth_of_field) { match_read_real("focus", cam->focus); match_read_real("aperture", cam->aperture); } else { cam->focus = 1.0; /* ?? */ cam->aperture = 1.0; } } else cam->depth_of_field = FALSE; } CAMERA *readnamecamera(VOID) { CAMERA *camera; readconststring(lookupstring(CONST_DATA,DATA_CAMERA)); camera = (CAMERA *)findname(INFO_CAMERA,token); if (camera == NULL) { camera = newonlytyp(CAMERA); savename(INFO_CAMERA,token,(VOIDPTR) camera); } nexttoken(); return(camera); } VOID writecamera(CAMERA *cam) { writestring("eye"); writepnt3(&(cam->eye)); writestring("direction"); writevec3(&(cam->direction)); write_string_real("zoom", cam->zoom); write_string_real("twist", cam->twist); write_string_bool("parallel", cam->parallel); if (cam->depth_of_field) { writestring("depth_of_field"); writelf(); write_string_real("focus", cam->focus); write_string_real("aperture", cam->aperture); } } VOID setupcamera(CAMERA *cam,UINT xpix,UINT ypix) { BOOLEAN autoscale,autocenter; FLOAT xscale,yscale,zscale; FLOAT alpha,beta; PNT3 locpnt; if (cam->direction.x == 0.0 && cam->direction.y == 0.0 && cam->direction.z == 0.0) { /* autocentering */ v3add(global_object->bbox.min,global_object->bbox.max,locpnt); v3scale(locpnt,0.5); v3sub(locpnt,cam->eye,cam->direction); if (v3length_2(cam->direction) < F_SMALL) cam->direction = V3XUNIT; autocenter = TRUE; } else autocenter = FALSE; if (cam->zoom == 0.0) { cam->zoom = 1.0; /* autozoom */ autoscale = TRUE; } else autoscale = FALSE; xscale = (FLOAT) xpix; /* VAX C-Compiler bug :-( */ yscale = (FLOAT) ypix; zscale = cam->zoom * f_sqrt(xscale * xscale + yscale * yscale); xscale = xpix / (2.0 * zscale); yscale = ypix / (2.0 * zscale); if (cam->direction.x == 0.0 && cam->direction.y == 0.0) alpha = sign(cam->direction.z) * F_PI_HALF; else { /* alpha = f_hypot(cam->direction.x,cam->direction.y)); clib-Bug :-( */ alpha = f_sqrt(cam->direction.x * cam->direction.x + cam->direction.y * cam->direction.y); alpha = f_atan2(cam->direction.z,alpha); } if (cam->direction.x == 0.0) beta = sign(cam->direction.y) * F_PI_HALF; else beta = f_atan2(cam->direction.y,cam->direction.x); cam->cam2world = M3UNIT; cam->world2cam = M3UNIT; m3scale(xscale,yscale,1.0,cam->cam2world,cam->world2cam); m3rotz(cam->twist,cam->cam2world,cam->world2cam); m3rotx(alpha - F_PI_HALF,cam->cam2world,cam->world2cam); m3rotz(beta - F_PI_HALF,cam->cam2world,cam->world2cam); m3trans(cam->eye.x,cam->eye.y,cam->eye.z,cam->cam2world,cam->world2cam); if (autocenter || autoscale) message("\nCAMERA:\n"); if (autocenter) { message(" direction (autocentered) : %10f\n",cam->direction.x); message(" %10f\n",cam->direction.y); message(" %10f\n",cam->direction.z); } if (autoscale) { do_autoscale(cam); message(" zoom (autoscaled) : %8.5f\n",cam->zoom); } } Static VOID do_autoscale(CAMERA *cam) { UINT i; FLOAT xscale,yscale,zscale; PNT3 locpnt,pnt[8]; VEC2 screenmin,screenmax; MAT3 zoomto,zoomfrom,mat; pnt[0] = global_object->bbox.min; pnt[1] = global_object->bbox.min; pnt[1].x = global_object->bbox.max.x; pnt[2] = global_object->bbox.min; pnt[2].y = global_object->bbox.max.y; pnt[3] = global_object->bbox.min; pnt[3].z = global_object->bbox.max.z; pnt[4] = global_object->bbox.max; pnt[4].x = global_object->bbox.min.x; pnt[5] = global_object->bbox.max; pnt[5].y = global_object->bbox.min.y; pnt[6] = global_object->bbox.max; pnt[6].z = global_object->bbox.min.z; pnt[7] = global_object->bbox.max; screenmin.x = F_HUGE; screenmin.y = F_HUGE; screenmax.x = -F_HUGE; screenmax.y = -F_HUGE; for (i = 0; i < 8; i++) { v3pmulm(pnt[i],cam->world2cam,locpnt); if (locpnt.z < F_SMALL) { message(" zoom (autoscale not possible) : 1.0\n"); return; } locpnt.x /= locpnt.z; locpnt.y /= locpnt.z; v2pmin(screenmin,locpnt,screenmin); v2pmax(screenmax,locpnt,screenmax); } screenmin.x = f_abs(screenmin.x); screenmin.y = f_abs(screenmin.y); screenmax.x = f_abs(screenmax.x); screenmax.y = f_abs(screenmax.y); xscale = maxi(screenmin.x,screenmax.x); yscale = maxi(screenmin.y,screenmax.y); zscale = maxi(xscale,yscale) * FRAMEFACTOR; zoomto = M3UNIT; zoomfrom = M3UNIT; m3scale(zscale,zscale,1.0,zoomto,zoomfrom); mat = cam->cam2world; m3mmulm(zoomto,mat,cam->cam2world); mat = cam->world2cam; m3mmulm(mat,zoomfrom,cam->world2cam); cam->zoom = 1.0 / zscale; } creenmin.y = f_abs(screenmin.y); screenmax.x = f_abs(screenmax.x); screenmax.y = f_abs(screenmax.y); xscale = maxi(screenmin.x,screenmax.x); yscale = maxi(screenmin.y,screenmax.y); zscale = maxi(xscale,yscale) * FRAMEFACTOR; zoomto = M3UNIT; zoomfrom = M3UNIT; m3scale(zscale,zscale,1.0,zoomto,zoomfrom); mat = cam->cam2world; m3mmulm(zFlirt/camera.d000644 000316 000311 00000001356 06103226552 013361 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : camera.d Header file for camera DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef CAMERA_D #define CAMERA_D #include "geometr3.d" #include "flirt.d" typedef struct { BOOLEAN parallel; BOOLEAN depth_of_field; FLOAT focus; FLOAT aperture; FLOAT zoom; FLOAT twist; PNT3 eye; VEC3 direction; VEC3 dx; VEC3 dy; MAT3 cam2world; MAT3 world2cam; } CAMERA; #endif ------------------------- 010391 wrzl,rft first version *****************************************************************************/ #ifndef CAMERA_D #define CAMERA_D #include "geometr3.d" #include "flirt.d" typedef struct { BOOLEAN parallel; BOOLEAN dFlirt/camera.f000644 000316 000311 00000001203 06103226602 013346 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : camera.f Header file for camera DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef CAMERA_F #define CAMERA_F #include "camera.d" Extern CAMERA *global_camera; VOID readcamera PP((CAMERA *camera)); CAMERA *readnamecamera PP((VOID)); VOID writecamera PP((CAMERA *cam)); VOID setupcamera PP((CAMERA *camera,UINT xpix,UINT ypix)); #endif Header file for camera DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef CAMERA_F #define CAMERA_F #include "camera.d" Extern CAMERA *global_camera; VOID readcamera PP((CAMERA *camera)); CAMERA *Flirt/color.c000644 000316 000311 00000002445 06103226506 013245 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : color.c colors DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "readdata.f" #include "writdata.f" #include "color.f" #ifndef SPECTRUM /* ------------------------------------------------------------------------ the following for RGB-defined colors ------------------------------------------------------------------------ */ COLOR COLBLACK = { 0.0, 0.0, 0.0 }; COLOR COLRED = { 1.0, 0.0, 0.0 }; COLOR COLGREEN = { 0.0, 1.0, 0.0 }; COLOR COLBLUE = { 0.0, 0.0, 1.0 }; COLOR COLWHITE = { 1.0, 1.0, 1.0 }; VOID readcolor(COLOR *color) { color->r = readreal(); color->g = readreal(); color->b = readreal(); } VOID writecolor(COLOR *color) { writereal(color->r); writereal(color->g); writereal(color->b); writelf(); } #else /* ------------------------------------------------------------------------ the following for spectrum-defined colors ------------------------------------------------------------------------ */ #endif ; COLOR COLWHITE = { 1.0, 1.0, 1.0 }; VOID readcolor(COLOR *color) { color->r = readreal(); color->g = readreal(); color->b = readreal(); } VOID writecolor(COLOR *color) { writereal(color-Flirt/color.d000644 000316 000311 00000001404 06103226552 013241 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : color.d Header file for color DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef COLOR_D #define COLOR_D #include "system.d" #include "flirt.d" #define RGBSAMPLES 3 #define SPECTSAMPLES 21 typedef struct { FLOAT r; FLOAT g; FLOAT b; } RGBCOLOR; typedef struct { FLOAT sample[SPECTSAMPLES]; } SPECTCOLOR; #ifndef SPECTRUM typedef RGBCOLOR COLOR; #else typedef SPECCOLOR COLOR; #endif #endif - 010391 wrzl,rft first version *****************************************************************************/ #ifndef COLOR_D #define COLOR_D #include "system.d" #include "flirt.d" #define RGBSAMPLES 3 #define SPECTSAMPLES 21 typedef Flirt/color.f000644 000316 000311 00000014333 06103226602 013244 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : color.f Header file for color DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef COLOR_F #define COLOR_F #include "color.d" #include "numeric.f" #ifndef SPECTRUM /* ------------------------------------------------------------------------ the following definitions are for RGB-defined colors ------------------------------------------------------------------------ */ #define colormax(c) maxi((c).r,maxi((c).g,(c).b)) #define color_iszero(c) (f_iszero((c).r) && f_iszero((c).g) && f_iszero((c).b)) #define extract_r(c) ((c).r) #define extract_g(c) ((c).g) #define extract_b(c) ((c).b) #define colorinit(c,k) \ { \ (c).r = (k); \ (c).g = (k); \ (c).b = (k); \ } #define colormini(c1,c2,c) \ { \ (c).r = mini((c1).r,(c2).r); \ (c).g = mini((c1).g,(c2).g); \ (c).b = mini((c1).b,(c2).b); \ } #define colormaxi(c1,c2,c) \ { \ (c).r = maxi((c1).r,(c2).r); \ (c).g = maxi((c1).g,(c2).g); \ (c).b = maxi((c1).b,(c2).b); \ } #define coloradd(c1,c2,c) \ { \ (c).r = (c1).r + (c2).r; \ (c).g = (c1).g + (c2).g; \ (c).b = (c1).b + (c2).b; \ } #define colorsub(c1,c2,c) \ { \ (c).r = (c1).r - (c2).r; \ (c).g = (c1).g - (c2).g; \ (c).b = (c1).b - (c2).b; \ } #define coloraddscaled(c1,c2,k,c) \ { \ (c).r = (c1).r + (k) * (c2).r; \ (c).g = (c1).g + (k) * (c2).g; \ (c).b = (c1).b + (k) * (c2).b; \ } #define colormult(c1,c2,c) \ { \ (c).r = (c1).r * (c2).r; \ (c).g = (c1).g * (c2).g; \ (c).b = (c1).b * (c2).b; \ } #define colormultk(c1,k,c) \ { \ (c).r = (c1).r * k; \ (c).g = (c1).g * k; \ (c).b = (c1).b * k; \ } #define colorpowk(c1,k,c) \ { \ (c).r = f_pow((c1).r,k); \ (c).g = f_pow((c1).g,k); \ (c).b = f_pow((c1).b,k); \ } #define colordiv(c1,c2,c) \ { \ (c).r = (f_iszero((c2).r) ? F_HUGE : (c1).r / (c2).r); \ (c).g = (f_iszero((c2).g) ? F_HUGE : (c1).g / (c2).g); \ (c).b = (f_iszero((c2).b) ? F_HUGE : (c1).b / (c2).b); \ } #define colorinv(c1,c) \ { \ (c).r = 1.0 - (c1).r; \ (c).g = 1.0 - (c1).g; \ (c).b = 1.0 - (c1).b; \ } #define colorinterpol(c1,c2,t,c) \ { \ (c).r = interpol((c1).r,(c2).r,t); \ (c).g = interpol((c1).g,(c2).g,t); \ (c).b = interpol((c1).b,(c2).b,t); \ } #else /* ------------------------------------------------------------------------ the following definitions are for spectrum-defined colors ------------------------------------------------------------------------ */ #define colormax(c) spect_colormax(c) #define color_iszero(c) spect_iszero(c) #define extract_r(c) spect_extract_r(c) #define extract_g(c) spect_extract_g(c) #define extract_b(c) spect_extract_b(c) #define colorinit(c,k) spect_colorinit(c,k) #define colormini(c1,c2,c) spect_colormini(c1,c2,c) #define colormaxi(c1,c2,c) spect_colormaxi(c1,c2,c) #define coloradd(c1,c2,c) spect_coloradd(c1,c2,c) #define colorsub(c1,c2,c) spect_colorsub(c1,c2,c) #define coloraddscaled(c1,c2,k,c) spect_coloraddscaled(c1,c2,k,c) #define colormult(c1,c2,c) spect_colormult(c1,c2,c) #define colormultk(c1,k,c) spect_colormultk(c1,k,c) #define colorpowk(c1,k,c) spect_colorpowk(c1,k,c) #define colordiv(c1,c) spect_colordiv(c1,c) #define colorinv(c1,c) spect_colorinv(c1,c) #define colorinterpol(c1,c2,t,c) spect_colorinterpol(c1,c2,t,c) #endif Extern COLOR COLWHITE; Extern COLOR COLBLACK; Extern COLOR COLRED; Extern COLOR COLGREEN; Extern COLOR COLBLUE; VOID readcolor PP((COLOR *color)); VOID writecolor PP((COLOR *color)); #endif 1,c2,c) #define colormultk(c1,k,c) spect_colormultk(c1,k,c) #define colorpowk(c1,k,c) spect_colorpowk(c1,k,c) #define colordiv(c1,c) spect_colordiv(c1,c) #define colorinv(c1,c) spect_colorinv(c1,c) #define colorinterpol(c1,c2,t,c) spect_colorintFlirt/cone.c000644 000316 000311 00000027215 06114642524 013061 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : cone.c cone manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr2.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "material.f" #include "texture.f" #include "objects.f" #include "scene.f" #include "readdata.f" #include "cone.f" Static OBJECT *readcone(VOID) { OBJECT *obj; obj = newonlyvar(OBJECT,SIMPLEOBJ); obj->typ = CONE; readtransform(&(obj->u.obj.obj2world),&(obj->u.obj.world2obj)); obj->u.obj.material = readnamematerial(); obj->u.obj.texture = readnametexture(); return(obj); } #define DIS 0.414213562 /* tan(22.5 * F_PI/180.0) == sqrt(2.0) - 1.0 */ Static PNT3 hull_cone[] = { { 0.0, 0.0, 0.0 }, { 1.0, DIS, 1.0 }, { DIS, 1.0, 1.0 }, { -DIS, 1.0, 1.0 }, { -1.0, DIS, 1.0 }, { -1.0, -DIS, 1.0 }, { -DIS, -1.0, 1.0 }, { DIS, -1.0, 1.0 }, { 1.0, -DIS, 1.0 } }; Static VOID plane2point(VEC3 *normal,MAT3 *obj2world,PNT3 *point) { VEC3 vec; v3vmultransm(*normal,*obj2world,vec); if (vec.z < 0.0 && v2length_2(vec) < vec.z * vec.z) vec = V3ZERO; else { v2normalize(vec); vec.z = 1.0; } v3pmulm(vec,*obj2world,*point); } Static VOID boundcone(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { PNT3 pnt; obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? TRUE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; plane2point(&V3XUNIT,&(obj->u.obj.obj2world),&pnt); obj->bbox.max.x = pnt.x; plane2point(&V3YUNIT,&(obj->u.obj.obj2world),&pnt); obj->bbox.max.y = pnt.y; plane2point(&V3ZUNIT,&(obj->u.obj.obj2world),&pnt); obj->bbox.max.z = pnt.z; plane2point(&V3XNEGUNIT,&(obj->u.obj.obj2world),&pnt); obj->bbox.min.x = pnt.x; plane2point(&V3YNEGUNIT,&(obj->u.obj.obj2world),&pnt); obj->bbox.min.y = pnt.y; plane2point(&V3ZNEGUNIT,&(obj->u.obj.obj2world),&pnt); obj->bbox.min.z = pnt.z; bounds4points(9,hull_cone,NULL,&(obj->bsphere),&pnt, &(obj->u.obj.obj2world)); *bbox = obj->bbox; *bsphere = obj->bsphere; } Static OBJECT *insidecone(PNT3 *pnt,OBJECT *obj) { PNT3 locpnt; INSIDE_BOUND_TEST(obj,pnt); v3pmulm(*pnt,obj->u.obj.world2obj,locpnt); if (0.0 < locpnt.z && locpnt.z < 1.0 && locpnt.x * locpnt.x + locpnt.y * locpnt.y < locpnt.z * locpnt.z) return(obj); return(NULL); } /* ------------------------------------------------------------------------ */ Static BOOLEAN hitcone(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) /* ------------------------------------------------------------------------ calculate intersection of ray and cone ------------------------------------------------------------------------ */ { ULONG tminface = 0L; ULONG tmaxface = 0L; HITINFO *hit1,*hit2; FLOAT a,b,c,d,tone,ttwo; RAY3 locray; PRE_OBJECT(obj,hitlist); v3pmulm(rci.ray.origin,obj->u.obj.world2obj,locray.origin); v3vmulm(rci.ray.direction,obj->u.obj.world2obj,locray.direction); if (f_iszero(locray.direction.z)) /* ray parallel to z-planes ? */ { if (locray.origin.z <= 0.0 || locray.origin.z >= 1.0) return(FALSE); } else if (locray.direction.z > 0.0) { tone = - locray.origin.z / locray.direction.z; checkaddmin(0L,tone,tminface,tmin,tmax); ttwo = (1.0 - locray.origin.z) / locray.direction.z; checkaddmax(2L,ttwo,tmaxface,tmin,tmax); } else { tone = (1.0 - locray.origin.z) / locray.direction.z; checkaddmin(2L,tone,tminface,tmin,tmax); ttwo = - locray.origin.z / locray.direction.z; checkaddmax(0L,ttwo,tmaxface,tmin,tmax); } a = locray.direction.x * locray.direction.x + locray.direction.y * locray.direction.y - locray.direction.z * locray.direction.z; b = locray.origin.x * locray.direction.x + locray.origin.y * locray.direction.y - locray.origin.z * locray.direction.z; c = locray.origin.x * locray.origin.x + locray.origin.y * locray.origin.y - locray.origin.z * locray.origin.z; if (f_iszero(a)) /* linear equation ? */ { if (! f_iszero(b)) /* solvable ? */ { tone = - c / (2.0 * b); if (c > 0.0) /* this may be a bug */ { checkaddmin(1L,tone,tminface,tmin,tmax); } else { checkaddmax(1L,tone,tmaxface,tmin,tmax); } } } else { /* quadric equation : a t^2 + 2b t + c = 0 */ d = b * b - a * c; /* factor 2 was eliminated! */ if (d <= 0.0) /* no root ? */ return(FALSE); /* then exit */ if (b > 0.0) /* stable way to calculate */ d = - f_sqrt(d) - b; /* the roots of a quadric */ else /* equation */ d = f_sqrt(d) - b; tone = d / a; ttwo = c / d; /* VIETA : tone * ttwo == c / a */ if (a > 0.0) /* ray intersecting only */ { /* one part of doublecone ? */ if (tone < ttwo) { checkaddmin(1L,tone,tminface,tmin,tmax); checkaddmax(1L,ttwo,tmaxface,tmin,tmax); } else { checkaddmin(1L,ttwo,tminface,tmin,tmax); checkaddmax(1L,tone,tmaxface,tmin,tmax); } } /* ray intersecting both */ else /* parts of doublecone : */ { /* subtract interval */ if (locray.direction.z > 0.0) { if (tone < ttwo) { checkaddmin(1L,ttwo,tminface,tmin,tmax); } else { checkaddmin(1L,tone,tminface,tmin,tmax); } } else { if (tone < ttwo) { checkaddmax(1L,tone,tmaxface,tmin,tmax); } else { checkaddmax(1L,ttwo,tmaxface,tmin,tmax); } } } } checkmakerayhit(tminface,tmin,locray,hit1); checkmakerayhit(tmaxface,tmax,locray,hit2); prepare2hits(obj,hit1,hit2,hitlist); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } Static VOID normcone(HITINFO *hit) { VEC3 locnormal; if (hit->face == 1L) { locnormal.x = hit->ray.origin.x + hit->t * hit->ray.direction.x; locnormal.y = hit->ray.origin.y + hit->t * hit->ray.direction.y; locnormal.z = - hit->ray.origin.z - hit->t * hit->ray.direction.z; v3vmultransm(locnormal,hit->obj->u.obj.world2obj,hit->normal); } else { v3vmultransm(V3ZUNIT,hit->obj->u.obj.world2obj,hit->normal); } v3normalize(hit->normal); } Static VOID pntnormcone(OBJECT *obj,ULONG surface,PNT2 *point, PNT3 *world,VEC3 *normal) { PNT3 locpnt; VEC3 locnormal; if (surface == 1L) { if (point->y < F_SMALL) { locpnt.x = 0.0; locpnt.y = 0.0; } else { locpnt.x = f_cos(point->x * F_2PI) / point->y; locpnt.y = f_sin(point->x * F_2PI) / point->y; } locpnt.z = point->y; locnormal = locpnt; locnormal.z = - locnormal.z; } else { locpnt.x = f_cos(point->x * F_2PI) * point->y; locpnt.y = f_sin(point->x * F_2PI) * point->y; locpnt.z = 1.0; locnormal = V3ZUNIT; } v3vmulm(locpnt,obj->u.obj.obj2world,*world); v3vmultransm(locnormal,obj->u.obj.world2obj,*normal); v3normalize(*normal); } Static VOID hitcoordcone(HITINFO *hit,GEOMPAR needed) { if (needed & (LOCALPNT | GEOM_2DCOORD)) { v3addscaled(hit->ray.origin,hit->ray.direction,hit->t, texinfo.localpnt); texinfo.face = hit->face; if (needed & GEOM_3DCOORD) { texinfo.pnt2[0].x = (1.0 / F_2PI) * f_atan2(texinfo.localpnt.y,texinfo.localpnt.x) + 0.5; if (texinfo.face == 1L) texinfo.pnt2[0].y = texinfo.localpnt.z; else texinfo.pnt2[0].y = f_sqrt(texinfo.localpnt.x * texinfo.localpnt.x + texinfo.localpnt.y * texinfo.localpnt.y); texinfo.num2 = 1; } } } Static BOOLEAN pntcoordcone(OBJECT *obj,GEOMPAR needed) { FLOAT x2_y2; if (needed & (LOCALPNT | GEOM_2DCOORD)) { v3pmulm(texinfo.worldpnt,obj->u.obj.world2obj,texinfo.localpnt); if (needed & GEOM_2DCOORD) { if (texinfo.localpnt.z <= 0.0) /* below 0 */ { texinfo.face = 1L; texinfo.pnt2[0].x = 0.0; texinfo.pnt2[0].y = 0.0; } else { texinfo.pnt2[0].x = (1.0 / F_2PI) * f_atan2(texinfo.localpnt.y,texinfo.localpnt.x) + 0.5; x2_y2 = texinfo.localpnt.x * texinfo.localpnt.x + texinfo.localpnt.y * texinfo.localpnt.y; if (x2_y2 > texinfo.localpnt.z * texinfo.localpnt.z) { /* out of (half) cone ? */ texinfo.face = 1L; if (texinfo.localpnt.z >= 1.0) /* too high */ texinfo.pnt2[0].y = 1.0; else texinfo.pnt2[0].y = texinfo.localpnt.z; } else /* upper cap */ { texinfo.face = 2L; texinfo.pnt2[0].y = f_sqrt(x2_y2) / texinfo.localpnt.z; } } texinfo.num2 = 1; } } return(TRUE); } VOID initcone(VOID) { nameobj[CONE] = "cone"; surfaces[CONE] = 2L; readobj[CONE] = readcone; copyobj[CONE] = copysobj; writeobj[CONE] = writesobj; boundobj[CONE] = boundcone; setupobj[CONE] = setup_primitiv; splitobj[CONE] = split_primitiv; inside[CONE] = insidecone; hitobj[CONE] = hitcone; normalvec[CONE] = normcone; pntnormvec[CONE] = pntnormcone; hitcoord[CONE] = hitcoordcone; pntcoord[CONE] = pntcoordcone; endobj[CONE] = end_primitiv; } ID initcone(VOID) { nameobj[CONE] = "cone"; surfaces[CONE] = 2L; readobj[CONE] = readcone; copyobj[CONE] = copysobj; writeobj[CONE] = writesobj; boundobj[CONE] = boundcone; setupobj[CONE] = setup_primitiv; splitobj[CONE] = split_primitiv; inside[CONE] = insidecone; hitobj[CONE] = hitcone; normalvec[CONE] = normcone; pFlirt/cone.f000644 000316 000311 00000000724 06103226602 013051 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : cone.f cone manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef CONE_F #define CONE_F #include "system.d" VOID initcone PP((VOID)); #endif tcone; nµ¯ «ö¨pE] = normcone; pFlirt/csg.c000644 000316 000311 00000055665 06103226506 012717 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : csg.c routines for csg-objects DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "objects.f" #include "random.f" /* for crc_random's */ #include "scene.f" /* scene_eps */ #include "csg.f" Static VOID shrinkobjects PP((OBJECT *obj,OBJECT *boundingobj)); #define OR_CRC_1 0x72 #define OR_CRC_2 0xAC #define AND_CRC_1 0xF1 #define AND_CRC_2 0x38 #define SUB_CRC_1 0x6F #define SUB_CRC_2 0xE9 #define SAVE_CRC if (rci.do_crc) old_crc = crc_rand; #define UPDATE_CRC(x) if (rci.do_crc) crc_rand_update(x); #define RESTORE_CRC if (rci.do_crc) crc_rand = old_crc; #define SAVE_UPDATE_CRC(x) \ if (rci.do_crc) \ { \ old_crc = crc_rand; \ crc_rand_update(x); \ } #define RESTORE_UPDATE_CRC(x) \ if (rci.do_crc) \ { \ crc_rand = old_crc; \ crc_rand_update(x); \ } Static OBJECT *readcsgor(VOID) { OBJECT *obj; obj = newonlyvar(OBJECT,CSGOBJ); obj->typ = CSG_OR; obj->u.csg.left = readobjects(); obj->u.csg.right = readobjects(); return(obj); } Static OBJECT *readcsgand(VOID) { OBJECT *obj; obj = newonlyvar(OBJECT,CSGOBJ); obj->typ = CSG_AND; obj->u.csg.left = readobjects(); obj->u.csg.right = readobjects(); return(obj); } Static OBJECT *readcsgsub(VOID) { OBJECT *obj; obj = newonlyvar(OBJECT,CSGOBJ); obj->typ = CSG_SUB; obj->u.csg.left = readobjects(); obj->u.csg.right = readobjects(); return(obj); } Static OBJECT *copycsg(OBJECT *obj,BOOLEAN recurse,MAT3 *obj2world, MAT3 *world2obj,MATERIAL *mat,TEXTURE *tex) { OBJECT *newobj; newobj = newonlyvar(OBJECT,CSGOBJ); newobj->typ = obj->typ; if (recurse) { newobj->u.csg.in_or_tree = obj->u.csg.in_or_tree; newobj->u.csg.left = copyobj[obj->u.csg.left->typ](obj->u.csg.left,TRUE, obj2world,world2obj,mat,tex); newobj->u.csg.right = copyobj[obj->u.csg.right->typ](obj->u.csg.right,TRUE, obj2world,world2obj,mat,tex); } else newobj->u.csg = obj->u.csg; return(newobj); } Static VOID writecsg(OBJECT *obj) { writeobjects(obj->u.csg.left); writeobjects(obj->u.csg.right); } Static VOID boundtestoptimize(OBJECT *son, OBJECT *obj) { switch (son->typ) { case CSG_AND: son->test_bsphere = FALSE; /* fall through */ case CSG_SUB: if (son == obj->u.csg.left) son->test_bsphere = FALSE; /* fall through */ case CSG_OR: if (son->test_bbox != BOUNDTEST_NOOPT) { if (son->bbox.min.x == obj->bbox.min.x) son->test_bbox &= ~BOUNDTEST_XMIN; if (son->bbox.max.x == obj->bbox.max.x) son->test_bbox &= ~BOUNDTEST_XMAX; if (son->bbox.min.y == obj->bbox.min.y) son->test_bbox &= ~BOUNDTEST_YMIN; if (son->bbox.max.y == obj->bbox.max.y) son->test_bbox &= ~BOUNDTEST_YMAX; if (son->bbox.min.z == obj->bbox.min.z) son->test_bbox &= ~BOUNDTEST_ZMIN; if (son->bbox.max.z == obj->bbox.max.z) son->test_bbox &= ~BOUNDTEST_ZMAX; } break; default: break; } } VOID combinecsgor(OBJECT *left,OBJECT *right,OBJECT *obj) { FLOAT f,distm; FLOAT rad_l,rad_r; VEC3 diff; v3pmin(left->bbox.min,right->bbox.min,obj->bbox.min); v3pmax(left->bbox.max,right->bbox.max,obj->bbox.max); v3sub(right->bsphere.center,left->bsphere.center,diff); distm = v3length(diff); rad_l = f_sqrt(left->bsphere.radius_2); rad_r = f_sqrt(right->bsphere.radius_2); if (distm + rad_l < rad_r) obj->bsphere = right->bsphere; else if (distm + rad_r < rad_l) obj->bsphere = left->bsphere; else { if (distm == 0.0) f = 0.0; else f = (distm + rad_r - rad_l) / (2.0 * distm); v3addscaled(left->bsphere.center,diff,f,obj->bsphere.center); obj->bsphere.radius_2 = (distm + rad_l + rad_r) / 2.0; obj->bsphere.radius_2 *= obj->bsphere.radius_2; } } VOID combinecsgand(OBJECT *left,OBJECT *right,OBJECT *obj) { FLOAT f,ca,distm; FLOAT rad_l,rad_r; VEC3 diff; v3pmax(left->bbox.min,right->bbox.min,obj->bbox.min); v3pmin(left->bbox.max,right->bbox.max,obj->bbox.max); v3sub(right->bsphere.center,left->bsphere.center,diff); distm = v3length(diff); rad_l = f_sqrt(left->bsphere.radius_2); rad_r = f_sqrt(right->bsphere.radius_2); if (rad_l == 0.0 || rad_r == 0.0 || distm > rad_l + rad_r) { obj->bsphere.center.x = 0.0; obj->bsphere.center.y = 0.0; obj->bsphere.center.z = 0.0; obj->bsphere.radius_2 = 0.0; } else if (distm == 0.0) { obj->bsphere.center = left->bsphere.center; obj->bsphere.radius_2 = mini(rad_l,rad_r); } else if (distm + rad_l < rad_r) { obj->bsphere.center = left->bsphere.center; obj->bsphere.radius_2 = rad_l; } else if (distm + rad_r < rad_l) { obj->bsphere.center = right->bsphere.center; obj->bsphere.radius_2 = rad_r; } else { ca = (distm * distm + right->bsphere.radius_2 - left->bsphere.radius_2) / (2.0 * distm * rad_r); f = (distm - rad_r * ca) / distm; v3addscaled(left->bsphere.center,diff,f,obj->bsphere.center); obj->bsphere.radius_2 = rad_r * f_sqrt(1.0 - ca * ca); } obj->bsphere.radius_2 *= obj->bsphere.radius_2; } /*lint -e715 not referenced */ VOID combinecsgsub(OBJECT *left,OBJECT *right,OBJECT *obj) { obj->bbox = left->bbox; obj->bsphere = left->bsphere; } /*lint +e715 not referenced */ Static VOID boundcsgor(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { ULONG old_crc; OBJECT *left; OBJECT *right; left = obj->u.csg.left; right = obj->u.csg.right; SAVE_UPDATE_CRC(OR_CRC_1); boundobj[left->typ](left,bbox_test,bsphere_test,bounds_test, bbox,bsphere,bounds); RESTORE_UPDATE_CRC(OR_CRC_2); boundobj[right->typ](right,bbox_test,bsphere_test,bounds_test, bbox,bsphere,bounds); RESTORE_CRC; obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? TRUE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; combinecsgor(left,right,obj); boundtestoptimize(left,obj); boundtestoptimize(right,obj); *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static VOID boundcsgand(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { ULONG old_crc; OBJECT *left; OBJECT *right; left = obj->u.csg.left; right = obj->u.csg.right; SAVE_UPDATE_CRC(AND_CRC_1); boundobj[left->typ](left,bbox_test,bsphere_test,bounds_test, bbox,bsphere,bounds); RESTORE_UPDATE_CRC(AND_CRC_2); boundobj[right->typ](right,bbox_test,bsphere_test,bounds_test, bbox,bsphere,bounds); RESTORE_CRC; obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? TRUE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; combinecsgand(left,right,obj); shrinkobjects(left,obj); shrinkobjects(right,obj); combinecsgand(left,right,obj); boundtestoptimize(left,obj); boundtestoptimize(right,obj); *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static VOID boundcsgsub(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { ULONG old_crc; OBJECT *left; OBJECT *right; left = obj->u.csg.left; right = obj->u.csg.right; SAVE_UPDATE_CRC(SUB_CRC_1); boundobj[left->typ](left,bbox_test,bsphere_test,bounds_test, bbox,bsphere,bounds); RESTORE_UPDATE_CRC(SUB_CRC_2); boundobj[right->typ](right,bbox_test,bsphere_test,bounds_test, bbox,bsphere,bounds); RESTORE_CRC; obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? TRUE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; combinecsgsub(left,right,obj); shrinkobjects(right,obj); boundtestoptimize(left,obj); boundtestoptimize(right,obj); *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static VOID shrinkobjects(OBJECT *obj,OBJECT *boundingobj) { if (obj->typ == CSG_OR || obj->typ == CSG_AND || obj->typ == CSG_SUB) { OBJECT *left; OBJECT *right; left = obj->u.csg.left; right = obj->u.csg.right; shrinkobjects(left,boundingobj); shrinkobjects(right,boundingobj); if (obj->typ == CSG_OR) combinecsgor(left,right,obj); else if (obj->typ == CSG_AND) combinecsgand(left,right,obj); else combinecsgsub(left,right,obj); } else { /* FIXME: stupid test */ if (obj->typ != GRID && obj->typ != CYLCUBE && obj->typ != OCTREE && obj->typ != FIVED_TREE && obj->typ != EYE_SHADOW_BUFFER) combinecsgand(obj,boundingobj,obj); } } Static ULONG setupcsg(OBJECT *obj,BOOLEAN in_or_tree,BOOLEAN space_opt) { ULONG objcount; if (obj->typ != CSG_OR) in_or_tree = FALSE; objcount = setupobjects(obj->u.csg.left,in_or_tree,space_opt); objcount += setupobjects(obj->u.csg.right,in_or_tree,space_opt); return(objcount); } Static OBJECT *splitcsg(OBJECT *obj,VOIDPTR bound_volume, BVTESTFUN bv_test,BOOLEAN *changed,ULONG *number_of_objects) { BOOLEAN changedleft,changedright; UINT intersect; ULONG leftnumber,rightnumber; OBJECT *left,*right,*newnode; intersect = bv_test(obj,bound_volume); if (! intersect) { *changed = TRUE; *number_of_objects = 0L; return(NULL); } if (*changed) /* real split */ { changedleft = TRUE; changedright = TRUE; } else /* only counting */ { changedleft = FALSE; changedright = FALSE; } left = obj->u.csg.left; right = obj->u.csg.right; left = splitobj[left->typ](left,bound_volume,bv_test,&changedleft, &leftnumber); right = splitobj[right->typ](right,bound_volume,bv_test,&changedright, &rightnumber); if ((! changedleft && ! changedright) || /* subtrees are also mixed */ intersect == 2 || /* was inside */ ! *changed) /* only counting */ { *number_of_objects = leftnumber + rightnumber; *changed = FALSE; return(obj); } *changed = TRUE; switch (obj->typ) { case CSG_OR: if (left == NULL) { *number_of_objects = rightnumber; return(right); } if (right == NULL) { *number_of_objects = leftnumber; return(left); } newnode = copyobj[obj->typ](obj,FALSE,NULL,NULL,NULL,NULL); combinecsgor(left,right,newnode); break; case CSG_AND: if (left == NULL || right == NULL) { *number_of_objects = 0L; return(NULL); } newnode = copyobj[obj->typ](obj,FALSE,NULL,NULL,NULL,NULL); combinecsgand(left,right,newnode); break; case CSG_SUB: if (left == NULL) { *number_of_objects = 0L; return(NULL); } if (right == NULL) { *number_of_objects = leftnumber; return(left); } newnode = copyobj[obj->typ](obj,FALSE,NULL,NULL,NULL,NULL); combinecsgsub(left,right,newnode); break; default: return(NULL); } newnode->test_bbox = obj->test_bbox; newnode->test_bsphere = obj->test_bsphere; newnode->u.csg.left = left; newnode->u.csg.right = right; *number_of_objects = leftnumber + rightnumber; return(newnode); } Static OBJECT *insidecsgor(PNT3 *pnt,OBJECT *obj) { ULONG old_crc; OBJECT *c; if (obj->test_bbox && ! insidebbox(pnt,&(obj->bbox))) return(NULL); SAVE_UPDATE_CRC(OR_CRC_1); c = inside[obj->u.csg.left->typ](pnt,obj->u.csg.left); RESTORE_CRC; if (c != NULL) return(c); UPDATE_CRC(OR_CRC_2); c = inside[obj->u.csg.right->typ](pnt,obj->u.csg.right); RESTORE_CRC; return(c); } Static OBJECT *insidecsgand(PNT3 *pnt,OBJECT *obj) { ULONG old_crc; OBJECT *c; if (obj->test_bbox && ! insidebbox(pnt,&(obj->bbox))) return(NULL); SAVE_UPDATE_CRC(AND_CRC_1); c = inside[obj->u.csg.left->typ](pnt,obj->u.csg.left); RESTORE_CRC; if (c == NULL) return(NULL); UPDATE_CRC(AND_CRC_2); c = inside[obj->u.csg.right->typ](pnt,obj->u.csg.right); RESTORE_CRC; return(c); } Static OBJECT *insidecsgsub(PNT3 *pnt,OBJECT *obj) { ULONG old_crc; OBJECT *c,*c1; if (obj->test_bbox && ! insidebbox(pnt,&(obj->bbox))) return(NULL); SAVE_UPDATE_CRC(SUB_CRC_1); c = inside[obj->u.csg.left->typ](pnt,obj->u.csg.left); RESTORE_CRC; if (c == NULL) return(NULL); UPDATE_CRC(SUB_CRC_2); c1 = inside[obj->u.csg.right->typ](pnt,obj->u.csg.right); RESTORE_CRC; if (c1 == NULL) return(c); return(NULL); } Static BOOLEAN hitcsgor(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) { ULONG old_crc; BOOLEAN left,right; FLOAT lefttmin,lefttmax; HITLIST lochitlist; lefttmin = tmin; lefttmax = tmax; HITBOUNDSONLY(obj->u.csg.left,lefttmin,lefttmax,left); HITBOUNDSONLY(obj->u.csg.right,tmin,tmax,right); SAVE_CRC; if (! left) { /* maybe only right bbox hit */ if (right) { UPDATE_CRC(OR_CRC_2); HITOBJONLY(obj->u.csg.right,tmin,tmax,hitlist,right); RESTORE_CRC; } return(right); } else if (! right) /* only left bbox hit */ { UPDATE_CRC(OR_CRC_1); HITOBJONLY(obj->u.csg.left,lefttmin,lefttmax,hitlist,left); RESTORE_CRC; return(left); } /* both bboxes were hit -> go down both sub-tree's */ lochitlist = emptyhitlist; if (lefttmin <= tmin) /* left before right */ { UPDATE_CRC(OR_CRC_1); HITOBJONLY(obj->u.csg.left,lefttmin,lefttmax,&lochitlist,left); RESTORE_CRC; if (left) { if (rci.shadow || ! obj->u.csg.in_or_tree || lochitlist.first->t >= tmin - scene_eps) { HITLIST righthitlist; righthitlist = emptyhitlist; UPDATE_CRC(OR_CRC_2); HITOBJONLY(obj->u.csg.right,tmin,tmax,&righthitlist,right); RESTORE_CRC; if (right) return orhitlists(&lochitlist,&righthitlist,hitlist); if (righthitlist.firstobj != NULL) replacenull(&lochitlist,righthitlist.firstobj); } *hitlist = lochitlist; } else { if (lochitlist.firstobj == NULL) { UPDATE_CRC(OR_CRC_2); HITOBJONLY(obj->u.csg.right,tmin,tmax,hitlist,right); RESTORE_CRC; return(right); } *hitlist = lochitlist; return(FALSE); } } else /* right before left */ { UPDATE_CRC(OR_CRC_2); HITOBJONLY(obj->u.csg.right,tmin,tmax,&lochitlist,right); RESTORE_CRC; if (right) { if (rci.shadow || ! obj->u.csg.in_or_tree || lochitlist.first->t >= lefttmin - scene_eps) { HITLIST lefthitlist; lefthitlist = emptyhitlist; UPDATE_CRC(OR_CRC_1); HITOBJONLY(obj->u.csg.left,lefttmin,lefttmax,&lefthitlist,left); RESTORE_CRC; if (left) return orhitlists(&lefthitlist,&lochitlist,hitlist); if (lefthitlist.firstobj != NULL) { freehitlist(&lochitlist); *hitlist = lefthitlist; return(FALSE); } } *hitlist = lochitlist; } else { UPDATE_CRC(OR_CRC_1); HITOBJONLY(obj->u.csg.left,lefttmin,lefttmax,hitlist,left); RESTORE_CRC; if (left) { if (lochitlist.firstobj != NULL) replacenull(hitlist,lochitlist.firstobj); return(TRUE); } if (hitlist->firstobj == NULL) hitlist->firstobj = lochitlist.firstobj; return(FALSE); } } return(TRUE); } Static BOOLEAN hitcsgand(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) { ULONG old_crc; BOOLEAN left,right; FLOAT lefttmin,lefttmax; HITLIST lefthitlist; lefthitlist = emptyhitlist; lefttmin = tmin; lefttmax = tmax; HITBOUNDSONLY(obj->u.csg.left,lefttmin,lefttmax,left); if (left) { HITBOUNDSONLY(obj->u.csg.right,tmin,tmax,right); } else right = FALSE; if (! left || ! right) return(FALSE); SAVE_UPDATE_CRC(AND_CRC_1); HITOBJONLY(obj->u.csg.left,lefttmin,lefttmax,&lefthitlist,left); RESTORE_CRC; if (left) { HITLIST righthitlist; if (lefthitlist.firstobj == NULL) tmin = lefthitlist.first->t; if (lefthitlist.last->newobj == NULL) tmax = lefthitlist.last->t; righthitlist = emptyhitlist; UPDATE_CRC(AND_CRC_2); HITOBJONLY(obj->u.csg.right,tmin,tmax,&righthitlist,right); RESTORE_CRC; if (right) return andhitlists(&lefthitlist,&righthitlist,hitlist); if (righthitlist.firstobj != NULL) { *hitlist = lefthitlist; return(TRUE); } freehitlist(&lefthitlist); } else if (lefthitlist.firstobj != NULL) { UPDATE_CRC(AND_CRC_2); HITOBJONLY(obj->u.csg.right,tmin,tmax,hitlist,right); RESTORE_CRC; if (right) { replaceobj(hitlist,lefthitlist.firstobj); returnhitlist(hitlist); } if (hitlist->firstobj != NULL) *hitlist = lefthitlist; } return(FALSE); } Static BOOLEAN hitcsgsub(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) { ULONG old_crc; BOOLEAN ray_hit_obj; FLOAT lefttmin,lefttmax; HITLIST lefthitlist; lefthitlist = emptyhitlist; lefttmin = tmin; lefttmax = tmax; SAVE_UPDATE_CRC(SUB_CRC_1); HITOBJ(obj->u.csg.left,lefttmin,lefttmax,&lefthitlist,ray_hit_obj); RESTORE_CRC; if (ray_hit_obj) { HITLIST righthitlist; if (lefthitlist.firstobj == NULL) tmin = lefthitlist.first->t; if (lefthitlist.last->newobj == NULL) tmax = lefthitlist.last->t; righthitlist = emptyhitlist; UPDATE_CRC(SUB_CRC_2); HITOBJ(obj->u.csg.right,tmin,tmax,&righthitlist,ray_hit_obj); RESTORE_CRC; if (ray_hit_obj) return subhitlists(&lefthitlist,&righthitlist,hitlist); if (righthitlist.firstobj == NULL) { *hitlist = lefthitlist; return(TRUE); } freehitlist(&lefthitlist); } else if (lefthitlist.firstobj != NULL) { UPDATE_CRC(SUB_CRC_2); HITOBJ(obj->u.csg.right,tmin,tmax,hitlist,ray_hit_obj); RESTORE_CRC; if (ray_hit_obj) { replaceall(hitlist,lefthitlist.firstobj); returnhitlist(hitlist); } if (hitlist->firstobj != NULL) hitlist->firstobj = NULL; else *hitlist = lefthitlist; } return(FALSE); } Static VOID endcsg(OBJECT *obj) { endobj[obj->u.csg.left->typ](obj->u.csg.left); endobj[obj->u.csg.right->typ](obj->u.csg.right); } VOID initcsg(VOID) { nameobj[CSG_OR] = "csg_or"; readobj[CSG_OR] = readcsgor; copyobj[CSG_OR] = copycsg; writeobj[CSG_OR] = writecsg; boundobj[CSG_OR] = boundcsgor; setupobj[CSG_OR] = setupcsg; splitobj[CSG_OR] = splitcsg; inside[CSG_OR] = insidecsgor; hitobj[CSG_OR] = hitcsgor; endobj[CSG_OR] = endcsg; nameobj[CSG_AND] = "csg_and"; readobj[CSG_AND] = readcsgand; copyobj[CSG_AND] = copycsg; writeobj[CSG_AND] = writecsg; boundobj[CSG_AND] = boundcsgand; setupobj[CSG_AND] = setupcsg; splitobj[CSG_AND] = splitcsg; inside[CSG_AND] = insidecsgand; hitobj[CSG_AND] = hitcsgand; endobj[CSG_AND] = endcsg; nameobj[CSG_SUB] = "csg_sub"; readobj[CSG_SUB] = readcsgsub; copyobj[CSG_SUB] = copycsg; writeobj[CSG_SUB] = writecsg; boundobj[CSG_SUB] = boundcsgsub; setupobj[CSG_SUB] = setupcsg; splitobj[CSG_SUB] = splitcsg; inside[CSG_SUB] = insidecsgsub; hitobj[CSG_SUB] = hitcsgsub; endobj[CSG_SUB] = endcsg; } setupobj[CSG_AND] = setupcsg; splitobj[CSG_AND] = splitcsg; insidFlirt/csg.f000644 000316 000311 00000001240 06103226604 012675 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : csg.f classification routines for csg-objects DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef CSG_F #define CSG_F #include "objects.d" VOID initcsg PP((VOID)); VOID combinecsgor PP((OBJECT *left,OBJECT *right,OBJECT *obj)); VOID combinecsgand PP((OBJECT *left,OBJECT *right,OBJECT *obj)); VOID combinecsgsub PP((OBJECT *left,OBJECT *right,OBJECT *obj)); #endif objects DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef CSG_F #define CSG_F #include "objects.d" VOID initcsg PP((VOID)); VOID combinecsgor PP((OBJECT *left,OBJECT *Flirt/cube.c000644 000316 000311 00000027506 06103226510 013045 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : cube.c Cube manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "texture.f" #include "objects.f" #include "readdata.f" #include "material.f" #include "texture.f" #include "cube.f" Static scube_allowed = TRUE; Static OBJECT *readcube(VOID) { OBJECT *obj,node; node.typ = CUBE; readcubetrans(&(node.u.obj.obj2world),&(node.u.obj.world2obj)); node.u.obj.material = readnamematerial(); node.u.obj.texture = readnametexture(); obj = copyobj[node.typ](&node,FALSE,NULL,NULL,NULL,NULL); return(obj); } Static OBJECT *copycube(OBJECT *obj,BOOLEAN recurse,MAT3 *to,MAT3 *fr, MATERIAL *mat,TEXTURE *tex) { OBJECT *newobj; MAT3 m; TURNINFO turninfo; BOX3 box; if (to == NULL) m = obj->u.obj.obj2world; else { m3mmulm(obj->u.obj.obj2world,*to,m); } if (scube_allowed && mat2turnbox(&m,&turninfo,&box) && tex == NULL && obj->u.obj.texture == NULL) { newobj = newonlyvar(OBJECT,SCUBEOBJ); newobj->typ = SIMPLE_CUBE; newobj->u.scube.box = box; newobj->u.scube.turninfo = turninfo; } else { newobj = newonlyvar(OBJECT,SIMPLEOBJ); newobj->typ = CUBE; newobj->u.obj.obj2world = m; if (fr == NULL) m = obj->u.obj.world2obj; else { m3mmulm(*fr,obj->u.obj.world2obj,m); } newobj->u.obj.world2obj = m; } newobj->u.obj.material = obj->u.obj.material; newobj->u.obj.texture = obj->u.obj.texture; if (mat != NULL) newobj->u.obj.material = mat; if (tex != NULL) newobj->u.obj.texture = tex; return(newobj); } Static PNT3 hull_cube[8] = { { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }, { 1.0, 0.0, 1.0 }, { 0.0, 1.0, 0.0 }, { 1.0, 1.0, 0.0 }, { 0.0, 1.0, 1.0 }, { 1.0, 1.0, 1.0 } }; Static PNT3 midcube = { 0.5, 0.5, 0.5 }; Static VOID boundcube(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? TRUE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; bounds4points(8,hull_cube,&(obj->bbox),&(obj->bsphere),&midcube, &(obj->u.obj.obj2world)); *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static OBJECT *insidecube(PNT3 *pnt,OBJECT *obj) { PNT3 locpnt; INSIDE_BOUND_TEST(obj,pnt); v3pmulm(*pnt,obj->u.obj.world2obj,locpnt); if (0.0 < locpnt.x && locpnt.x < 1.0 && 0.0 < locpnt.y && locpnt.y < 1.0 && 0.0 < locpnt.z && locpnt.z < 1.0) return(obj); return(NULL); } /* ------------------------------------------------------------------------ */ Static BOOLEAN hitcube(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) /* ------------------------------------------------------------------------ calculate intersection of ray and cube ------------------------------------------------------------------------ */ { ULONG tminface = 0L; ULONG tmaxface = 0L; HITINFO *hit1,*hit2; FLOAT hit; RAY3 locray; PRE_OBJECT(obj,hitlist); v3pmulm(rci.ray.origin,obj->u.obj.world2obj,locray.origin); v3vmulm(rci.ray.direction,obj->u.obj.world2obj,locray.direction); if (locray.direction.x > 0.0) { hit = - locray.origin.x / locray.direction.x; checkaddmin(1L,hit,tminface,tmin,tmax); hit = (1.0 - locray.origin.x) / locray.direction.x; checkaddmax(2L,hit,tmaxface,tmin,tmax); } else if (locray.direction.x < 0.0) { hit = (1.0 - locray.origin.x) / locray.direction.x; checkaddmin(2L,hit,tminface,tmin,tmax); hit = - locray.origin.x / locray.direction.x; checkaddmax(1L,hit,tmaxface,tmin,tmax); } else /* ray parallel to x-planes ? */ { if (locray.origin.x <= 0.0 || locray.origin.x >= 1.0) return FALSE; } if (locray.direction.y > 0.0) { hit = - locray.origin.y / locray.direction.y; checkaddmin(3L,hit,tminface,tmin,tmax); hit = (1.0 - locray.origin.y) / locray.direction.y; checkaddmax(4L,hit,tmaxface,tmin,tmax); } else if (locray.direction.y < 0.0) { hit = (1.0 - locray.origin.y) / locray.direction.y; checkaddmin(4L,hit,tminface,tmin,tmax); hit = - locray.origin.y / locray.direction.y; checkaddmax(3L,hit,tmaxface,tmin,tmax); } else /* ray parallel to y-planes ? */ { if (locray.origin.y <= 0.0 || locray.origin.y >= 1.0) return FALSE; } if (locray.direction.z > 0.0) { hit = - locray.origin.z / locray.direction.z; checkaddmin(5L,hit,tminface,tmin,tmax); hit = (1.0 - locray.origin.z) / locray.direction.z; checkaddmax(6L,hit,tmaxface,tmin,tmax); } else if (locray.direction.z < 0.0) { hit = (1.0 - locray.origin.z) / locray.direction.z; checkaddmin(6L,hit,tminface,tmin,tmax); hit = - locray.origin.z / locray.direction.z; checkaddmax(5L,hit,tmaxface,tmin,tmax); } else /* ray parallel to x-planes ? */ { if (locray.origin.z <= 0.0 || locray.origin.z >= 1.0) return FALSE; } checkmakerayhit(tminface,tmin,locray,hit1); checkmakerayhit(tmaxface,tmax,locray,hit2); prepare2hits(obj,hit1,hit2,hitlist); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } Static VOID normcube(HITINFO *hit) { v3vmultransm(box_normal[hit->face],hit->obj->u.obj.world2obj,hit->normal); v3normalize(hit->normal); } Static VOID pntnormcube(OBJECT *obj,ULONG surface,PNT2 *point, PNT3 *world,VEC3 *normal) { PNT3 locpnt; locpnt = V3ZERO; switch ((INT) surface) { case 1: locpnt.y = point->x; locpnt.z = point->y; break; case 2: locpnt.x = 1.0; locpnt.z = point->x; locpnt.y = point->y; break; case 3: locpnt.z = point->x; locpnt.x = point->y; break; case 4: locpnt.y = 1.0; locpnt.x = point->x; locpnt.z = point->y; break; case 5: locpnt.x = point->x; locpnt.y = point->y; break; case 6: locpnt.z = 1.0; locpnt.y = point->x; locpnt.x = point->y; break; } v3vmulm(locpnt,obj->u.obj.obj2world,*world); v3vmultransm(box_normal[surface],obj->u.obj.world2obj,*normal); v3normalize(*normal); } Static VOID hitcoordcube(HITINFO *hit,GEOMPAR needed) { if (needed & (LOCALPNT | GEOM_2DCOORD)) { v3addscaled(hit->ray.origin,hit->ray.direction,hit->t, texinfo.localpnt); texinfo.face = hit->face; if (needed & GEOM_2DCOORD) { switch ((INT) texinfo.face) { case 1: texinfo.pnt2[0].x = texinfo.localpnt.y; texinfo.pnt2[0].y = texinfo.localpnt.z; break; case 2: texinfo.pnt2[0].x = texinfo.localpnt.z; texinfo.pnt2[0].y = texinfo.localpnt.y; break; case 3: texinfo.pnt2[0].x = texinfo.localpnt.z; texinfo.pnt2[0].y = texinfo.localpnt.x; break; case 4: texinfo.pnt2[0].x = texinfo.localpnt.x; texinfo.pnt2[0].y = texinfo.localpnt.z; break; case 5: texinfo.pnt2[0].x = texinfo.localpnt.x; texinfo.pnt2[0].y = texinfo.localpnt.y; break; case 6: texinfo.pnt2[0].x = texinfo.localpnt.y; texinfo.pnt2[0].y = texinfo.localpnt.x; break; } texinfo.num2 = 1; } } } Static BOOLEAN pntcoordcube(OBJECT *obj,GEOMPAR needed) { FLOAT absx,absy; PNT3 localpnt; if (needed & (LOCALPNT | GEOM_2DCOORD)) { v3pmulm(texinfo.worldpnt,obj->u.obj.world2obj,texinfo.localpnt); if (needed & GEOM_2DCOORD) { v3sub(texinfo.localpnt,midcube,localpnt); absx = f_abs(localpnt.x); absy = f_abs(localpnt.y); if (absx > absy) if (absx > f_abs(localpnt.z)) if (localpnt.x < 0.0) texinfo.face = 1L; else texinfo.face = 2L; else if (localpnt.z < 0.0) texinfo.face = 5L; else texinfo.face = 6L; else if (absy > f_abs(localpnt.z)) if (localpnt.y < 0.0) texinfo.face = 3L; else texinfo.face = 4L; else if (localpnt.z < 0.0) texinfo.face = 5L; else texinfo.face = 6L; switch ((INT) texinfo.face) { case 1: texinfo.pnt2[0].x = localpnt.y / localpnt.x; texinfo.pnt2[0].y = localpnt.z / localpnt.x; break; case 2: texinfo.pnt2[0].x = localpnt.z / localpnt.x; texinfo.pnt2[0].y = localpnt.y / localpnt.x; break; case 3: texinfo.pnt2[0].x = localpnt.z / localpnt.y; texinfo.pnt2[0].y = localpnt.x / localpnt.y; break; case 4: texinfo.pnt2[0].x = localpnt.x / localpnt.y; texinfo.pnt2[0].y = localpnt.z / localpnt.y; break; case 5: texinfo.pnt2[0].x = localpnt.x / localpnt.z; texinfo.pnt2[0].y = localpnt.y / localpnt.z; break; case 6: texinfo.pnt2[0].x = localpnt.y / localpnt.z; texinfo.pnt2[0].y = localpnt.x / localpnt.z; break; } texinfo.pnt2[0].x = (texinfo.pnt2[0].x + 1.0) * 0.5; texinfo.pnt2[0].y = (texinfo.pnt2[0].y + 1.0) * 0.5; texinfo.num2 = 1; } } return(TRUE); } VOID initcube(BOOLEAN scube_ok) { scube_allowed = scube_ok; nameobj[CUBE] = "cube"; surfaces[CUBE] = 6L; readobj[CUBE] = readcube; writeobj[CUBE] = writesobj; copyobj[CUBE] = copycube; boundobj[CUBE] = boundcube; setupobj[CUBE] = setup_primitiv; splitobj[CUBE] = split_primitiv; inside[CUBE] = insidecube; hitobj[CUBE] = hitcube; normalvec[CUBE] = normcube; pntnormvec[CUBE] = pntnormcube; hitcoord[CUBE] = hitcoordcube; pntcoord[CUBE] = pntcoordcube; endobj[CUBE] = end_primitiv; } be_allowed = scube_ok; nameobj[CUBE] = "cube"; surfaces[CUBE] = 6L; readobj[CUBE] = readcube; writeobj[CUBE] = writesobj; copyobj[CUBE] = copycube; boundobj[CUBEFlirt/cube.f000644 000316 000311 00000000740 06103226604 013043 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : cube.f Cube manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef CUBE_F #define CUBE_F #include "system.d" VOID initcube PP((BOOLEAN scube_ok)); #endif µ¯ «ö¨aÀe; boundobj[CUBEFlirt/cylcube.c000644 000316 000311 00000043667 06103226510 013563 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : cylcube.c cylcube manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "objects.f" #include "csg.f" #include "readdata.f" #include "writdata.f" #include "scene.f" /* scene_eps */ #include "cylcube.f" typedef struct cylinder3 { AXIS3 axis; FLOAT radius; } CYLINDER3; Static UINT count = 0; /* Mapping of four-dimensional array on one-dimensional array */ #define INDEX(i,j,k,l,n_2) (i + 6*(j + n_2 *(k + 6 * l))) /*Static VOID dump(OBJECT **node,ULONG subd) { ULONG ind,i,j,k,l; for(i = 0; i< 5 ;i++) { for(j = 0; j <= (UINT) (subd-1); j++) { for(k = 0; k<=5 ; k++) { for(l = 0; l <= (UINT) (subd-1); l++) { ind = INDEX(i,j,k,l,subd); log_message("IN: %3d %3d OUT: %3d %3d ",i,j,k,l); log_message(" Objecte : "); if (node[ind] == NULL) { log_message("Null - Pointer\n"); } else { writeobjects(node[ind]); } } } } } }*/ Static OBJECT *readcylcube(VOID) { ULONG size; OBJECT *obj; obj = newonlyvar(OBJECT,CYLCUBEOBJ); obj->typ = CYLCUBE; readconststring("subdivisions"); obj->u.cylcube.subdivisions = (INT) readuint(); obj->u.cylcube.num_squares = obj->u.cylcube.subdivisions * obj->u.cylcube.subdivisions; obj->u.cylcube.original = readobjects(); size = (ULONG)(6L * 6L * obj->u.cylcube.num_squares * obj->u.cylcube.num_squares) * (ULONG)sizeof(OBJECT *); obj->u.cylcube.cylcube = (OBJECT **)newonlymem(size); return(obj); } Static OBJECT *copycylcube(OBJECT *obj,BOOLEAN recurse,MAT3 *to,MAT3 *fr, MATERIAL *mat,TEXTURE *tex) { ULONG size; OBJECT *newobj; newobj = newonlyvar(OBJECT,CYLCUBE); newobj->typ = obj->typ; newobj->u.cylcube = obj->u.cylcube; size = (ULONG)(6L * 6L * obj->u.cylcube.num_squares * obj->u.cylcube.num_squares) * (ULONG)sizeof(OBJECT *); newobj->u.cylcube.cylcube = (OBJECT **)newonlymem(size); message("copycylcube\n"); if (recurse) newobj->u.cylcube.original = copyobj[obj->u.cylcube.original->typ] (obj->u.cylcube.original,TRUE,to,fr,mat,tex); else newobj->u.cylcube.original = obj->u.cylcube.original; return(newobj); } Static VOID writecylcube(OBJECT *obj) { writestring("subdivisions"); writeuint(obj->u.cylcube.subdivisions); writelf(); writeobjects(obj->u.cylcube.original); } Static VOID boundcylcube(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { boundobj[obj->u.cylcube.original->typ](obj->u.cylcube.original,bbox_test, bsphere_test,bounds_test,bbox,bsphere,bounds); obj->test_bbox = (bbox_test) ? BOUNDTEST_NONE : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? FALSE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; obj->bbox = obj->u.cylcube.original->bbox; obj->bsphere = obj->u.cylcube.original->bsphere; *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static FLOAT distance(AXIS3 *axis,PNT3 *point) { VEC3 vec1; FLOAT t,f; PNT3 q; v3sub(*point,axis->origin,vec1); t = v3dot(axis->direction,vec1); t /= v3length_2(axis->direction); v3addscaled(axis->origin,axis->direction,t,q); v3dist(*point,q,f); return(f); } Static UINT cyl_cube_test(OBJECT *obj,VOIDPTR bound_volume) { CYLINDER3 *cyl; FLOAT dist,sum,rad; cyl = (CYLINDER3 *) bound_volume; rad = f_sqrt(obj->bsphere.radius_2); sum = rad + cyl->radius; dist = distance(&(cyl->axis),&(obj->bsphere.center)); if (dist < sum ) { if (cyl->radius > dist + rad) return(2); /* totally inside */ return(1); /* intersection */ } return(0); /* no intersection */ } Static FLOAT cyl_rad(AXIS3 *cylaxis, VEC3 *v1, VEC3 *v2) { FLOAT dist1,dist2; PNT3 pkt; v3add(cylaxis->origin,*v1,pkt); dist1 = distance(cylaxis, &pkt); v3add(cylaxis->origin,*v2, pkt); dist2 = distance(cylaxis, &pkt); return(maxi(dist1,dist2)); } Static VOID Init_point(BOX3 *box,VEC3 *len,ULONG face,PNT3 *point) { /* Initialisierung der Ein- bzw. Austrittspunkte */ switch((INT)face) { case 0: point->x = box->min.x; point->y = box->max.y - len->y / 2; point->z = box->min.z + len->z / 2; break; case 1: point->x = box->max.x; point->y = box->min.y + len->y / 2; point->z = box->min.z + len->z / 2; break; case 2: point->x = box->min.x + len->x / 2; point->y = box->min.y; point->z = box->min.z + len->z / 2; break; case 3: point->x = box->max.x - len->x / 2; point->y = box->max.y; point->z = box->min.z + len->z / 2; break; case 4: point->x = box->min.x + len->x / 2; point->y = box->min.y + len->y / 2; point->z = box->min.z ; break; case 5: point->x = box->max.x - len->x / 2; point->y = box->min.y + len->y / 2; point->z = box->max.z; break; } } Static ULONG setupcylcube(OBJECT *obj,BOOLEAN in_or_tree,BOOLEAN space_opt) { BOOLEAN changed; ULONG i,j,k,l,indx,subd; ULONG number_of_objects,number_of_objects1,sub_2; VEC3 box_len,len,len_half; /* Seitenlaenge , Laenge eines Quadrates */ VEC3 vec1,vec2; PNT3 in,out; /* Eintrittspunkt , Austrittspunkt des Strahles */ OBJECT **node; CYLCUBEOBJ *cylcubeobj; BOX3 bbox; CYLINDER3 cyl; if (! in_or_tree) fatal("cylcube not in or_tree"); number_of_objects = setupobjects(obj->u.cylcube.original,TRUE,TRUE); cylcubeobj = &(obj->u.cylcube); node = cylcubeobj->cylcube; bbox = obj->bbox; v3sub(bbox.max,bbox.min,box_len); subd = cylcubeobj->subdivisions; len.x = box_len.x / subd; /* square-length */ len.y = box_len.y / subd; len.z = box_len.z / subd; len_half = len; v3scale(len_half, 0.5); sub_2 = cylcubeobj->num_squares; for (i = 0; i < 5 ; i++) { Init_point(&bbox,&len,i,&in); /* Initialisierung */ for (j = 0; j <= (sub_2 - 1) ; j++) { for (k = i + 1; k <= 5 ; k++) { /* Initialisierung */ Init_point(&bbox,&len,k,&out); switch ((UINT)k) { case 1: vec1.x = 0.0; vec1.y = len_half.y; vec1.z = len_half.z; vec2.x = 0.0; vec2.y = - len_half.y; vec2.z = len_half.z; break; case 2: vec1.x = len_half.x; vec1.y = 0.0; vec1.z = len_half.z; vec2.x = - len_half.x ; vec2.y = 0.0; vec2.z = len_half.z ; break; case 3: vec1.x = len_half.x ; vec1.y = 0.0; vec1.z = len_half.z ; vec2.x = - len_half.x ; vec2.y = 0.0; vec2.z = len_half.z ; break; case 4: vec1.x = len_half.x ; vec1.y = len_half.y ; vec1.z = 0.0; vec2.x = len_half.x ; vec2.y = - len_half.y ; vec2.z = 0.0; break; case 5: vec1.x = len_half.x ; vec1.y = len_half.y ; vec1.z = 0.0; vec2.x = len_half.x ; vec2.y = - len_half.y ; vec2.z = 0.0; break; } for (l = 0; l<= (sub_2 - 1) ; l++) { cyl.axis.origin = out; v3sub(in,out,cyl.axis.direction); cyl.radius = cyl_rad(&(cyl.axis),&vec1,&vec2); changed = TRUE; indx = INDEX(i,j,k,l,sub_2); node[indx] = splitobj[cylcubeobj->original->typ] (cylcubeobj->original,(VOIDPTR) &cyl, cyl_cube_test,&changed,&number_of_objects1); switch ((INT)k) { case 1: if (l % subd == subd - 1) { out.y = bbox.min.y + len_half.y; out.z += len.z; } else out.y += len.y; break; case 2: if (l % subd == subd - 1) { out.x = bbox.min.x + len_half.x; out.z += len.z; } else out.x += len.x; break; case 3: if (l % subd == subd - 1) { out.x = bbox.max.x - len_half.x; out.z += len.z; } else out.x -= len.x; break; case 4: if (l % subd == subd - 1) { out.y = bbox.min.y + len_half.y; out.x += len.x; } else out.y += len.y; break; case 5: if (l % subd == subd- 1) { out.y = bbox.min.y + len_half.y; out.x -= len.x; } else out.y += len.y; break; } } } switch ((INT)i) { case 0: if (j % subd == subd - 1) { in.y = bbox.max.y - len_half.y; in.z += len.z; } else in.y -= len.y; break; case 1: if (j % subd == subd - 1 ) { in.y = bbox.min.y + len_half.y; in.z += len.z; } else in.y += len.y; break; case 2: if (j % subd == subd - 1) { in.x = bbox.min.x + len_half.x; in.z += len.z; } else in.x += len.x; break; case 3: if (j % subd == subd - 1) { in.x = bbox.max.x - len_half.x; in.z += len.z; } else in.x -= len.x; break; case 4: if (j % subd == subd - 1) { in.y = bbox.min.y + len_half.y; in.x += len.x; } else in.y += len.y; break; case 5: if(j % subd == subd - 1) { in.y = bbox.min.y + len_half.y; in.x -= len.x; } else in.y += len.y; break; } } } /* dump(node,subd); */ return(number_of_objects); } Static OBJECT *insidecylcube(PNT3 *pnt,OBJECT *obj) { INSIDE_BOUND_TEST(obj,pnt); return(inside[obj->u.cylcube.original->typ](pnt,obj->u.cylcube.original)); } Static INT hitcoordface(INTPNT3 point,ULONG face,INT subdiv) { switch((INT)face) { case 0L: return((subdiv * point.z) + (subdiv - point.y - 1)); break; case 1L: return(point.z * subdiv + point.y); break; case 2L: return(point.z * subdiv + point.x); break; case 3L: return((subdiv * point.z) + (subdiv - point.x - 1)); break; case 4L: return(point.x * subdiv + point.y); break; case 5L: return((subdiv * (subdiv - 1 - point.x)) + point.y); break; } return(0); } Static BOOLEAN hit_bounds(OBJECT *obj,RAY3 *ray,FLOAT *tmin,FLOAT *tmax) { return((BOOLEAN) ((obj->test_bbox == 0 || hitbbox(ray,tmin,tmax, obj->test_bbox,&(obj->bbox))) && (! obj->test_bsphere || hitbsphere(ray,tmin,tmax, &(obj->bsphere))) && (obj->bounds == NULL || hitbounds(ray,tmin,tmax,obj->bounds)))); } Static VOID hit_obj(OBJECT *obj,FLOAT tmin,FLOAT tmax,HITLIST *hitlst, BOOLEAN *ray_hit_obj) { *ray_hit_obj = (BOOLEAN) hit_bounds(obj,&(rci.ray),&tmin,&tmax); if(ray_hit_obj) { count++; *ray_hit_obj = hitobj[obj->typ](tmin,tmax,obj,hitlst); raysobj[obj->typ]++; } } /* ------------------------------------------------------------------------ */ Static BOOLEAN hitcylcube(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) /* --------------------------------------------------------------------------- calculate intersection with ray and cylcube --------------------------------------------------------------------------- */ { BOOLEAN ray_hit_obj; ULONG ind2,ind1,index; ULONG t,in_face,out_face,sub_2; INTPNT3 in_el,out_el; INT subdivisions; PNT3 in,out; VEC3 box_len,len; OBJECT *node; CYLCUBEOBJ *cylcube; FLOAT tmin_box,tmax_box; PRE_OBJECT(obj,hitlist); cylcube = &(obj->u.cylcube); if (!(hitbox(&rci.ray,&tmin_box,&tmax_box,&in_face,&out_face,&(obj->bbox)))) return(FALSE); if (tmax_box < tmin) return(FALSE); if (tmin_box >= tmax) return(FALSE); if (tmin < tmin_box) tmin = tmin_box; if (tmax > tmax_box) tmax = tmax_box; in_face--; out_face--; subdivisions = (INT) cylcube->subdivisions; v3sub(obj->bbox.max,obj->bbox.min,box_len); len = box_len; v3divk(len,subdivisions); /* square-length */ v3addscaled(rci.ray.origin,rci.ray.direction,tmin_box,in); v3addscaled(rci.ray.origin,rci.ray.direction,tmax_box,out); in_el.x = (INT)f_floor((in.x - obj->bbox.min.x) / len.x); in_el.y = (INT)f_floor((in.y - obj->bbox.min.y) / len.y); in_el.z = (INT)f_floor((in.z - obj->bbox.min.z) / len.z); subdivisions--; in_el.x = maxi(in_el.x,0); in_el.x = mini(in_el.x,subdivisions); in_el.y = maxi(in_el.y,0); in_el.y = mini(in_el.y,subdivisions); in_el.z = maxi(in_el.z,0); in_el.z = mini(in_el.z,subdivisions); out_el.x = (INT) f_floor((out.x - obj->bbox.min.x) /len.x); out_el.y = (INT) f_floor((out.y - obj->bbox.min.y) /len.y); out_el.z = (INT) f_floor((out.z - obj->bbox.min.z) /len.z); out_el.x = maxi(out_el.x,0); out_el.x = mini(out_el.x,subdivisions); out_el.y = maxi(out_el.y,0); out_el.y = mini(out_el.y,subdivisions); out_el.z = maxi(out_el.z,0); out_el.z = mini(out_el.z,subdivisions); subdivisions++; sub_2 = cylcube->num_squares; ind1 = hitcoordface(in_el,in_face,subdivisions); ind2 = hitcoordface(out_el,out_face,subdivisions); if (in_face > out_face) { t = in_face; in_face = out_face; out_face = t; t = ind1; ind1 = ind2; ind2 = t; } index = INDEX(in_face,ind1,out_face,ind2,sub_2); node = cylcube->cylcube[index]; if (node == NULL) return(FALSE); /* HITOBJ(node,tmin,tmax,hitlist,ray_hit_obj); */ hit_obj(node,tmin,tmax,hitlist,&ray_hit_obj); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } Static VOID endcylcube(OBJECT *obj) { /*message("Die Prozedur wurde %d -mal aufgerufen\n",count);*/ endobj[obj->u.cylcube.original->typ](obj->u.cylcube.original); } VOID initcylcube(VOID) { nameobj[CYLCUBE] = "cylcube"; readobj[CYLCUBE] = readcylcube; copyobj[CYLCUBE] = copycylcube; writeobj[CYLCUBE] = writecylcube; boundobj[CYLCUBE] = boundcylcube; setupobj[CYLCUBE] = setupcylcube; splitobj[CYLCUBE] = split_primitiv; inside[CYLCUBE] = insidecylcube; hitobj[CYLCUBE] = hitcylcube; endobj[CYLCUBE] = endcylcube; } rde %d -mal aufgerufen\n",count);*/ endobj[obj->u.cylcube.original->Flirt/cylcube.f000644 000316 000311 00000000736 06103226604 013560 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : cylcube.f Cylcube optimisation obj DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef CYLCUBE_F #define CYLCUBE_F #include "system.d" VOID initcylcube PP((VOID)); #endif µ¯ «ö¨^ðu.cylcube.original->Flirt/cylinder.c000644 000316 000311 00000025403 06103226510 013732 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : cylinder.c cylinder manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr2.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "material.f" #include "texture.f" #include "objects.f" #include "readdata.f" #include "cylinder.f" Static OBJECT *readcylinder(VOID) { OBJECT *obj; obj = newonlyvar(OBJECT,SIMPLEOBJ); obj->typ = CYLINDER; readtransform(&(obj->u.obj.obj2world),&(obj->u.obj.world2obj)); obj->u.obj.material = readnamematerial(); obj->u.obj.texture = readnametexture(); return(obj); } #define DIS 0.414213562 /* tan(22.5 * F_PI/180.0) == sqrt(2.0) - 1.0 */ Static PNT3 hull_cylinder[16] = { { 1.0, DIS, 0.0 }, { 1.0, DIS, 1.0 }, { DIS, 1.0, 0.0 }, { DIS, 1.0, 1.0 }, { -DIS, 1.0, 0.0 }, { -DIS, 1.0, 1.0 }, { -1.0, DIS, 0.0 }, { -1.0, DIS, 1.0 }, { -1.0, -DIS, 0.0 }, { -1.0, -DIS, 1.0 }, { -DIS, -1.0, 0.0 }, { -DIS, -1.0, 1.0 }, { DIS, -1.0, 0.0 }, { DIS, -1.0, 1.0 }, { 1.0, -DIS, 0.0 }, { 1.0, -DIS, 1.0 } }; Static PNT3 midcylinder = { 0.0, 0.0, 0.5 }; Static VOID plane2point(VEC3 *normal,MAT3 *obj2world,PNT3 *point) { VEC3 vec; v3vmultransm(*normal,*obj2world,vec); v2normalize(vec); if (vec.z > 0.0) vec.z = 1.0; else vec.z = 0.0; v3pmulm(vec,*obj2world,*point); } Static VOID boundcylinder(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { PNT3 pnt; obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? TRUE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; v3pmulm(midcylinder,obj->u.obj.obj2world,obj->bsphere.center); plane2point(&V3XUNIT,&(obj->u.obj.obj2world),&pnt); obj->bbox.max.x = pnt.x; obj->bbox.min.x = 2 * obj->bsphere.center.x - pnt.x; plane2point(&V3YUNIT,&(obj->u.obj.obj2world),&pnt); obj->bbox.max.y = pnt.y; obj->bbox.min.y = 2 * obj->bsphere.center.y - pnt.y; plane2point(&V3ZUNIT,&(obj->u.obj.obj2world),&pnt); obj->bbox.max.z = pnt.z; obj->bbox.min.z = 2 * obj->bsphere.center.z - pnt.z; bounds4points(16,hull_cylinder,NULL,&(obj->bsphere),&pnt, &(obj->u.obj.obj2world)); *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static OBJECT *insidecylinder(PNT3 *pnt,OBJECT *obj) { PNT3 locpnt; INSIDE_BOUND_TEST(obj,pnt); v3pmulm(*pnt,obj->u.obj.world2obj,locpnt); if (0.0 < locpnt.z && locpnt.z < 1.0 && locpnt.x * locpnt.x + locpnt.y * locpnt.y < 1.0) return(obj); return(NULL); } /* ------------------------------------------------------------------------ */ Static BOOLEAN hitcylinder(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) /* ------------------------------------------------------------------------ calculate intersection of ray and cylinder ------------------------------------------------------------------------ */ { ULONG tminface = 0L; ULONG tmaxface = 0L; HITINFO *hit1,*hit2; FLOAT a,b,c,d,tone,ttwo; RAY3 locray; PRE_OBJECT(obj,hitlist); v3pmulm(rci.ray.origin,obj->u.obj.world2obj,locray.origin); v3vmulm(rci.ray.direction,obj->u.obj.world2obj,locray.direction); a = locray.direction.x * locray.direction.x + locray.direction.y * locray.direction.y; c = locray.origin.x * locray.origin.x + locray.origin.y * locray.origin.y - 1.0; if (f_iszero(a)) /* vertical ray ? */ { if (c >= 0.0) /* eye outside cylinder ? */ return(FALSE); } else { b = locray.origin.x * locray.direction.x + locray.origin.y * locray.direction.y; /* ----------------------- quadric equation : a t^2 + 2b t + c = 0 */ d = b * b - a * c; /* factor 2 was eliminated! */ if (d <= 0.0) /* no root ? */ return(FALSE); /* then exit */ if (b > 0.0) /* stable way to calculate */ d = - f_sqrt(d) - b; /* the roots of a quadratic */ else /* equation */ d = f_sqrt(d) - b; tone = d / a; ttwo = c / d; /* VIETA : tone * ttwo == c/a */ if (tone < ttwo) { checkaddmin(1L,tone,tminface,tmin,tmax); checkaddmax(1L,ttwo,tmaxface,tmin,tmax); } else { checkaddmin(1L,ttwo,tminface,tmin,tmax); checkaddmax(1L,tone,tmaxface,tmin,tmax); } } if (f_iszero(locray.direction.z)) /* ray parallel to z-planes ? */ { if (locray.origin.z <= 0.0 || locray.origin.z >= 1.0) return(FALSE); } else if (locray.direction.z > 0.0) { tone = - locray.origin.z / locray.direction.z; checkaddmin(2L,tone,tminface,tmin,tmax); ttwo = (1.0 - locray.origin.z) / locray.direction.z; checkaddmax(3L,ttwo,tmaxface,tmin,tmax); } else { tone = (1.0 - locray.origin.z) / locray.direction.z; checkaddmin(3L,tone,tminface,tmin,tmax); ttwo = - locray.origin.z / locray.direction.z; checkaddmax(2L,ttwo,tmaxface,tmin,tmax); } checkmakerayhit(tminface,tmin,locray,hit1); checkmakerayhit(tmaxface,tmax,locray,hit2); prepare2hits(obj,hit1,hit2,hitlist); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } Static VEC3 cylinder_normal[] = { { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, -1.0 }, { 0.0, 0.0, 1.0 } }; Static VOID normcylinder(HITINFO *hit) { VEC3 locnormal; if (hit->face == 1L) { v2addscaled(hit->ray.origin,hit->ray.direction,hit->t,locnormal); locnormal.z = 0.0; v3vmultransm(locnormal,hit->obj->u.obj.world2obj,hit->normal); } else { v3vmultransm(cylinder_normal[hit->face],hit->obj->u.obj.world2obj, hit->normal); } v3normalize(hit->normal); } Static VOID pntnormcylinder(OBJECT *obj,ULONG surface,PNT2 *point, PNT3 *world,VEC3 *normal) { PNT3 locpnt; VEC3 locnormal; if (surface == 1L) { locpnt.x = f_cos(point->x * F_2PI); locpnt.y = f_sin(point->x * F_2PI); locpnt.z = point->y; locnormal = locpnt; locnormal.z = 0.0; } else { locpnt.x = f_cos(point->x * F_2PI) * point->y; locpnt.y = f_sin(point->x * F_2PI) * point->y; if (surface == 2L) locpnt.z = -1.0; else locpnt.z = 1.0; locnormal = cylinder_normal[surface]; } v3vmulm(locpnt,obj->u.obj.obj2world,*world); v3vmultransm(locnormal,obj->u.obj.world2obj,*normal); v3normalize(*normal); } Static VOID hitcoordcylinder(HITINFO *hit,GEOMPAR needed) { if (needed & (LOCALPNT | GEOM_2DCOORD)) { v3addscaled(hit->ray.origin,hit->ray.direction,hit->t, texinfo.localpnt); texinfo.face = hit->face; if (needed & GEOM_2DCOORD) { texinfo.pnt2[0].x = (1.0 / F_2PI) * f_atan2(texinfo.localpnt.y,texinfo.localpnt.x) + 0.5; if (texinfo.face == 1L) texinfo.pnt2[0].y = texinfo.localpnt.z; else texinfo.pnt2[0].y = f_sqrt(texinfo.localpnt.x * texinfo.localpnt.x + texinfo.localpnt.y * texinfo.localpnt.y); texinfo.num2 = 1; } } } Static BOOLEAN pntcoordcylinder(OBJECT *obj,GEOMPAR needed) { FLOAT x2_y2; if (needed & (LOCALPNT | GEOM_2DCOORD)) { v3pmulm(texinfo.worldpnt,obj->u.obj.world2obj,texinfo.localpnt); if (needed & GEOM_2DCOORD) { texinfo.pnt2[0].x = (1.0 / F_2PI) * f_atan2(texinfo.localpnt.y,texinfo.localpnt.x) + 0.5; texinfo.localpnt.z -= 0.5; /* shift down ! */ x2_y2 = texinfo.localpnt.x * texinfo.localpnt.x + texinfo.localpnt.y * texinfo.localpnt.y; if (x2_y2 > texinfo.localpnt.z * texinfo.localpnt.z * 4.0) { /* out of cone ? */ texinfo.face = 1L; if (f_iszero(x2_y2)) texinfo.pnt2[0].y = 0.5; else { texinfo.pnt2[0].y = (texinfo.localpnt.z * 2.0) / f_sqrt(x2_y2); if (texinfo.localpnt.z < 0.0) texinfo.pnt2[0].y = 0.5 - texinfo.pnt2[0].y * 0.5; else texinfo.pnt2[0].y = 0.5 + texinfo.pnt2[0].y * 0.5; } } else /* upper or lower cap */ { if (f_iszero(texinfo.localpnt.z)) texinfo.pnt2[0].y = 0.0; else { if (texinfo.localpnt.z < 0.0) texinfo.face = 2L; else texinfo.face = 3L; texinfo.pnt2[0].y = f_sqrt(x2_y2) / (texinfo.localpnt.z * 2.0); } } texinfo.num2 = 1; } } return(TRUE); } VOID initcylinder(VOID) { nameobj[CYLINDER] = "cylinder"; surfaces[CYLINDER] = 3L; readobj[CYLINDER] = readcylinder; copyobj[CYLINDER] = copysobj; writeobj[CYLINDER] = writesobj; boundobj[CYLINDER] = boundcylinder; setupobj[CYLINDER] = setup_primitiv; splitobj[CYLINDER] = split_primitiv; inside[CYLINDER] = insidecylinder; hitobj[CYLINDER] = hitcylinder; normalvec[CYLINDER] = normcylinder; pntnormvec[CYLINDER] = pntnormcylinder; hitcoord[CYLINDER] = hitcoordcylinder; pntcoord[CYLINDER] = pntcoordcylinder; endobj[CYLINDER] = end_primitiv; } dobj[CYLINDER] = readcylinder; copyobj[CYLINDER] = copysobj; writeobj[CYLINDER] = writesobj; boundobj[CYLINDER] = boundcylinder; setupobj[CYLINDER] = setup_primitiv; splitobj[CYLINDER] = split_primitiv; inside[CYLINDER] = insidecFlirt/cylinder.f000644 000316 000311 00000000750 06103226604 013737 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : cylinder.f cylinder manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef CYLINDER_F #define CYLINDER_F #include "system.d" VOID initcylinder PP((VOID)); #endif n`[CYLINDER] = insidecFlirt/environm.c000644 000316 000311 00000004762 06103226510 013763 0ustar00wrzlgup000000 000000 #include "flirt.f" #include "numeric.f" #include "geometr2.f" #include "geometr3.f" #include "hitlist.f" #include "material.f" #include "texture.f" #include "objects.f" #include "color.f" #include "raytrace.f" #include "readdata.f" #include "symbols.f" #include "scene.f" #include "environm.f" ENVIRONMENT *global_enviro; UCHAR Const *nameenv[LAST_ENVIRONMENT]; VOID readenvironment(ENVIRONMENT *enviro) {/* ENVTYP typ; readconststring("typ"); typ = readnameconst(CONST_ENVIRONMENT,FALSE); if (typ == NOCONST) fatal("line %d: unknown typ of environment '%s'",linenumber,token); enviro->typ = typ; if(matchreadconststring("zenit")) { readcolor(&(enviro->zenit)); enviro->north = readreal(); } else { colorset(enviro->zenit,0.0,0.1,0.4); enviro->north = 40.0; } if(matchreadconststring("horizon")) { readcolor(&(enviro->horizon)); enviro->south = readreal(); } else { colorset(enviro->horizon,0.9,0.9,1.0); enviro->south = 30.0; } */ } ENVIRONMENT *readnameenvironment(VOID) { ENVIRONMENT *enviro; enviro = (ENVIRONMENT *)findname(INFO_ENVIRONMENT,token); if (enviro == NULL) { enviro = newonlytyp(ENVIRONMENT); savename(INFO_ENVIRONMENT,token,(VOIDPTR) enviro); } nexttoken(); return(enviro); } VOID hitenvironment(RAY3 *ray, COLOR *color) { FLOAT t, beta, north, south, range; COLOR zenit,horizon; north = 90.0 - global_enviro->north; south = 90.0 + global_enviro->south; range = south - north; zenit = global_enviro->zenit; horizon = global_enviro->horizon; beta = F_RAD2DEG * f_acos(ray->direction.z); /* INT zi; zi = (INT)beta; if(zi & 0x1) { color->r = 0.8; color->g = 0.0; color->b = 0.2; } else { color->r = 0.0; color->g = 0.3; color->b = 0.8; } */ if(beta < north) *color = zenit; else if(beta > south) *color = horizon; else { t = (beta - north) / range; color->r = interpol(zenit.r, horizon.r, t); color->g = interpol(zenit.g, horizon.g, t); color->b = interpol(zenit.b, horizon.b, t); } } VOID initenvironment() { nameenv[TWO_COLOR_SKY] = "twocolorsky"; } f(beta < northFlirt/environm.d000644 000316 000311 00000000560 06103226552 013762 0ustar00wrzlgup000000 000000 typedef enum { UNKNOWN_ENVIRONMENT, TWO_COLOR_SKY, LAST_ENVIRONMENT } ENVTYP; typedef struct { ENVTYP typ; FLOAT north; FLOAT south; COLOR zenit; COLOR horizon; } ENVIRONMENT; } }µ¯ «öinitenvironment() { nameenv[TWO_COLOR_SKY] = "twµ¯ «ö¨nx } f(beta < northFlirt/environm.f000644 000316 000311 00000000514 06103226604 013761 0ustar00wrzlgup000000 000000 #ifndef ENVIRO_F #define ENVIRO_F #include "environm.d" #include "geometr3.d" Extern ENVIRONMENT *global_enviro; Extern UCHAR Const *nameenv[]; VOID readenvironment PP((ENVIRONMENT *enviro)); ENVIRONMENT *readnameenvironment PP((VOID)); VOID hitenvironment PP((RAY3 *ray, COLOR *color)); VOID initenvironment PP((VOID)); #endif } ENVIRONMENT; } }µ¯ «öinitenvironment() { nameenv[TWO_COLOR_SKY] = "twµ¯ «ö¨rp } f(beta < northFlirt/esbuf.c000644 000316 000311 00000066533 06103226512 013240 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : esbuf.c DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 3.6.92 rb Eyebuffer-Optimization 1.7.92 rb kein lokales Eyebuffer-Koord. System mehr *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr2.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "objects.f" #include "csg.f" #include "readdata.f" #include "writdata.f" #include "camera.f" /* global_camera */ #include "light.f" /* global_light */ #include "scene.f" /* scene_eps */ #include "esbuf.f" /****************************************************************************\ * ReadEyeShadowBuffer: * * Read dimensions of eye- and shadowbuffer und create 'arrays' * \****************************************************************************/ Static OBJECT *readesbuffer(VOID) { UINT k; ULONG size; OBJECT *obj; LIGHT *light; BOOLEAN marker = FALSE; obj = newonlyvar(OBJECT,ESBUFOBJ); obj->typ = EYE_SHADOW_BUFFER; obj->u.esbuffer.eye_dim_x = 0; obj->u.esbuffer.shadow_dim_x = 0; if (matchreadconststring("eyebuffer")) { readconststring("dimension"); obj->u.esbuffer.eye_dim_x = (INT) readuint(); obj->u.esbuffer.eye_dim_y = (INT) readuint(); if ((obj->u.esbuffer.eye_dim_x <= 0) || (obj->u.esbuffer.eye_dim_y <= 0)) { message("WARNING: No Eyebuffer created!\n"); } else { marker = TRUE; obj->u.esbuffer.eye_buf = (RAYBUFFER *) newonlymem(sizeof(RAYBUFFER)); size = (ULONG)obj->u.esbuffer.eye_dim_x * (ULONG)obj->u.esbuffer.eye_dim_y * (ULONG)sizeof(RAYARRAY); obj->u.esbuffer.eye_buf->buffer = (RAYARRAY *)newonlymem(size); } } if (matchreadconststring("shadowbuffer")) { readconststring("dimension"); obj->u.esbuffer.shadow_dim_x = (INT) readuint(); obj->u.esbuffer.shadow_dim_y = (INT) readuint(); if ((obj->u.esbuffer.shadow_dim_x <= 0) || (obj->u.esbuffer.shadow_dim_y <= 0)) { message("WARNING: No Shadowbuffer created!\n"); } else { marker = TRUE; for (light = global_lights; light != NULL; light = light->next) { if (light->typ == LIGHT_AMBIENT || light->typ == LIGHT_INFINITY) continue; /* try next light */ size = (ULONG)obj->u.esbuffer.shadow_dim_x * (ULONG)obj->u.esbuffer.shadow_dim_y * (ULONG)sizeof(RAYARRAY); for (k = 0; k < 6; k++) /* fuer alle sechs Seiten */ { light->shadow_buf[k] = (RAYBUFFER *)newonlymem(sizeof(RAYBUFFER)); light->shadow_buf[k]->buffer = (RAYARRAY *)newonlymem(size); } } } } if (!marker) message("WARNING: neither eyebuffer nor shadowbuffer created!\n"); obj->u.esbuffer.original = readobjects(); return(obj); } /****************************************************************************\ * CopyEyeShadowBuffer: * * Copy an object of type EYE_SHADOW_BUFFER (copies only the eyebuffer * \****************************************************************************/ Static OBJECT *copyesbuffer(OBJECT *obj,BOOLEAN recurse,MAT3 *to,MAT3 *fr, MATERIAL *mat,TEXTURE *tex) { ULONG size; OBJECT *newobj; newobj = newonlyvar(OBJECT,ESBUFOBJ); newobj->typ = obj->typ; newobj->u.esbuffer = obj->u.esbuffer; newobj->u.esbuffer.eye_buf = (RAYBUFFER *)newonlymem(sizeof(RAYBUFFER)); *newobj->u.esbuffer.eye_buf = *obj->u.esbuffer.eye_buf; size = (ULONG)newobj->u.esbuffer.eye_dim_x * (ULONG)newobj->u.esbuffer.eye_dim_y * (ULONG)sizeof(RAYARRAY); newobj->u.esbuffer.eye_buf->buffer = (RAYARRAY *)newonlymem(size); if (recurse) newobj->u.esbuffer.original = copyobj[obj->u.esbuffer.original->typ](obj->u.esbuffer.original, TRUE,to,fr,mat,tex); else newobj->u.esbuffer.original = obj->u.esbuffer.original; return(newobj); } /****************************************************************************\ * WriteEyeShadowBuffer: * * Write values to file * \****************************************************************************/ Static VOID writeesbuffer(OBJECT *obj) { if (obj->u.esbuffer.eye_dim_x != 0) { writestring("eyebuffer"); writestring("dimension"); writeuint(obj->u.esbuffer.eye_dim_x); writeuint(obj->u.esbuffer.eye_dim_y); writelf(); } if (obj->u.esbuffer.shadow_dim_x != 0) { writestring("shadowbuffer"); writestring("dimension"); writeuint(obj->u.esbuffer.shadow_dim_x); writeuint(obj->u.esbuffer.shadow_dim_y); writelf(); } writeobjects(obj->u.esbuffer.original); } /****************************************************************************\ * BoundEyeShadowBuffer: * * Setup bounds for EYE_SHADOW_BUFFER object. * \****************************************************************************/ Static VOID boundesbuffer(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { boundobj[obj->u.esbuffer.original->typ](obj->u.esbuffer.original, bbox_test,bsphere_test,bounds_test,bbox,bsphere,bounds); obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? TRUE : FALSE; obj->bounds = (bounds_test) ? obj->u.esbuffer.original->bounds : NULL; obj->bbox = obj->u.esbuffer.original->bbox; obj->bsphere = obj->u.esbuffer.original->bsphere; *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } /* * bounding box auf den sichtbaren Bereich des Bildes projezieren, und * den Durchschnitt davon als box fuer die Zerlegung zurueckgeben. */ Static VOID clip_box(BOX3 bbox,VEC2 *screenmin, VEC2 *screenmax) { UINT i; PNT3 locpnt,pnt[8]; VEC2 boxmin,boxmax; pnt[0] = bbox.min; pnt[1] = bbox.min; pnt[1].x = bbox.max.x; pnt[2] = bbox.min; pnt[2].y = bbox.max.y; pnt[3] = bbox.min; pnt[3].z = bbox.max.z; pnt[4] = bbox.max; pnt[4].x = bbox.min.x; pnt[5] = bbox.max; pnt[5].y = bbox.min.y; pnt[6] = bbox.max; pnt[6].z = bbox.min.z; pnt[7] = bbox.max; boxmin.x = F_HUGE; boxmin.y = F_HUGE; boxmax.x = -F_HUGE; boxmax.y = -F_HUGE; for (i = 0; i < 8; i++) { v3pmulm(pnt[i],global_camera->world2cam,locpnt); if (locpnt.z < F_SMALL) { /* * fatal("eyebuffer-error: camera within bounding box!"); * return; */ } else { locpnt.x /= locpnt.z; locpnt.y /= locpnt.z; v2pmin(boxmin,locpnt,boxmin); v2pmax(boxmax,locpnt,boxmax); } } screenmin->x = -1.0; screenmin->y = -1.0; screenmax->x = 1.0; screenmax->y = 1.0; v2pmax(boxmin,*screenmin,*screenmin); v2pmin(boxmax,*screenmax,*screenmax); } /* * Ergibt das Quadrat des Cosinus des Winkels zw. 2 Vektoren * Wird von make_cone verwendet. * Formel: cos^2(alpha) = ((V.W)^2) / (|V|^2 * |W|^2) * V,W sind die Vektoren. */ Static FLOAT cosinus_2(VEC3 v, VEC3 w) { FLOAT zaehl,nenn; zaehl = v3dot(v,w); /* V.W */ zaehl = zaehl * zaehl; /* ^2 */ nenn = v3dot(v,v) * v3dot(w,w); /* |V|^2 * |W|^2 */ if (zaehl > nenn) return(0); /* 0 means an angle of 90 degree */ return (zaehl / nenn); /* (V.W)^2) / (|V|^2 * |W|^2) */ } /* * Die Funktion erzeugt einen Kegel mit Achse cone->axis, der die 4 * Vektoren kanten[4] umschliesst indem sie feststellt welcher Winkel * von den 4 Winkeln zwischen Achse und Kanten der groesste ist (der mit * kleinstem Cosinus^2), und ihn in die Struktur *cone schreibt. * Achse und Kante sind schon im Weltkkordinatensystem. */ Static VOID make_cone(RAYARRAY *cone,VEC3 *kanten) { UINT i; FLOAT cos_2,erg; /* * Die Winkel berechnen, und herausfinden, welcher der groesste ist, * naemlich der mit kleinstem Cosinus. */ erg = F_HUGE; for (i = 0; i < 4; i++) { cos_2 = cosinus_2(cone->axis.direction,kanten[i]); erg = mini(cos_2,erg); } erg = f_sqrt(erg); /* Winkel berechnen, */ cone->spread_angle = f_acos(erg); /* und eintragen. */ cone->cos_angle = erg; /* Cosinus und Tangens */ cone->tan_angle = f_tan(cone->spread_angle); /* werden noch gebraucht */ } /* * Schneiden eines Objekts mit einem Kegel, und feststellen, ob * bounding sphere innerhalb, schneidend oder ausserhalb. * (verwendet Code von cylcube.c/distance zur Berechnung von q) */ Static UINT cone_sphere_test(OBJECT *obj,VOIDPTR bound_volume) { RAYARRAY *cone; SPHERE3 sphere; VEC3 vec1; AXIS3 axis; FLOAT t,pq,yq,r; PNT3 q; /* Punkt auf Kegelachse, der am naechsten zur Kugel */ FLOAT fact1,fact2; /* Zum Halten von Zwischenergebnissen */ cone = (RAYARRAY *) bound_volume; sphere = obj->bsphere; axis = cone->axis; v3sub(sphere.center,axis.origin,vec1); t = v3dot(axis.direction,vec1); t /= v3length_2(axis.direction); v3addscaled(axis.origin,axis.direction,t,q); v3dist(sphere.center,q,pq); v3dist(axis.origin,q,yq); r = f_sqrt(sphere.radius_2); fact1 = yq * cone->tan_angle; /* vorher berechnen, damit es nicht */ fact2 = r / cone->cos_angle; /* doppelt gerechnet werden muss */ /* Es gibt 3 Moeglichkeiten, wo die Kugel im Bezug zum Kegel liegen kann, ** die verschieden gehandhabt werden muessen: */ /* 1.) Kugelmittelpunkt liegt 'auf gleicher Seite' wie Kegel */ if (t >= 0.0) { if (pq < (fact1 + fact2)) { if (pq < (fact1 - fact2)) { return(2); /* sphere inside cone */ } return(1); /* sphere intersects with cone */ } return(0); /* no intersection at all */ } /* 2.) Kugelmittelpunkt 'auf anderer' Seite. ** Kugel kann Kegel schneiden, oder ausserhalb liegen, aber nicht ** innerhalb des Kegels. ** a) Kugelmittelpunkt in 'Gegenkegel' mit Oeffnungswinkel 90-alpha. ** Dann kann die Kugel den Kegel nur schneiden, wenn sie den ** Kegelursprung einschliesst, d.h. der Radius groesser ist als ** der Abstand Kugelmittelpunkt->Kegelursprung. ** b) Kugelmittelpunkt ausserhalb des unter a) beschriebenen Kegels. ** Kugel kann Kegel auch schneiden, wenn sie Kegelursprung nicht ** einschliesst. */ else { if (pq < (yq * f_tan(F_PI_HALF - cone->spread_angle))) /* 2.a) */ { if (sphere.radius_2 >= v3length_2(vec1)) { return(1); /* Kugel und Kegel schneiden sich */ } else { return(0); /* sie schneiden sich nicht */ } } else /* 2.b) */ { if (pq < (fact1 + fact2)) { return(1); } else { return(0); } } } } /* * Macht eine Ebene die durch die drei Punkte corner, u und v gespannt wird, * darauf ein Rechteck das durch corner, u und v definiert ist. * zerlegt es in kleine Rechtecke und erzeugt die Kegel und deren Teilbaueme. * alle Punkte in Weltkkordinaten. Funktion aknn auch fuer Shadowbuffer * verwendet werden. */ Static VOID eye_shadow_setup(OBJECT *original, RAYBUFFER *side, PNT3 origin, PNT3 corner, PNT3 u, PNT3 v, UINT eye_dim_x, UINT eye_dim_y) { RAYARRAY *cone; ULONG num_objects; FLOAT u_len_2, v_len_2; VEC3 kanten[4]; FLOAT dx,dy; BOOLEAN changed; UINT j,i; v3subfrom(u,corner); /* Die Vektoren vom Eckpunkt ausgehen lassen */ v3subfrom(v,corner); /* die Ebene aufstellen: */ side->cornervec = corner; side->uvec = u; side->vvec = v; u_len_2 = v3length_2(side->uvec); v_len_2 = v3length_2(side->vvec); v3cross(side->uvec,side->vvec,side->normal); side->ndotd = v3dot(side->normal,side->cornervec); if (u_len_2 != 0.0) v3divk(side->uvec,u_len_2); if (v_len_2 != 0.0) v3divk(side->vvec,v_len_2); cone = side->buffer; /* * Da cosinus_2 davon ausgeht, das die Vektoren vom Nullpunkt ausgehen, * werden sie jetzt dahin verschoben. Und zwar reicht es corner zu * verschieben, da die anderen Ecken relativ dazu berechnet werden. */ v3subfrom(corner,origin); dx = 1.0 / eye_dim_x; dy = 1.0 / eye_dim_y; for (j = 0; j < eye_dim_y; j++) { for (i = 0; i < eye_dim_x; i++) { v3addscaled(corner,u,i*dx,kanten[0]); v3addscaled(kanten[0],v,j*dy,kanten[0]); v3addscaled(kanten[0],u,dx,kanten[1]); v3addscaled(kanten[0],v,dy,kanten[2]); v3addscaled(kanten[2],u,dx,kanten[3]); v3addscaled(kanten[0],u,dx / 2.0,cone->axis.direction); v3addscaled(cone->axis.direction,v,dy / 2.0,cone->axis.direction); cone->axis.origin = origin; make_cone(cone,kanten); changed = TRUE; cone->obj= splitobj[original->typ](original,(VOIDPTR) cone, cone_sphere_test, &changed,&num_objects); cone++; /* naechsten Kegel */ } } } /****************************************************************************\ * SetupEyeShadowBuffer: * * Create cones and subtrees. * \****************************************************************************/ Static ULONG setupesbuffer(OBJECT *obj,BOOLEAN in_or_tree,BOOLEAN space_opt) { ULONG number_of_objects; VEC2 screenmin,screenmax; PNT3 help,corner,u,v; ESBUFOBJ *esbuffer; LIGHT *light; BOOLEAN changed = FALSE; /* fuer simuliertes Split */ RAYARRAY cone; ULONG num_objects; PNT3 quadcorner[8] = {{-1.0,-1.0,-1.0},{ 1.0,-1.0,-1.0}, { 1.0, 1.0,-1.0},{-1.0, 1.0,-1.0}, {-1.0,-1.0, 1.0},{ 1.0,-1.0, 1.0}, { 1.0, 1.0, 1.0},{-1.0, 1.0, 1.0}}; esbuffer = &(obj->u.esbuffer); if (!in_or_tree && esbuffer->eye_buf != NULL) fatal("eyebuffer not in or-tree"); number_of_objects = setupobjects(obj->u.esbuffer.original,TRUE,TRUE); /* * Das Setup fuer den Eyebuffer (wenn einer vorgesehen ist) */ if (esbuffer->eye_buf != NULL) { clip_box(obj->bbox,&screenmin,&screenmax); /* am Screenrand clippen */ help.x = screenmin.x; /* 3 Eckpunkte in Weltkkordinaten umrechnen */ help.y = screenmin.y; help.z = 1; v3pmulm(help,global_camera->cam2world,corner); help.x = screenmax.x; help.y = screenmin.y; help.z = 1; v3pmulm(help,global_camera->cam2world,u); help.x = screenmin.x; help.y = screenmax.y; help.z = 1; v3pmulm(help,global_camera->cam2world,v); eye_shadow_setup(esbuffer->original,esbuffer->eye_buf, global_camera->eye,corner,u,v, esbuffer->eye_dim_x,esbuffer->eye_dim_y); } /* * Das Setup fuer die Shadowbuffer (wenn einer vorgesehen ist) */ if (esbuffer->shadow_dim_x != 0) { cone.spread_angle = 0.96; /* ca. 55 deg */ cone.cos_angle = f_cos(0.96); cone.tan_angle = f_tan(0.96); for (light = global_lights; light != NULL; light = light->next) { if (light->typ == LIGHT_AMBIENT || light->typ == LIGHT_INFINITY) continue; /* try next light */ cone.axis.origin = light->position; /* erste Seite: ( x = 1) */ cone.axis.direction = V3XUNIT; cone.obj = splitobj[esbuffer->original->typ](esbuffer->original, (VOIDPTR) &cone, cone_sphere_test, &changed, &num_objects); if (num_objects > 0) { v3add(light->position,quadcorner[1],corner); v3add(light->position,quadcorner[2],u); v3add(light->position,quadcorner[5],v); eye_shadow_setup(esbuffer->original,light->shadow_buf[0], light->position,corner,u,v, esbuffer->shadow_dim_x,esbuffer->shadow_dim_y); } /* zweite Seite: ( x = -1) */ cone.axis.direction = V3XNEGUNIT; cone.obj = splitobj[esbuffer->original->typ](esbuffer->original, (VOIDPTR) &cone, cone_sphere_test, &changed, &num_objects); if (num_objects > 0) { v3add(light->position,quadcorner[0],corner); v3add(light->position,quadcorner[3],u); v3add(light->position,quadcorner[4],v); eye_shadow_setup(esbuffer->original,light->shadow_buf[1], light->position,corner,u,v, esbuffer->shadow_dim_x,esbuffer->shadow_dim_y); } /* dritte Seite: ( y = 1) */ cone.axis.direction = V3YUNIT; cone.obj = splitobj[esbuffer->original->typ](esbuffer->original, (VOIDPTR) &cone, cone_sphere_test, &changed, &num_objects); if (num_objects > 0) { v3add(light->position,quadcorner[2],corner); v3add(light->position,quadcorner[3],u); v3add(light->position,quadcorner[6],v); eye_shadow_setup(esbuffer->original,light->shadow_buf[2], light->position,corner,u,v, esbuffer->shadow_dim_x,esbuffer->shadow_dim_y); } /* vierte Seite: ( y = -1) */ cone.axis.direction = V3YNEGUNIT; cone.obj = splitobj[esbuffer->original->typ](esbuffer->original, (VOIDPTR) &cone, cone_sphere_test, &changed, &num_objects); if (num_objects > 0) { v3add(light->position,quadcorner[1],corner); v3add(light->position,quadcorner[0],u); v3add(light->position,quadcorner[5],v); eye_shadow_setup(esbuffer->original,light->shadow_buf[3], light->position,corner,u,v, esbuffer->shadow_dim_x,esbuffer->shadow_dim_y); } /* fuenfte Seite: ( z = 1) */ cone.axis.direction = V3ZUNIT; cone.obj = splitobj[esbuffer->original->typ](esbuffer->original, (VOIDPTR) &cone, cone_sphere_test, &changed, &num_objects); if (num_objects > 0) { v3add(light->position,quadcorner[5],corner); v3add(light->position,quadcorner[4],u); v3add(light->position,quadcorner[6],v); eye_shadow_setup(esbuffer->original,light->shadow_buf[4], light->position,corner,u,v, esbuffer->shadow_dim_x,esbuffer->shadow_dim_y); } /* sechste Seite: ( z = -1) */ cone.axis.direction = V3ZNEGUNIT; cone.obj = splitobj[esbuffer->original->typ](esbuffer->original, (VOIDPTR) &cone, cone_sphere_test, &changed, &num_objects); if (num_objects > 0) { v3add(light->position,quadcorner[1],corner); v3add(light->position,quadcorner[0],u); v3add(light->position,quadcorner[2],v); eye_shadow_setup(esbuffer->original,light->shadow_buf[5], light->position,corner,u,v, esbuffer->shadow_dim_x,esbuffer->shadow_dim_y); } } } return(number_of_objects); } /****************************************************************************\ * InsideEyeShadowBuffer: * * Check if 'point inside buffer'. * \****************************************************************************/ Static OBJECT *insideesbuffer(PNT3 *pnt, OBJECT *obj) { INSIDE_BOUND_TEST(obj,pnt); /* FIXME: could be improved */ return(inside[obj->u.esbuffer.original->typ](pnt, obj->u.esbuffer.original)); } /****************************************************************************\ * HitEyeShadowBuffer: * * Does ray hit something in our object? * \****************************************************************************/ Static BOOLEAN hitesbuffer(FLOAT tmin,FLOAT tmax,OBJECT *obj, HITLIST *hitlist) { BOOLEAN ray_hit_obj; UINT ndx,i,j; /* Index, Zeilenindex, Spaltenindex */ VEC3 hitray; PNT3 hitpnt; /* Punkt wo Strahl die Flaeche trifft (falls) */ UINT side; FLOAT abs_x,abs_y,abs_z; FLOAT dot_dir,dot_origin,t,u,v; RAYBUFFER *buffer; if (rci.primary && obj->u.esbuffer.eye_buf != NULL) { PRE_OBJECT(obj,hitlist); buffer = obj->u.esbuffer.eye_buf; dot_origin = v3dot(buffer->normal,rci.ray.origin); dot_dir = v3dot(buffer->normal,rci.ray.direction); if (dot_dir == 0.0) return(FALSE); t = (buffer->ndotd - dot_origin) / dot_dir; if (t < 0.0) return(FALSE); /* weil Strahl und keine Gerade! */ v3addscaled(rci.ray.origin,rci.ray.direction,t,hitpnt); v3sub(hitpnt,buffer->cornervec,hitray); u = v3dot(hitray,buffer->uvec); v = v3dot(hitray,buffer->vvec); if (u < 0.0 || u >= 1.0 || v < 0.0 || v >= 1.0) return (FALSE); i = (UINT) (u * obj->u.esbuffer.eye_dim_x); j = (UINT) (v * obj->u.esbuffer.eye_dim_y); ndx = j * obj->u.esbuffer.eye_dim_y + i; if (buffer->buffer[ndx].obj == NULL) return (FALSE); HITOBJ(buffer->buffer[ndx].obj,tmin,tmax,hitlist,ray_hit_obj); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } if (rci.shadow && rci.shadow_light->shadow_buf[0] != NULL) { PRE_OBJECT(obj,hitlist); /* Strahl umdrehen */ /* anstatt den Strahl umzudrehen, geht man einfach beim bestimmen * der Seite, davon aus, das die Komponenten eigentlich alle mit * -1 multipliziert sein sollten. */ /* feststellen, welche Ebene */ abs_x = f_abs(rci.ray.direction.x); abs_y = f_abs(rci.ray.direction.y); abs_z = f_abs(rci.ray.direction.z); if (abs_x >= abs_y && abs_x >= abs_z) { if (rci.ray.direction.x < 0.0) side = 0; else side = 1; } else if (abs_y >= abs_x && abs_y >= abs_z) { if (rci.ray.direction.y < 0.0) side = 2; else side = 3; } else { if (rci.ray.direction.z < 0.0) side = 4; else side = 5; } buffer = rci.shadow_light->shadow_buf[side]; /* Schnitt berechnen */ PRE_OBJECT(obj,hitlist); dot_origin = v3dot(buffer->normal,rci.ray.origin); dot_dir = v3dot(buffer->normal,rci.ray.direction); /* kann hier nicht passieren if (dot_dir == 0.0) return(FALSE); */ t = (buffer->ndotd - dot_origin) / dot_dir; /* if (t < 0.0) return(FALSE); */ v3addscaled(rci.ray.origin,rci.ray.direction,t,hitpnt); v3sub(hitpnt,buffer->cornervec,hitray); u = v3dot(hitray,buffer->uvec); v = v3dot(hitray,buffer->vvec); i = (UINT) (u * obj->u.esbuffer.shadow_dim_x); j = (UINT) (v * obj->u.esbuffer.shadow_dim_y); ndx = j * obj->u.esbuffer.shadow_dim_y + i; if (buffer->buffer[ndx].obj == NULL) return(FALSE); HITOBJ(buffer->buffer[ndx].obj,tmin,tmax,hitlist,ray_hit_obj); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } /* hierher kommt man nur, wenn's keine Optimierung fuer den Strahl gibt */ HITOBJ(obj->u.esbuffer.original,tmin,tmax,hitlist,ray_hit_obj); returnhitlist(hitlist); } /****************************************************************************\ * EndEyeShadowBuffer: * * endobj fuer das Originalobjekt aufrufen. * \****************************************************************************/ Static VOID endesbuffer(OBJECT *obj) { endobj[obj->u.esbuffer.original->typ](obj->u.esbuffer.original); } /****************************************************************************\ * InitEyeShadowBuffer: * * Funktionenarray initialisieren. * \****************************************************************************/ VOID initesbuffer(VOID) { nameobj[EYE_SHADOW_BUFFER] = "eye_shadow_buffer"; readobj[EYE_SHADOW_BUFFER] = readesbuffer; copyobj[EYE_SHADOW_BUFFER] = copyesbuffer; writeobj[EYE_SHADOW_BUFFER] = writeesbuffer; boundobj[EYE_SHADOW_BUFFER] = boundesbuffer; setupobj[EYE_SHADOW_BUFFER] = setupesbuffer; splitobj[EYE_SHADOW_BUFFER] = split_primitiv; inside[EYE_SHADOW_BUFFER] = insideesbuffer; hitobj[EYE_SHADOW_BUFFER] = hitesbuffer; endobj[EYE_SHADOW_BUFFER] = endesbuffer; } tesbuffer(VOID) { nameobj[EYE_SHADOW_BUFFER] = "eye_shadow_buffer"; readobj[EYE_SHADOW_BUFFER] = readesbuffer; copyobj[EYE_SHADOW_BUFFER] = copyesbufFlirt/esbuf.d000644 000316 000311 00000001406 06103226554 013233 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : eyebuf.d Eye/Shadow-buffer DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef EYEBUF_D #define EYEBUF_D #include "geometr3.d" #include "flirt.d" typedef struct rayarray { AXIS3 axis; FLOAT spread_angle; FLOAT cos_angle; FLOAT tan_angle; struct object *obj; } RAYARRAY; typedef struct raybuffer { RAYARRAY *buffer; VEC3 uvec; VEC3 vvec; VEC3 cornervec; VEC3 normal; FLOAT ndotd; } RAYBUFFER; #endif 010391 wrzl,rft first version *****************************************************************************/ #ifndef EYEBUF_D #define EYEBUF_D #include "geometr3.d" #include "flirt.d" typedef struct rayarray { AXIS3 axis; FLOAT spreaFlirt/esbuf.f000644 000316 000311 00000000736 06103226606 013240 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : eyebuf.f Eyebuffer optimisation obj DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010692 rbrandner first version *****************************************************************************/ #ifndef EYEBUF_F #define EYEBUF_F #include "system.d" VOID initesbuffer PP((VOID)); #endif {µ¯ «ö¨txis; FLOAT spreaFlirt/f000755 000316 000311 00000000165 06114643012 012130 0ustar00wrzlgup000000 000000 echo flirt Ftl/$1.ftl $1.ppm -i Ftl/ $2 $3 $4 $5 $6 $7 $8 $9 flirt Ftl/$1.ftl $1.ppm -i Ftl/ $2 $3 $4 $5 $6 $7 $8 $9 eyebuf.f Eyebuffer optimisation obj DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010692 rbrandner first version *****************************************************************************/ µ¯ «ïøHUF_F #define EYEBUF_µ¯ «öž "system.d" VOIDHtesbuffer PP((VOID)); #endif {µ¯ «ö¨t¨xis; FLOAT spreaFlirt/fived.c000644 000316 000311 00000045516 06103226512 013227 0ustar00wrzlgup000000 000000 /******************************************************************* PROJECT : flirt MODULE : fived.c fived manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 150793 rweber first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "objects.f" #include "csg.f" #include "readdata.f" #include "writdata.f" #include "scene.f" /* scene_eps */ #include "fived.f" /* Globale Varibalen */ Static UINT dominant; /* Dominante Achse des Strahls */ Static UINT count = 0; /* Aufrufe der Hitfunktion */ Static ULONG size_fivednode; /* Groesse des 5D-Knotens */ Static UINT count_machkegel; /* Aufrufe von mach_kegel */ Static UINT count_kegeltest; /* Aufrufe von Kegeltest */ #ifdef NOT_NOW /*-----Debuggingroutinen*/ Static VOID box5aus(BOX5 *b) { message("--------------\n"); message(" x y z u v\n"); message("min: %f %f %f %f %f\n",b->min[0],b->min[1],b->min[2], b->min[3],b->min[4]); message("max: %f %f %f %f %f\n",b->max[0],b->max[1],b->max[2], b->max[3],b->max[4]); } #endif /* Lesen des Objekts vom File */ Static OBJECT *readfived(VOID) { OBJECT *obj; UINT i; obj = newonlyvar(OBJECT,FIVEDOBJ); obj->typ = FIVED_TREE; readconststring("maximumlevel"); obj->u.fived.max_level = (INT) readuint(); readconststring("maximumpronode"); obj->u.fived.max_num_pro_node = (INT) readuint(); option_read_bool("optimisation", obj->u.fived.optimize,FALSE); obj->u.fived.original = readobjects(); for (i=0; i<6; i++) obj->u.fived.wurzel[i]=NULL; return(obj); } /* Kopieren des Objekts */ Static OBJECT *copyfived(OBJECT *obj,BOOLEAN recurse,MAT3 *to,MAT3 *fr, MATERIAL *mat,TEXTURE *tex) { OBJECT *newobj; UINT i; newobj = newonlyvar(OBJECT,FIVEDOBJ); newobj->typ = obj->typ; newobj->u.fived = obj->u.fived; for (i=0; i<6; i++) newobj->u.fived.wurzel[i]=NULL; if (recurse) newobj->u.fived.original = copyobj[obj->u.fived.original->typ](obj->u.fived.original,TRUE, to,fr,mat,tex); else newobj->u.fived.original = obj->u.fived.original; return(newobj); } Static VOID writefived(OBJECT *obj) { writestring("maximumlevel"); writeuint(obj->u.fived.max_level); writestring("maximumpronode"); writeuint(obj->u.fived.max_num_pro_node); writelf(); write_string_bool("optimisation",obj->u.fived.optimize); writeobjects(obj->u.fived.original); } Static VOID boundfived(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { boundobj[obj->u.fived.original->typ](obj->u.fived.original,bbox_test, bsphere_test,bounds_test,bbox,bsphere,bounds); obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_ALL; obj->test_bsphere = (bsphere_test) ? FALSE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; obj->bbox = obj->u.fived.original->bbox; obj->bsphere = obj->u.fived.original->bsphere; *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } /* ---------------------------------------------------------------- */ /* Makro zur Initialisierung des Hypercubes */ #define init_hypcube(a,b,c) \ { \ a[0] = b.x; \ a[1] = b.y; \ a[2] = b.z; \ a[3] = c; \ a[4] = c; \ } /* ---------------------------------------------------------------- */ /* Setup-Prozedur initialisiert den 5D-Tree */ Static ULONG setupfived(OBJECT *obj,BOOLEAN in_or_tree,BOOLEAN space_opt) { UINT i; /* Schleife */ ULONG number_of_objects; /* Anzahl der Objekte */ FIVEDNODE *root; /* Wurzel des 5D-Trees */ FIVEDOBJ *fived; /* 5D-Objekt */ BOX5 hypcube; /* Hypercube */ if (! in_or_tree) fatal("fived not in or-tree"); number_of_objects = setupobjects(obj->u.fived.original,TRUE,TRUE); size_fivednode = (ULONG) sizeof(FIVEDNODE); fived = &(obj->u.fived); /* Zeiger auf Fivedobj */ /* Hypercube ist zu Beginn fuer alle 6 Teilbaeume gleich */ init_hypcube(hypcube.max,obj->bbox.max,1); init_hypcube(hypcube.min,obj->bbox.min,-1); /* restliche Initialisierungen der 6 Teilbaeume, die die 6 dominanten Halb-Achsen repraesentieren: Werte von 'dominant' fuer die entsprechenden Halb-Achsen 0 x+ 2 y+ 4 z+ 1 x- 3 y- 5 y- */ for (i=0; i<6; i++) { fived->wurzel[i] = (FIVEDNODE *)newonlymem(size_fivednode); root = fived->wurzel[i]; root->high = NULL; /* Weiterzeiger leer */ root->low = NULL; root->objects = fived->original; /* ganze Objektliste */ root->anzahl = number_of_objects; /* Anzahl vermerken */ root->hypcube = hypcube; /* Hypercube uebernehmen */ } return(number_of_objects); } Static OBJECT *insidefived(PNT3 *pnt,OBJECT *obj) { INSIDE_BOUND_TEST(obj,pnt); return(inside[obj->u.fived.original->typ](pnt,obj->u.fived.original)); } /* ---------------------------------------------------------------- */ /* Makros zur Erstellung des Kegels, der den durch einen Hypercube definierten Beam einschliesst */ #define machbox3(b,p) \ { \ p.x = b[0]; \ p.y = b[1]; \ p.z = b[2]; \ } #define f(a,b,c,vec) \ { \ vec.x = a; \ vec.y = b; \ vec.z = c; \ } #define init_vec(u,v,vc) \ switch (dominant) \ { \ case 0: f( 1, u, v,vc); break; \ case 1: f(-1, u, v,vc); break; \ case 2: f( u, 1, v,vc); break; \ case 3: f( u,-1, v,vc); break; \ case 4: f( u, v, 1,vc); break; \ case 5: f( u, v,-1,vc); break; \ default:break; \ } /* berechnet Cosinus des Winkels zw. Vec a u.b */ #define cosinus(a,b) abso(v3dot(a,b))/(v3length(a)*v3length(b)) Static VOID mach_kegel(BOX5 *hypcube, FIVEDCONE *kegel) { PNT3 spitze; /* Spitze des Kegels */ VEC3 achse; /* Achsenvektor des Kegels */ PNT3 boxmin,boxmax; /* x,y,z-Anteil des Hypercubes (bbox) */ FLOAT durchmesser; /* Dm. der Bbox des hypcubes (ohne u,v) */ FLOAT umin,umax,vmin,vmax; /* u,v-Anteil des Hypercubes */ VEC3 a,b,c,d; /* Vektoren zu u,v-Intervall-Ecken */ count_machkegel++; machbox3(hypcube->min,boxmin); /* x,y,z-min extrahieren */ machbox3(hypcube->max,boxmax); /* x,y,z-max extrahieren */ umin = hypcube->min[3]; /* u,v-min/max extrahieren */ umax = hypcube->max[3]; vmin = hypcube->min[4]; vmax = hypcube->max[4]; init_vec(umin,vmax,a); /* Vektoren initialisieren */ init_vec(umax,vmin,b); /* diese begrenzen den Beam */ init_vec(umin,vmin,c); init_vec(umax,vmax,d); achse.x = (a.x+b.x)/2; /* Achsenvektor des Kegels */ achse.y = (a.y+b.y)/2; achse.z = (a.z+b.z)/2; v3normalize(achse); /* Einheitsvektor */ kegel->achse = achse; /* Cosinus des Oeffnungswinkels des Kegels */ kegel->winkel_cos = mini( mini(cosinus(a,achse), cosinus(b,achse)), mini(cosinus(c,achse), cosinus(d,achse))); /* Sinus des Oeffnungswinkels */ kegel->winkel_sin = f_sqrt(1-(kegel->winkel_cos)*(kegel->winkel_cos)); v3interpol(boxmin,boxmax,0.5,spitze); /* Mittelpunkt der bbox */ v3dist(boxmin,boxmax,durchmesser); /* Durchm. der bbox */ /* Die naechste Anweisung verschiebt die Spitze, die momentan im Mittelpunkt der Bbox zusammenfaellt, entlang der Achse, bis der durch den Oeffnungswinkel gegebene Kegel den durch den Hypercube definierten Beam vollstaendig einschliesst. */ v3addscaled(spitze,achse,durchmesser/(-2*kegel->winkel_sin), kegel->spitze); } /* end machkegel */ /* Kegel-Kugel-Test Dieser Test untersucht, ob die Kugelumgebung eines Objekts innerhalb oder ausserhalb eines Kegels liegt, oder ihn schneidet */ Static UINT bsphere_cone_test(OBJECT *obj,VOIDPTR bound_volume) { FIVEDCONE *kegel; /* Kegel */ PNT3 spitze; /* Spitze des Kegels */ VEC3 achse; /* Achsenvektor des Kegels */ PNT3 mittel; /* Mittelpunkt d. Bound.Sphere */ FLOAT radius; /* Radius d. Bd.Sph. */ VEC3 sm; /* Vektor Spitze-Mittel */ FLOAT sq; /* Normalabstand Mittelp.-Normalebene */ FLOAT distanz; /* Normalabstand Mittelp.-Kegelachse */ FLOAT kegdist; /* Kegel-Teilstueck v. distanz */ FLOAT kugdist; /* Kugel-Teilstueck v. distanz */ FLOAT lage; /* Lage von mittel bezuegl Norm.ebene */ count_kegeltest++; /* Initialisierungen */ kegel = (FIVEDCONE *) bound_volume; /* Kegel uebernehmen */ achse = kegel->achse; spitze = kegel->spitze; mittel = obj->bsphere.center; radius = f_sqrt(obj->bsphere.radius_2); v3sub(mittel,spitze,sm); /* Vec Spitze->Mittelp. */ lage = v3dot(achse,sm); sq = abso(lage)/v3length(achse); /* Normalabstand Kugelmittelpunkt-Kegelachse */ distanz = f_sqrt(v3length_2(sm) - sq*sq); /* Sei Q der Punkt der Achse mit dem kuerzesten Abstand zum Kugelmittelpunkt ( = Normalabstand), dann ist kegdist = Abstand(Spitze-Q) * tangens(Oeffnungswinkel) kugdist = Radius / cos(Oeffn.Winkel) */ kegdist = (kegel->winkel_sin / kegel->winkel_cos) * sq; kugdist = radius / kegel->winkel_cos; /* Tests (1) ist distanz > kegdist+kugdist --> ausserhalb ok (2) ist distanz < kegdist-kugdist --> innerhalb kann aber auch im 'hinteren' Teil des Doppelkegels liegen, dieser Fall muss ausgeschlossen werden: Test mit Normalebene zur Achse durch Spitze, liegt Mittelpunkt im positiven Bereich, dann ist die Kugel innerhalb, sonst ausserhalb (3) weder (1) noch (2): Kegel schneidet Kugel Normalebenentest wie bei (2): Mittelpunkt im positiven Halbraum --> schneidet im negativen: schneidet nur dann, wenn der Abstand Mittelpunkt-Kegelspitze < Radius */ if (distanz > kegdist+kugdist) return(0); /* Kugel ausserhalb */ else { /* in welchem Halbraum der Normalebene liegt der Mittelpunkt ? */ if (distanz <= kegdist-kugdist) /* innerhalb */ { if (lage >= 0) return(2); /* Kugel innerhalb */ else return(0); /* im 'Negativkegel' */ } else { if (lage >= 0) return(1); /* schneidet */ else { if (v3length_2(sm) <= obj->bsphere.radius_2) return(1); /* Kegelspitze innerhalb der Kugel */ else return(0); /* Schneidet nur mit 'Negativkegel */ } } } } /* ------------------------------------------------------------------------ */ Static BOOLEAN hitfived(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) /* --------------------------------------------------------------------------- calculate intersection with fived --------------------------------------------------------------------------- */ { HITLIST lochitlist; /* lokale Hitliste */ BOOLEAN ray_hit_obj; /* Objekt getroffen? */ FIVEDNODE *knoten; /* Teilknoten */ PNT3 begin; /* Strahlbeginn in bbox */ VEC3 richtung; /* Richtungsvektor des Strahls */ FLOAT kompmax; /* Maximale Komponente der Richtung */ FLOAT x,y,z; /* Strahlrichtungskomponenten */ PNT5 strahl; /* Strahl als 5D-Punkt */ UINT level; /* aktuelle Baumebene */ UINT trenn; /* Index - aktuelle Trennebene */ FLOAT mittelteil; /* Wert - aktuelle Trennebene */ BOX5 hypcube; /* aktueller Hypercube */ FIVEDCONE kegel; /* Kegel fuer boundingtest in split */ BOOLEAN changed; /* fuer split */ ULONG num_obj; /* anzahl der objekte */ PRE_OBJECT(obj,hitlist); if (obj->u.fived.optimize) rci.save_hitlist++; /* Ermittlung des Eintrittspunktes */ /* Initialisierungen */ /* Anfangspunkt des Strahls im 5D-Tree */ if (insidebbox(&(rci.ray.origin),&(obj->bbox))) { begin = rci.ray.origin; } else { richtung = rci.ray.direction; v3normalize(richtung); v3addscaled(rci.ray.origin,richtung,tmin,begin); } /* Ortskomponenten des 5D-Strahls initialisieren */ strahl[0] = begin.x; strahl[1] = begin.y; strahl[2] = begin.z; /* Richtungskomponenten des 5D-Strahls initialisieren und dominante Achse ermitteln */ x = rci.ray.direction.x; y = rci.ray.direction.y; z = rci.ray.direction.z; /* Das Maximum der Betraege der Komponenten des Richtungs- vektors des Rays definiert die dominante Achse */ kompmax = maxi(maxi(abso(x),abso(y)),abso(z)); if (abso(x) == kompmax) /* x-Achse dominant */ { dominant = (x>0) ? 0 : 1; /* pos od. neg. x-Achse */ strahl[3] = y/kompmax; /* u,v initialisieren */ strahl[4] = z/kompmax; } else { if (abso(y) == kompmax) /* y-Achse */ { dominant = (y>0) ? 2 : 3; strahl[3] = x/kompmax; strahl[4] = z/kompmax; } else /* z-Achse */ { dominant = (z>0) ? 4 : 5; strahl[3] = x/kompmax; strahl[4] = y/kompmax; } } /* subdivision tree hinuntergehen */ hypcube = obj->u.fived.wurzel[dominant]->hypcube; level = 0; /* oberste Baumebene */ trenn = 0; /* Hypercubes werden zyklisch bezueglich aller 5 Komponenten unterteilt */ knoten = obj->u.fived.wurzel[dominant]; /* aktueller Baumknoten */ while (knoten->high != NULL) /* binaeres Suchen */ { if (strahl[trenn] < (hypcube.max[trenn]+hypcube.min[trenn])/2) knoten = knoten->low; else knoten = knoten->high; hypcube = knoten->hypcube; /* naechster hypcube */ level++; /* naechste Baumebene */ trenn = (trenn+1) % 5; /* naechste Trennkomponente */ } /* Baum ausbauen, wenn noetig und moeglich */ while ((level <= obj->u.fived.max_level) && (knoten->anzahl > obj->u.fived.max_num_pro_node)) { mittelteil = (hypcube.max[trenn]+hypcube.min[trenn])/2; knoten->low = (FIVEDNODE *)newonlymem(size_fivednode); knoten->low->low = NULL; knoten->low->high = NULL; knoten->low->hypcube = hypcube; knoten->low->hypcube.max[trenn] = mittelteil; knoten->high = (FIVEDNODE *)newonlymem(size_fivednode); knoten->high->low = NULL; knoten->high->high = NULL; knoten->high->hypcube = hypcube; knoten->high->hypcube.min[trenn] = mittelteil; /* nur nach jeder 5. Unterteilung werden die Objektklassifizierungen aktualisiert */ if (trenn == 4) { changed = TRUE; mach_kegel(&(knoten->low->hypcube), &kegel); knoten->low->objects = splitobj[knoten->objects->typ]( knoten->objects, (VOIDPTR) &kegel, bsphere_cone_test, &changed,&num_obj); knoten->low->anzahl = num_obj; if (num_obj == 0) knoten->low->objects = NULL; changed = TRUE; mach_kegel(&(knoten->high->hypcube), &kegel); knoten->high->objects = splitobj[knoten->objects->typ]( knoten->objects, (VOIDPTR) &kegel, bsphere_cone_test, &changed,&num_obj); knoten->high->anzahl = num_obj; if (num_obj == 0) knoten->high->objects = NULL; } /* bei den anderen Unterteilungen werden die Werte des darueberliegenden Knotens vererbt */ else { knoten->low->objects = knoten->objects; knoten->high->objects = knoten->objects; knoten->low->anzahl = knoten->anzahl; knoten->high->anzahl = knoten->anzahl; } /* weiter den Binaer-Tree hinuntergehen */ if (strahl[trenn] < mittelteil) knoten = knoten->low; else knoten = knoten->high; hypcube = knoten->hypcube; /* naechster hypcube */ level++; trenn = (trenn+1) % 5; } /* end while */ /* Hitprozedur aufrufen */ if (knoten->objects != NULL) { lochitlist = emptyhitlist; HITOBJ(knoten->objects,tmin,tmax,&lochitlist,ray_hit_obj); count++; if (ray_hit_obj) { /* hit? */ if (! rci.shadow ) *hitlist = lochitlist; else { if (hitlist->first != NULL) { hitlist->last->next = lochitlist.first; hitlist->last = lochitlist.last; } else *hitlist = lochitlist; } /* end else */ } /* end if (ray_hit_obj) */ } /* end if (node->objects != NULL) */ if (obj->u.fived.optimize) rci.save_hitlist--; POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } Static VOID endfived(OBJECT *obj) { message("Die Prozedur wurde %d -mal aufgerufen\n",count); message("mach_kegel wurde %d -mal aufgerufen\n",count_machkegel); message("kegel_test wurde %d -mal aufgerufen\n",count_kegeltest); endobj[obj->u.fived.original->typ](obj->u.fived.original); } VOID initfived(VOID) { nameobj[FIVED_TREE] = "fived"; readobj[FIVED_TREE] = readfived; copyobj[FIVED_TREE] = copyfived; writeobj[FIVED_TREE] = writefived; boundobj[FIVED_TREE] = boundfived; setupobj[FIVED_TREE] = setupfived; splitobj[FIVED_TREE] = split_primitiv; inside[FIVED_TREE] = insidefived; hitobj[FIVED_TREE] = hitfived; endobj[FIVED_TREE] = endfived; } ufgerufen\n",count_kegeltest); endobj[obj->u.fived.original->typ](obj->u.fived.original); } VOID initfived(VOID) { nameobj[FIVED_TREE] = "fived"; readobj[FIFlirt/fived.d000644 000316 000311 00000002343 06103226554 013225 0ustar00wrzlgup000000 000000 /******************************************************************* PROJECT : flirt MODULE : fived.d fived definitions DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010793 rweber first version *****************************************************************************/ #ifndef FIVED_D #define FIVED_D #include "geometr3.d" #include "flirt.d" #include "system.d" typedef float PNT5[5]; /* 5D-Punkt */ typedef struct box5 { PNT5 max, min; } BOX5; /* 5D-Box */ typedef struct fivedcone /* Kegel fuer Kegel-Kugel-Schnitt */ { PNT3 spitze; /* Kegelspitze */ VEC3 achse; /* Richtungsvektor der Achse */ FLOAT winkel_cos; /* Cosinus des Oeffnungswinkels */ FLOAT winkel_sin; /* Sinus des Oeffnungswinkels */ } FIVEDCONE; typedef struct fivednode /* Knoten im 5D-Baum */ { BOX5 hypcube; /* Hyper-Cube */ UINT anzahl; /* Anzahl der Objekte */ struct fivednode *high, *low; /* Nachfolgerknoten */ struct object *objects; /* Objekte innerhalb dieses Knotens */ } FIVEDNODE; #endif vektor der Achse */ FLOAT winkel_cos; /* Cosinus des Oeffnungswinkels */ FLOAT winkel_sin; /* Sinus des Oeffnungswinkels */ } FIVEDCONE; typedef struct fivednode /* Knoten im 5D-Baum */ { BOX5 hypcube; /* Hyper-Cube */Flirt/fived.f000644 000316 000311 00000000731 06103226606 013224 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : fived.f fived manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010693 rweber first version *****************************************************************************/ #ifndef FIVED_F #define FIVED_F #include "system.d" VOID initfived PP((VOID)); #endif µ¯ «ö¨t /* Hyper-Cube */Flirt/fived_p.d000644 000316 000311 00000002515 06103226554 013545 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : fived_p.d ray classification by five dimensional space subdivision DATE AUTHOR DESCRIPTION ------ -------------- ------------------------------------------------ 290493 Franz Kriftner first version *****************************************************************************/ #ifndef FIVED_PRIV_D #define FIVED_PRIV_D #include "fived.d" /* a ray is represented by its origin (normal 3D) and its direction (2 dimensions named u and v): put a cube [origin.x - 1, origin.x + 1] [origin.y - 1, origin.y + 1] [origin.z - 1, origin.z + 1] around the ray origin find out which face the ray intersects => dominant axis u and v are measured from this face's middlepoint to the intersection u and v can be in [-1, 1] */ const char *axis_name[] = { "+x", "+y", "+z", "-x", "-y", "-z" } ; const char *coord_name[] = { "X", "Y", "Z", "U", "V" } ; typedef struct { AXIS3 axis; FLOAT spread_angle; FLOAT cos_angle; FLOAT tan_angle; } BOUNDING_CONE; #define write_string_ulong(s,v) { writestring(s); writeulong(v); writelf(); } #endif /* #ifndef FIVED_PRIV_D */ face's middlepoint to the intersection u and v can be in [-1, 1] */ const char *axis_name[] = { "+x", "+y", "+z", "-x", "-y", "-z" } ; coFlirt/flirt.c000644 000316 000311 00000023761 06103226512 013250 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : flirt.c Main program DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include #define STRING_H #include "numeric.f" #include "setup.f" #include "sampling.f" #include "scene.f" #include "init.f" #include "readdata.f" #include "writdata.f" #include "flirt.f" BOOLEAN verbose = FALSE; UINT obj_id = SYSTEM; /* memory id for obj tree */ Static MATERIALTYP materialtyp = STANDARDMATERIALS; Static UCHAR *logfilename = NULL; Static UCHAR *includepath = NULL; Static VOID parse_args PP((WORD argc,UCHAR *argv[],BOOLEAN override)); Static VOID secs2hmsm PP((DOUBLE s,UINT *hours,UINT *mins,UINT *secs, UINT *msec)); WORD main(WORD argc,UCHAR *argv[]) { TIME starttime; TIME endtime; ULONG startticks; DOUBLE cpusecs; DOUBLE totalsecs; UINT hours,mins,secs,msec; screen_message("%s - %s - Version %s\n", SHORTSTRING,NAMESTRING,VERSIONSTRING); screen_message("(c) 1991 by W.Stuerzlinger and R.F.Tobler\n"); if (argc < 3) { screen_message("\nUSAGE:\t%s\t \n", SMALLSHORTSTRING); screen_message("\t\t[-i ] /* path for #include */\n"); screen_message("\t\t[-v] /* verbose mode */\n"); screen_message("\t\t[-l ] /* logfile */\n"); screen_message("\t\t[-m simple] /* Simple Materials */\n"); screen_message("\t\t[-m riss] /* RISS Materials */\n"); screen_message("\t\t[-r [x]] /* Aufloesung */\n"); screen_message("\t\t[-x {}"); screen_message("|{-}|{-}|{-}]\n"); screen_message("\t\t[-y {}"); screen_message("|{-}|{-}|{-}]\n"); return(255); } parse_args(argc,argv,FALSE); /* get important args: */ /* logfilename, materialtyp */ init_system(logfilename,verbose); obj_id = getallocid(0); /* memory id for obj tree */ log_message("%s %s (c) by W.Stuerzlinger and R.F.Tobler\n", SHORTSTRING,VERSIONSTRING); clocktime(&starttime); startticks = clockticks(); initmodules(materialtyp); readdata(argv[1],includepath,materialtyp); if (logfilename != NULL) writedata(NULL); parse_args(argc,argv,TRUE); cpusecs = ticks2secs(startticks,clockticks()); cpusecs += setup(); cpusecs += sampling(argv[2]); /* the name of the output file */ startticks = clockticks(); endmodules(); cpusecs += ticks2secs(startticks,clockticks()); clocktime(&endtime); secs2hmsm(cpusecs,&hours,&mins,&secs,&msec); message("\nNET CPU TIME: %4d:%02d:%02d.%03d\n", hours,mins,secs,msec); totalsecs = time2secs(starttime,endtime); secs2hmsm(totalsecs,&hours,&mins,&secs,&msec); message("TOTAL EXECUTION TIME: %4d:%02d:%02d.%03d\n", hours,mins,secs,msec); end_system(); #ifdef VAX return(1); #else return(0); #endif } Static VOID secs2hmsm(DOUBLE s,UINT *hours,UINT *mins,UINT *secs,UINT *msec) { *hours = (UINT)(s / 3600.0); *mins = (UINT)d_mod(s / 60.0,60.0); *secs = (UINT)d_mod(s,60.0); *msec = (UINT)d_mod(s * 1000.0,1000.0); } Static VOID parse_args(WORD argc,UCHAR *argv[],BOOLEAN override) { UCHAR c; INT i; UINT val; UCHAR *x; logfilename = NULL; /* first arg to process */ for (i = 3; i < argc; i++) { if (argv[i][0] != '-' || argv[i][1] == '\0') fatal("illegal argument '%s'",argv[i]); c = argv[i][1]; if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; switch (c) { case 'i': i++; if (i >= argc) fatal("option '-i' with no argument"); if (override) continue; includepath = argv[i]; break; case 'v': verbose = TRUE; break; case 'l': i++; if (i >= argc) fatal("option '-l' with no argument"); if (override) continue; logfilename = argv[i]; break; case 'm': i++; if (i >= argc) fatal("option '-m' with no argument"); if (override) continue; if (strcmp("standard",argv[i]) == 0) materialtyp = STANDARDMATERIALS; else if (strcmp("riss",argv[i]) == 0) materialtyp = RISSMATERIALS; else if (strcmp("simple",argv[i]) == 0) materialtyp = SIMPLEMATERIALS; break; case 'r': { UINT newxpix,newypix; i++; if (i >= argc) fatal("option '-r' with no argument"); if (! override) continue; x = argv[i]; while (*x >= '0' && *x <= '9') x++; if (*x == 'x') /* new resolution */ { global_scene->xpix = strtouint(argv[i]); x++; global_scene->ypix = strtouint(x); global_scene->xstart = 0; global_scene->xsize = global_scene->xpix; global_scene->ystart = 0; global_scene->ysize = global_scene->ypix; } else /* scale to new resolution */ { newxpix = strtouint(argv[i]); newypix = iroundscale(global_scene->xpix,newxpix, global_scene->ypix); global_scene->xstart = iroundscale(global_scene->xpix, newxpix,global_scene->xstart); global_scene->xsize = iroundscale(global_scene->xpix, newxpix,global_scene->xsize); global_scene->ystart = iroundscale(global_scene->xpix, newxpix,global_scene->ystart); global_scene->ysize = iroundscale(global_scene->xpix, newxpix,global_scene->ysize); global_scene->xpix = newxpix; global_scene->ypix = newypix; } break; } case 'x': i++; if (i >= argc) fatal("option '-x' with no argument"); if (! override) continue; x = argv[i]; if (*x != '-') { global_scene->xstart = strtouint(x); if (global_scene->xstart >= global_scene->xpix) fatal("xstart >= xpixels"); while (*x >= '0' && *x <= '9') x++; global_scene->xsize = global_scene->xpix - global_scene->xstart; } if (*x == '\0') { global_scene->xsize = 1; continue; } if (*x != '-') fatal("option -x with illegal argument"); x++; if (*x != '\0') /* range */ { val = strtouint(x); if (val >= global_scene->xpix) fatal("xend >= xpixels"); if (val < global_scene->xstart) fatal("xstart < xend"); global_scene->xsize = val + 1 - global_scene->xstart; } break; case 'y': i++; if (i >= argc) fatal("option '-y' with no argument"); if (! override) continue; x = argv[i]; if (*x != '-') { global_scene->ystart = strtouint(x); if (global_scene->ystart >= global_scene->ypix) fatal("ystart >= ypixels"); while (*x >= '0' && *x <= '9') x++; global_scene->ysize = global_scene->ypix - global_scene->ystart; } if (*x == '\0') { global_scene->ysize = 1; continue; } if (*x != '-') fatal("option -y with illegal argument"); x++; if (*x != '\0') /* range */ { val = strtouint(x); if (val >= global_scene->ypix) fatal("yend >= ypixels"); if (val < global_scene->ystart) fatal("ystart < yend"); global_scene->ysize = val + 1 - global_scene->ystart; } break; default: fatal("illegal option '%s'",argv[i]); } } } /* Flirt/flirt.d000644 000316 000311 00000003352 06103226556 013253 0ustar00wrzlgup000000 000000 /**************************************************************************** Project: flirt Module: flirt.d global configuration switches debug switches Constants DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef FLIRT_D #define FLIRT_D #define VERSIONSTRING "0.86" #define SHORTSTRING "FLIRT" #define SMALLSHORTSTRING "flirt" #define NAMESTRING "Faster than LIght Ray-Tracer" /* #define SPECTRUM */ /* spectrum colors */ /* #define DB_GEOMETRICF */ /* RISSMAT: check for geometricfactor < 0 */ #define DB_HITCOUNT /* HITLIST & RAYTRACE: count used hits */ #define DB_RTFACE /* RAYTRACE: check for hit->face == 0L */ #define DB_RTNULL /* RAYTRACE: check for both obj's = NULL */ #define NO_DIFFERENCE (3.0 / 256.0) /* for adaptive sampling */ #define MAXADAPTLEVEL 3 /* max subdivisions */ #define MAXADAPT 8 /* 2^MAXADAPTLEVEL */ #define SCENE_EPS_DIVISOR 1.0E5 /* for epsilon of scene */ #define HIT_EPS_DIVISOR 1.0E3 /* for hitlist epsilon */ /* Constants for BSPLINES */ #define MAXRES 50 /* number of points in u/v */ #define MAXITERATIONS 30 /* maximum iterations */ #define ORTHOEPS 1e-4 #define MINCOSPHI 0.1 /* fuer Blech */ #define PNTIDENTFACTOR 1000.0 /* in Prozent der Blechstaerke oder */ /* Epiped-Hoehe */ #endif ine SCENE_EPS_DIVISOR 1.0E5 /* for epsilon of scene */ #define HIT_EPS_DIVISOR 1.0E3 /* for hitlist epsilon */ /* Constants for BSPLINES */ #define MAXRES 50 /* number of points in u/v */ #define MAXITERATIONS 30 Flirt/flirt.f000644 000316 000311 00000001660 06103226610 013244 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : flirt.f global DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef FLIRT_F #define FLIRT_F #include "flirt.d" #include "system.f" Extern BOOLEAN verbose; /* verbose flag */ Extern UINT obj_id; /* memory id for obj tree */ #define newonlymem(x) smalloc(obj_id,x) #define newonlytyp(x) ((x *) smalloc(obj_id,sizeof(x))) #define newonlyuni(typ,var) ((typ *) smalloc(obj_id,sizeof(var))) #define newonlyvar(typ,var) \ ((typ *) smalloc(obj_id,(ULONG) offsetof(typ,u) + sizeof(var))) /* usage: newonlyvar(OBJECT,BSPLINEOBJ); */ #endif " Extern BOOLEAN verbose; /* verbose flag */ Extern UINFlirt/geometr2.d000644 000316 000311 00000001777 06103226556 013670 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : geometr2.d Header file for basic 2D geometric types DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef GEOMETR2_D #define GEOMETR2_D #include "system.d" #include "flirt.d" typedef struct { FLOAT x; FLOAT y; } VEC2, PNT2; typedef struct { INT x; INT y; } INTPNT2; typedef struct { FLOAT e[3][2]; } MAT2; typedef struct { PNT2 origin; VEC2 direction; } AXIS2; typedef struct { PNT2 origin; VEC2 direction; VEC2 inv_dir; } RAY2; typedef struct { PNT2 min; PNT2 max; } BOX2; typedef struct { PNT2 center; FLOAT radius_2; } SPHERE2; #endif xFlirt/geometr2.f000644 000316 000311 00000013317 06103226610 013652 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : geometr2.f 2D - Vector macros DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef GEOMETR2_F #define GEOMETR2_F #include "geometr2.d" #include "numeric.f" #define v2length_2(v) ((v).x * (v).x + (v).y * (v).y) #define v2length(v) f_sqrt((v).x * (v).x + (v).y * (v).y) #define v2dot(v1,v2) ((v1).x * (v2).x + (v1).y * (v2).y) #define v2dist_2(v1,v2,dist_2) \ { \ VEC2 t; \ \ t.x = (v1).x - (v2).x; \ t.y = (v1).y - (v2).y; \ dist_2 = t.x * t.x + t.y * t.y; \ } #define v2dist(v1,v2,dist) \ { \ VEC2 t; \ \ t.x = (v1).x - (v2).x; \ t.y = (v1).y - (v2).y; \ dist = f_sqrt(t.x * t.x + t.y * t.y); \ } #define v2pmin(p1,p2,p) \ { \ (p).x = mini((p1).x,(p2).x); \ (p).y = mini((p1).y,(p2).y); \ } #define v2pmax(p1,p2,p) \ { \ (p).x = maxi((p1).x,(p2).x); \ (p).y = maxi((p1).y,(p2).y); \ } #define v2normalize(v) \ { \ FLOAT _len = v2length_2(v); \ \ if (! f_iszero(_len)) \ { \ _len = f_sqrt(_len); \ v2divk(v,_len); \ } \ } #define v2invdir(v,v1) \ { \ if (f_iszero((v).x)) \ (v1).x = F_HUGE; \ else \ (v1).x = 1.0 / (v).x; \ if (f_iszero((v).y)) \ (v1).y = F_HUGE; \ else \ (v1).y = 1.0 / (v).y; \ } #define v2negate(v) \ { \ (v).x = -(v).x; \ (v).y = -(v).y; \ } #define v2scale(v,s) \ { \ (v).x *= (s); \ (v).y *= (s); \ } #define v2divk(v,k) \ { \ (v).x /= (k); \ (v).y /= (k); \ } #define v2add(v1,v2,v) \ { \ (v).x = (v1).x + (v2).x; \ (v).y = (v1).y + (v2).y; \ } #define v2addto(v,v1) \ { \ (v).x += (v1).x; \ (v).y += (v1).y; \ } #define v2sub(v1,v2,v) \ { \ (v).x = (v1).x - (v2).x; \ (v).y = (v1).y - (v2).y; \ } #define v2subfrom(v,v1) \ { \ (v).x -= (v1).x; \ (v).y -= (v1).y; \ } #define v2mult(v1,v2,v) \ { \ (v).x = (v1).x * (v2).x; \ (v).y = (v1).y * (v2).y; \ } #define v2interpol(v1,v2,t,v) \ { \ (v).x = interpol((v1).x,(v2).x,t); \ (v).y = interpol((v1).y,(v2).y,t); \ } #define v2addscaled(v1,v2,t,v) \ { \ (v).x = (v1).x + (t) * (v2).x; \ (v).y = (v1).y + (t) * (v2).y; \ } #define v2add2scaled(v1,t1,v2,t2,v) \ { \ (v).x = (t1) * (v1).x + (t2) * (v2).x; \ (v).y = (t1) * (v1).y + (t2) * (v2).y; \ } #define readpnt2(pnt2) \ { \ (pnt2).x = readreal(); \ (pnt2).y = readreal(); \ } #endif x = (v1).x + (t) * (v2).x; \ (v).y = (v1).y + (t) * (v2).y; \ } #define v2add2scaled(v1,t1,v2,t2,v) \ { \ (v).x = (t1) * (v1).x + (t2) * (v2).x; \ (v).y = (t1)Flirt/geometr3.c000644 000316 000311 00000070012 06103226514 013646 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : geometr3.c 3-dimensional geometry routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "readdata.f" #include "symbols.f" #include "writdata.f" #include "geometr3.f" /****************************************************************************** Vectors & Matrices ******************************************************************************/ MAT3 M3ZERO = { { { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 } } }; MAT3 M3UNIT = { { { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 }, { 0.0, 0.0, 0.0 } } }; VEC3 V3ZERO = { 0.0, 0.0, 0.0 }; VEC3 V3ONE = { 1.0, 1.0, 1.0 }; VEC3 V3XUNIT = { 1.0, 0.0, 0.0 }; VEC3 V3YUNIT = { 0.0, 1.0, 0.0 }; VEC3 V3ZUNIT = { 0.0, 0.0, 1.0 }; VEC3 V3XNEGUNIT = { -1.0, 0.0, 0.0 }; VEC3 V3YNEGUNIT = { 0.0, -1.0, 0.0 }; VEC3 V3ZNEGUNIT = { 0.0, 0.0, -1.0 }; VEC3 V3SCENE_EPS = { 0.0, 0.0, 0.0 }; VOID readpnt3(PNT3 *pnt) { pnt->x = readreal(); pnt->y = readreal(); pnt->z = readreal(); } VOID readvec3(VEC3 *vec) { vec->x = readreal(); vec->y = readreal(); vec->z = readreal(); } VOID readmat3(MAT3 *mat) { mat->e[0][0] = readreal(); mat->e[0][1] = readreal(); mat->e[0][2] = readreal(); mat->e[1][0] = readreal(); mat->e[1][1] = readreal(); mat->e[1][2] = readreal(); mat->e[2][0] = readreal(); mat->e[2][1] = readreal(); mat->e[2][2] = readreal(); mat->e[3][0] = readreal(); mat->e[3][1] = readreal(); mat->e[3][2] = readreal(); } VOID readtransform(MAT3 *to,MAT3 *from) { TRANSTYP typ; FLOAT x,y,z; *to = M3UNIT; *from = M3UNIT; if (! matchreadconststring("transform")) return; if (matchreadconststring("matrix")) { readmat3(to); if (matchreadconststring("inverse")) readmat3(from); m3invert(to,from); } else { forever { typ = readnameconst(CONST_TRANSFORM,FALSE); if (typ == NOCONST) return; switch (typ) { case NO_TRANS: break; case TRANS_TRANS: case TRANS_SCALE: x = readreal(); y = readreal(); z = readreal(); switch (typ) { case TRANS_TRANS: m3trans(x,y,z,*to,*from); break; case TRANS_SCALE: m3scale(x,y,z,*to,*from); break; default: break; } break; case TRANS_SHEARXY: case TRANS_SHEARXZ: case TRANS_SHEARYZ: x = readreal(); y = readreal(); switch (typ) { case TRANS_SHEARXY: m3shearxy(x,y,*to,*from); break; case TRANS_SHEARXZ: m3shearxz(x,y,*to,*from); break; case TRANS_SHEARYZ: m3shearyz(x,y,*to,*from); break; default: break; } break; case TRANS_ROTX: case TRANS_ROTY: case TRANS_ROTZ: x = readreal(); x *= F_PI / 180.0; /* convert to radians */ switch (typ) { case TRANS_ROTX: m3rotx(x,*to,*from); break; case TRANS_ROTY: m3roty(x,*to,*from); break; case TRANS_ROTZ: m3rotz(x,*to,*from); break; default: break; } break; } } } return; } VOID readcubetrans(MAT3 *to,MAT3 *from) { TURNINFO turninfo; BOX3 box; if (matchreadconststring("min")) { readpnt3(&(box.min)); readconststring("max"); readpnt3(&(box.max)); turninfo = 1; turnbox2mat(turninfo,&box,to,from); } else { readtransform(to,from); } } VOID readspheretrans(MAT3 *to,MAT3 *from) { TURNINFO turninfo; SPHERE3 sphere; if (matchreadconststring("center")) { readpnt3(&(sphere.center)); readconststring("radius"); sphere.radius_2 = readreal(); sphere.radius_2 *= sphere.radius_2; turninfo = 1; turnsphere2mat(turninfo,&sphere,to,from); } else { readtransform(to,from); } } VOID writepnt3(PNT3 *pnt) { writereal(pnt->x); writereal(pnt->y); writereal(pnt->z); writelf(); } VOID writevec3(VEC3 *vec) { writereal(vec->x); writereal(vec->y); writereal(vec->z); writelf(); } VOID writemat3(MAT3 *mat) { writereal(mat->e[0][0]); writereal(mat->e[0][1]); writereal(mat->e[0][2]); writelf(); writereal(mat->e[1][0]); writereal(mat->e[1][1]); writereal(mat->e[1][2]); writelf(); writereal(mat->e[2][0]); writereal(mat->e[2][1]); writereal(mat->e[2][2]); writelf(); writereal(mat->e[3][0]); writereal(mat->e[3][1]); writereal(mat->e[3][2]); writelf(); } VOID writetransform(MAT3 *to,MAT3 *from) { writestring("transform"); writestring("matrix"); writemat3(to); writestring("inverse"); writemat3(from); } /****************************************************************************** Pointarrays ******************************************************************************/ POINTARRAY *readnamepoints(VOID) { POINTARRAY *points; readconststring(lookupstring(CONST_DATA,DATA_POINTS)); points = (POINTARRAY *)findname(INFO_POINTS,token); if (points == NULL) fatal("line %d: unknown %s '%s'",linenumber, lookupstring(CONST_DATA,DATA_POINTS),token); nexttoken(); return(points); } POINTARRAY *readpointarray(VOID) { UINT i; POINTARRAY *newpoints; newpoints = newonlytyp(POINTARRAY); match_read_uint("number",newpoints->number); newpoints->element = (PNT3 *) newonlymem(sizeof(PNT3) * newpoints->number); for (i = 0; i < newpoints->number; i++) readpnt3(&(newpoints->element[i])); return(newpoints); } VOID writenamepoints(POINTARRAY *points) { UCHAR Const *x; x = findinfo(INFO_POINTS,(VOIDPTR) points); if (x != NULL) { writestring(lookupstring(CONST_DATA,DATA_POINTS)); writestring(x); writelf(); } } VOID writepointarray(POINTARRAY *pointarray) { UINT i; write_string_uint("number", pointarray->number); for (i = 0; i < pointarray->number; i++) writepnt3(&(pointarray->element[i])); } /****************************************************************************** Turninfo routines ******************************************************************************/ BOOLEAN mat2turnbox(MAT3 *mat,TURNINFO *turninfo,BOX3 *box) { BYTE one,two; UINT i; PNT3 pone,ptwo; FLOAT t,val[3]; one = 0; two = 0; for (i = 0; i < 3; i++) val[i] = 0.0; for (i = 0; i < 3; i++) { if (! f_iszero(mat->e[0][i])) { if (val[0] != 0.0) return(FALSE); val[0] = mat->e[0][i]; one = (BYTE) i; } } if (val[0] == 0.0) return (FALSE); for (i = 0; i < 3; i++) { if (! f_iszero(mat->e[1][i])) { if (i == one || val[1] != 0.0) return(FALSE); val[1] = mat->e[1][i]; two = (BYTE) i; } } if (val[1] == 0.0) return (FALSE); for (i = 0; i < 3; i++) { if (! f_iszero(mat->e[2][i])) { if (i == one || i == two || val[2] != 0.0) return(FALSE); val[2] = mat->e[2][i]; } } if (val[2] == 0.0) return (FALSE); *turninfo = (BYTE) (one + 1); if ((UINT) ((one + 1) % 3) != (UINT) two) *turninfo |= TURN_INVTYP; if (val[0] < 0.0) *turninfo |= TURN_XSIGN; if (val[1] < 0.0) *turninfo |= TURN_YSIGN; if (val[2] < 0.0) *turninfo |= TURN_ZSIGN; t = f_abs(val[0]); if (t == f_abs(val[1]) && t == f_abs(val[2])) *turninfo |= TURN_NODISTORT; pone.x = mat->e[3][0]; pone.y = mat->e[3][1]; pone.z = mat->e[3][2]; ptwo.x = pone.x + val[0]; ptwo.y = pone.y + val[1]; ptwo.z = pone.z + val[2]; v3pmin(pone,ptwo,box->min); v3pmax(pone,ptwo,box->max); return(TRUE); } VOID turnbox2mat(TURNINFO turninfo,BOX3 *box,MAT3 *one,MAT3 *two) { FLOAT val[3]; INT i,j,dj; *one = M3ZERO; *two = M3ZERO; if (turninfo & TURN_XSIGN) { one->e[3][0] = box->max.x; val[0] = box->min.x - box->max.x; } else { one->e[3][0] = box->min.x; val[0] = box->max.x - box->min.x; } if (turninfo & TURN_YSIGN) { one->e[3][1] = box->max.y; val[1] = box->min.y - box->max.y; } else { one->e[3][1] = box->min.y; val[1] = box->max.y - box->min.y; } if (turninfo & TURN_ZSIGN) { one->e[3][2] = box->max.z; val[2] = box->min.z - box->max.z; } else { one->e[3][2] = box->min.z; val[2] = box->max.z - box->min.z; } j = (turninfo & TURN_QUANT) - 1; dj = (turninfo & TURN_INVTYP) ? 2 : 1; for (i = 0; i < 3; i++) { one->e[i][j] = val[i]; two->e[j][i] = 1.0 / val[i]; two->e[3][i] = - one->e[3][j] * two->e[j][i]; j = (j + dj) % 3; } } BOOLEAN mat2turnsphere(MAT3 *mat,TURNINFO *turninfo,SPHERE3 *sphere) { BYTE one,two; UINT i; FLOAT t,val[3]; one = 0; two = 0; for (i = 0; i < 3; i++) val[i] = 0.0; for (i = 0; i < 3; i++) { if (! f_iszero(mat->e[0][i])) { if (val[0] != 0.0) return(FALSE); val[0] = mat->e[0][i]; one = (BYTE) i; } } if (val[0] == 0.0) return (FALSE); for (i = 0; i < 3; i++) { if (! f_iszero(mat->e[1][i])) { if (i == one || val[1] != 0.0) return(FALSE); val[1] = mat->e[1][i]; two = (BYTE) i; } } if (val[1] == 0.0) return (FALSE); for (i = 0; i < 3; i++) { if (! f_iszero(mat->e[2][i])) { if (i == one || i == two || val[2] != 0.0) return(FALSE); val[2] = mat->e[2][i]; } } if (val[2] == 0.0) return (FALSE); *turninfo = (BYTE) (one + 1); if ((UINT) ((one + 1) % 3) != (UINT) two) *turninfo |= TURN_INVTYP; if (val[0] < 0.0) *turninfo |= TURN_XSIGN; if (val[1] < 0.0) *turninfo |= TURN_YSIGN; if (val[2] < 0.0) *turninfo |= TURN_ZSIGN; t = f_abs(val[0]); if (t == f_abs(val[1]) && t == f_abs(val[2])) { sphere->radius_2 = t * t; sphere->center.x = mat->e[3][0]; sphere->center.y = mat->e[3][1]; sphere->center.z = mat->e[3][2]; *turninfo |= TURN_NODISTORT; return(TRUE); } return(FALSE); } VOID turnsphere2mat(TURNINFO turninfo,SPHERE3 *sphere,MAT3 *one,MAT3 *two) { FLOAT r,val[3]; INT i,j,dj; r = f_sqrt(sphere->radius_2); *one = M3ZERO; *two = M3ZERO; one->e[3][0] = sphere->center.x; one->e[3][1] = sphere->center.y; one->e[3][2] = sphere->center.z; if (turninfo & TURN_XSIGN) val[0] = -r; else val[0] = r; if (turninfo & TURN_YSIGN) val[1] = -r; else val[1] = r; if (turninfo & TURN_ZSIGN) val[2] = -r; else val[2] = r; j = (turninfo & TURN_QUANT) - 1; dj = (turninfo & TURN_INVTYP) ? 2 : 1; for (i = 0; i < 3; i++) { one->e[i][j] = val[i]; two->e[j][i] = 1.0 / val[i]; two->e[3][i] = - one->e[3][j] * two->e[j][i]; j = (j + dj) % 3; } } /******************************************************************************/ VOID v3vmulminv( VEC3 v1, MAT3 *m, VEC3 *v ) { FLOAT det; det = m3det(*m); if ( f_iszero( det )) fatal("Non-singular matrix, no inverse"); v->x = ((m->e[1][1] * m->e[2][2] - m->e[1][2] * m->e[2][1]) * v1.x + (m->e[1][2] * m->e[2][0] - m->e[1][0] * m->e[2][2]) * v1.y + (m->e[1][0] * m->e[2][1] - m->e[1][1] * m->e[2][0]) * v1.z) / det; v->y = ((m->e[0][2] * m->e[2][1] - m->e[0][1] * m->e[2][2]) * v1.x + (m->e[0][0] * m->e[2][2] - m->e[0][2] * m->e[2][0]) * v1.y + (m->e[0][1] * m->e[2][0] - m->e[0][0] * m->e[2][1]) * v1.z) / det; v->z = ((m->e[0][1] * m->e[1][2] - m->e[0][2] * m->e[1][1]) * v1.x + (m->e[0][2] * m->e[1][0] - m->e[0][0] * m->e[1][2]) * v1.y + (m->e[0][0] * m->e[1][1] - m->e[0][1] * m->e[1][0]) * v1.z) / det; } /****************************************************************************** -1 1 calculate the inverse of a 4x3 matrix A = ------- adjoint A det A ******************************************************************************/ VOID m3invert( MAT3 *in, MAT3 *out ) { FLOAT det; det = m3det(*in); if ( f_iszero( det )) fatal("Non-singular matrix, no inverse"); /* calculate the adjoint matrix */ out->e[0][0] = (in->e[1][1] * in->e[2][2] - in->e[1][2] * in->e[2][1])/det; out->e[1][0] = (in->e[1][2] * in->e[2][0] - in->e[1][0] * in->e[2][2])/det; out->e[2][0] = (in->e[1][0] * in->e[2][1] - in->e[1][1] * in->e[2][0])/det; out->e[0][1] = (in->e[0][2] * in->e[2][1] - in->e[0][1] * in->e[2][2])/det; out->e[1][1] = (in->e[0][0] * in->e[2][2] - in->e[0][2] * in->e[2][0])/det; out->e[2][1] = (in->e[0][1] * in->e[2][0] - in->e[0][0] * in->e[2][1])/det; out->e[0][2] = (in->e[0][1] * in->e[1][2] - in->e[0][2] * in->e[1][1])/det; out->e[1][2] = (in->e[0][2] * in->e[1][0] - in->e[0][0] * in->e[1][2])/det; out->e[2][2] = (in->e[0][0] * in->e[1][1] - in->e[0][1] * in->e[1][0])/det; out->e[3][0] = -(in->e[3][0] * out->e[0][0] + in->e[3][1] * out->e[1][0] + in->e[3][2] * out->e[2][0]); out->e[3][1] = -(in->e[3][0] * out->e[0][1] + in->e[3][1] * out->e[1][1] + in->e[3][2] * out->e[2][1]); out->e[3][2] = -(in->e[3][0] * out->e[0][2] + in->e[3][1] * out->e[1][2] + in->e[3][2] * out->e[2][2]); } /***************************************************************************** ***************************************************************************** Routines for 3-d Macros ***************************************************************************** *****************************************************************************/ #ifdef G3_MAT_FUNCTIONS VOID m_3mmulm(MAT3 *m1,MAT3 *m2,MAT3 *m) { m->e[0][0] = m1->e[0][0] * m2->e[0][0] + m1->e[0][1] * m2->e[1][0] + m1->e[0][2] * m2->e[2][0]; m->e[0][1] = m1->e[0][0] * m2->e[0][1] + m1->e[0][1] * m2->e[1][1] + m1->e[0][2] * m2->e[2][1]; m->e[0][2] = m1->e[0][0] * m2->e[0][2] + m1->e[0][1] * m2->e[1][2] + m1->e[0][2] * m2->e[2][2]; m->e[1][0] = m1->e[1][0] * m2->e[0][0] + m1->e[1][1] * m2->e[1][0] + m1->e[1][2] * m2->e[2][0]; m->e[1][1] = m1->e[1][0] * m2->e[0][1] + m1->e[1][1] * m2->e[1][1] + m1->e[1][2] * m2->e[2][1]; m->e[1][2] = m1->e[1][0] * m2->e[0][2] + m1->e[1][1] * m2->e[1][2] + m1->e[1][2] * m2->e[2][2]; m->e[2][0] = m1->e[2][0] * m2->e[0][0] + m1->e[2][1] * m2->e[1][0] + m1->e[2][2] * m2->e[2][0]; m->e[2][1] = m1->e[2][0] * m2->e[0][1] + m1->e[2][1] * m2->e[1][1] + m1->e[2][2] * m2->e[2][1]; m->e[2][2] = m1->e[2][0] * m2->e[0][2] + m1->e[2][1] * m2->e[1][2] + m1->e[2][2] * m2->e[2][2]; m->e[3][0] = m1->e[3][0] * m2->e[0][0] + m1->e[3][1] * m2->e[1][0] + m1->e[3][2] * m2->e[2][0] + m2->e[3][0]; m->e[3][1] = m1->e[3][0] * m2->e[0][1] + m1->e[3][1] * m2->e[1][1] + m1->e[3][2] * m2->e[2][1] + m2->e[3][1]; m->e[3][2] = m1->e[3][0] * m2->e[0][2] + m1->e[3][1] * m2->e[1][2] + m1->e[3][2] * m2->e[2][2] + m2->e[3][2]; } #endif #ifdef G3_VEC_FUNCTIONS FLOAT v_3length_2(VEC3 *v) { return (v->x * v->x + v->y * v->y + v->z * v->z); } FLOAT v_3length(VEC3 *v) { return (f_sqrt(v->x * v->x + v->y * v->y + v->z * v->z)); } FLOAT v_3dot(VEC3 *v1,VEC3 *v2) { return (v1->x * v2->x + v1->y * v2->y + v1->z * v2->z); } VOID v_3dist_2(VEC3 *v1,VEC3 *v2,FLOAT *dist_2) { VEC3 t; t.x = v1->x - v2->x; t.y = v1->y - v2->y; t.z = v1->z - v2->z; *dist_2 = t.x * t.x + t.y * t.y + t.z * t.z; } VOID v_3dist(VEC3 *v1,VEC3 *v2,FLOAT *dist) { VEC3 t; t.x = v1->x - v2->x; t.y = v1->y - v2->y; t.z = v1->z - v2->z; *dist = f_sqrt(t.x * t.x + t.y * t.y + t.z * t.z); } VOID v_3pmin(PNT3 *p1,PNT3 *p2,PNT3 *p) { p->x = mini(p1->x,p2->x); p->y = mini(p1->y,p2->y); p->z = mini(p1->z,p2->z); } VOID v_3pmax(PNT3 *p1,PNT3 *p2,PNT3 *p) { p->x = maxi(p1->x,p2->x); p->y = maxi(p1->y,p2->y); p->z = maxi(p1->z,p2->z); } VOID v_3normalize(VEC3 *v) { FLOAT len = v_3length_2(v); if (! f_iszero(len)) { len = f_sqrt(len); v_3divk(v,len); } } VOID v_3invdir(VEC3 *v,VEC3 *v1) { if (f_iszero(v->x)) v1->x = sign(v->x) * F_HUGE; else v1->x = 1.0 / v->x; if (f_iszero(v->y)) v1->y = sign(v->y) * F_HUGE; else v1->y = 1.0 / v->y; if (f_iszero(v->z)) v1->z = sign(v->z) * F_HUGE; else v1->z = 1.0 / v->z; } VOID r_3normalize(RAY3 *r) { v_3normalize(&(r->direction)); v_3invdir(&(r->direction),&(r->inv_dir)); } VOID v_3negate(VEC3 *v) { v->x = -v->x; v->y = -v->y; v->z = -v->z; } VOID v_3scale(VEC3 *v,FLOAT s) { v->x *= s; v->y *= s; v->z *= s; } VOID v_3divk(VEC3 *v,FLOAT k) { v->x /= k; v->y /= k; v->z /= k; } VOID v_3add(VEC3 *v1,VEC3 *v2,VEC3 *v) { v->x = v1->x + v2->x; v->y = v1->y + v2->y; v->z = v1->z + v2->z; } VOID v_3addto(VEC3 *v,VEC3 *v1) { v->x += v1->x; v->y += v1->y; v->z += v1->z; } VOID v_3sub(VEC3 *v1,VEC3 *v2,VEC3 *v) { v->x = v1->x - v2->x; v->y = v1->y - v2->y; v->z = v1->z - v2->z; } VOID v_3subfrom(VEC3 *v,VEC3 *v1) { v->x -= v1->x; v->y -= v1->y; v->z -= v1->z; } VOID v_3multk(VEC3 *v1,FLOAT k,VEC3 *v) { v->x = v1->x * k; v->y = v1->y * k; v->z = v1->z * k; } VOID v_3mult(VEC3 *v1,VEC3 *v2,VEC3 *v) { v->x = v1->x * v2->x; v->y = v1->y * v2->y; v->z = v1->z * v2->z; } VOID v_3div(VEC3 *v1,VEC3 *v2,VEC3 *v) { v->x = v1->x / v2->x; v->y = v1->y / v2->y; v->z = v1->z / v2->z; } VOID v_3cross(VEC3 *v1,VEC3 *v2,VEC3 *v) { v->x = v1->y * v2->z - v1->z * v2->y; v->y = v1->z * v2->x - v1->x * v2->z; v->z = v1->x * v2->y - v1->y * v2->x; } VOID v_3interpol(VEC3 *v1,VEC3 *v2,FLOAT t,VEC3 *v) { v->x = interpol(v1->x,v2->x,t); v->y = interpol(v1->y,v2->y,t); v->z = interpol(v1->z,v2->z,t); } VOID v_3addscaled(VEC3 *v1,VEC3 *v2,FLOAT t,VEC3 *v) { v->x = v1->x + t * v2->x; v->y = v1->y + t * v2->y; v->z = v1->z + t * v2->z; } VOID v_3add2scaled(VEC3 *v1,FLOAT t1,VEC3 *v2,FLOAT t2,VEC3 *v) { v->x = t1 * v1->x + t2 * v2->x; v->y = t1 * v1->y + t2 * v2->y; v->z = t1 * v1->z + t2 * v2->z; } FLOAT m_3det(MAT3 *m) { return(m->e[0][0] * m->e[1][1] * m->e[2][2] + m->e[0][1] * m->e[1][2] * m->e[2][0] + m->e[0][2] * m->e[1][0] * m->e[2][1] - m->e[0][2] * m->e[1][1] * m->e[2][0] - m->e[0][1] * m->e[1][0] * m->e[2][2] - m->e[0][0] * m->e[1][2] * m->e[2][1]); } FLOAT v_3det(VEC3 *v1,VEC3 *v2,VEC3 *v3) { return(v1->x * v2->y * v3->z + v1->y * v2->z * v3->x + v1->z * v2->x * v3->y - v1->z * v2->y * v3->x - v1->y * v2->x * v3->z - v1->x * v2->z * v3->y); } VOID v_3pmulm(PNT3 *p1,MAT3 *m,PNT3 *p) { p->x = p1->x * m->e[0][0] + p1->y * m->e[1][0] + p1->z * m->e[2][0] + m->e[3][0]; p->y = p1->x * m->e[0][1] + p1->y * m->e[1][1] + p1->z * m->e[2][1] + m->e[3][1]; p->z = p1->x * m->e[0][2] + p1->y * m->e[1][2] + p1->z * m->e[2][2] + m->e[3][2]; } VOID v_3vmulm(VEC3 *v1,MAT3 *m,VEC3 *v) { v->x = v1->x * m->e[0][0] + v1->y * m->e[1][0] + v1->z * m->e[2][0]; v->y = v1->x * m->e[0][1] + v1->y * m->e[1][1] + v1->z * m->e[2][1]; v->z = v1->x * m->e[0][2] + v1->y * m->e[1][2] + v1->z * m->e[2][2]; } VOID v_3vmultransm(VEC3 *v1,MAT3 *m,VEC3 *v) { v->x = v1->x * m->e[0][0] + v1->y * m->e[0][1] + v1->z * m->e[0][2]; v->y = v1->x * m->e[1][0] + v1->y * m->e[1][1] + v1->z * m->e[1][2]; v->z = v1->x * m->e[2][0] + v1->y * m->e[2][1] + v1->z * m->e[2][2]; } VOID m_3trans(FLOAT xt,FLOAT yt,FLOAT zt,MAT3 *one,MAT3 *two) { one->e[3][0] += xt; one->e[3][1] += yt; one->e[3][2] += zt; two->e[3][0] -= two->e[0][0] * xt + two->e[1][0] * yt + two->e[2][0] * zt; two->e[3][1] -= two->e[0][1] * xt + two->e[1][1] * yt + two->e[2][1] * zt; two->e[3][2] -= two->e[0][2] * xt + two->e[1][2] * yt + two->e[2][2] * zt; } VOID m_3rotx(FLOAT alpha,MAT3 *one,MAT3 *two) { FLOAT _t; FLOAT _s = f_sin(alpha); FLOAT _c = f_cos(alpha); _t = one->e[0][1]; one->e[0][1] = _t * _c - one->e[0][2] * _s; one->e[0][2] = _t * _s + one->e[0][2] * _c; _t = one->e[1][1]; one->e[1][1] = _t * _c - one->e[1][2] * _s; one->e[1][2] = _t * _s + one->e[1][2] * _c; _t = one->e[2][1]; one->e[2][1] = _t * _c - one->e[2][2] * _s; one->e[2][2] = _t * _s + one->e[2][2] * _c; _t = one->e[3][1]; one->e[3][1] = _t * _c - one->e[3][2] * _s; one->e[3][2] = _t * _s + one->e[3][2] * _c; _t = two->e[1][0]; two->e[1][0] = _t * _c - two->e[2][0] * _s; two->e[2][0] = _t * _s + two->e[2][0] * _c; _t = two->e[1][1]; two->e[1][1] = _t * _c - two->e[2][1] * _s; two->e[2][1] = _t * _s + two->e[2][1] * _c; _t = two->e[1][2]; two->e[1][2] = _t * _c - two->e[2][2] * _s; two->e[2][2] = _t * _s + two->e[2][2] * _c; } VOID m_3roty(FLOAT alpha,MAT3 *one,MAT3 *two) { FLOAT _t; FLOAT _s = f_sin(alpha); FLOAT _c = f_cos(alpha); _t = one->e[0][0]; one->e[0][0] = _t * _c + one->e[0][2] * _s; one->e[0][2] = -_t * _s + one->e[0][2] * _c; _t = one->e[1][0]; one->e[1][0] = _t * _c + one->e[1][2] * _s; one->e[1][2] = -_t * _s + one->e[1][2] * _c; _t = one->e[2][0]; one->e[2][0] = _t * _c + one->e[2][2] * _s; one->e[2][2] = -_t * _s + one->e[2][2] * _c; _t = one->e[3][0]; one->e[3][0] = _t * _c + one->e[3][2] * _s; one->e[3][2] = -_t * _s + one->e[3][2] * _c; _t = two->e[0][0]; two->e[0][0] = _t * _c + two->e[2][0] * _s; two->e[2][0] = -_t * _s + two->e[2][0] * _c; _t = two->e[0][1]; two->e[0][1] = _t * _c + two->e[2][1] * _s; two->e[2][1] = -_t * _s + two->e[2][1] * _c; _t = two->e[0][2]; two->e[0][2] = _t * _c + two->e[2][2] * _s; two->e[2][2] = -_t * _s + two->e[2][2] * _c; } VOID m_3rotz(FLOAT alpha,MAT3 *one,MAT3 *two) { FLOAT _t; FLOAT _s = f_sin(alpha); FLOAT _c = f_cos(alpha); _t = one->e[0][0]; one->e[0][0] = _t * _c - one->e[0][1] * _s; one->e[0][1] = _t * _s + one->e[0][1] * _c; _t = one->e[1][0]; one->e[1][0] = _t * _c - one->e[1][1] * _s; one->e[1][1] = _t * _s + one->e[1][1] * _c; _t = one->e[2][0]; one->e[2][0] = _t * _c - one->e[2][1] * _s; one->e[2][1] = _t * _s + one->e[2][1] * _c; _t = one->e[3][0]; one->e[3][0] = _t * _c - one->e[3][1] * _s; one->e[3][1] = _t * _s + one->e[3][1] * _c; _t = two->e[0][0]; two->e[0][0] = _t * _c - two->e[1][0] * _s; two->e[1][0] = _t * _s + two->e[1][0] * _c; _t = two->e[0][1]; two->e[0][1] = _t * _c - two->e[1][1] * _s; two->e[1][1] = _t * _s + two->e[1][1] * _c; _t = two->e[0][2]; two->e[0][2] = _t * _c - two->e[1][2] * _s; two->e[1][2] = _t * _s + two->e[1][2] * _c; } VOID m_3scale(FLOAT xs,FLOAT ys,FLOAT zs,MAT3 *one,MAT3 *two) { FLOAT _x = 1.0 / (xs); FLOAT _y = 1.0 / (ys); FLOAT _z = 1.0 / (zs); one->e[0][0] *= xs; one->e[0][1] *= ys; one->e[0][2] *= zs; one->e[1][0] *= xs; one->e[1][1] *= ys; one->e[1][2] *= zs; one->e[2][0] *= xs; one->e[2][1] *= ys; one->e[2][2] *= zs; one->e[3][0] *= xs; one->e[3][1] *= ys; one->e[3][2] *= zs; two->e[0][0] *= _x; two->e[0][1] *= _x; two->e[0][2] *= _x; two->e[1][0] *= _y; two->e[1][1] *= _y; two->e[1][2] *= _y; two->e[2][0] *= _z; two->e[2][1] *= _z; two->e[2][2] *= _z; } VOID m_3shearxy(FLOAT xs,FLOAT ys,MAT3 *one,MAT3 *two) { one->e[0][0] += one->e[0][2] * xs; one->e[0][1] += one->e[0][2] * ys; one->e[1][0] += one->e[1][2] * xs; one->e[1][1] += one->e[1][2] * ys; one->e[2][0] += one->e[2][2] * xs; one->e[2][1] += one->e[2][2] * ys; one->e[3][0] += one->e[3][2] * xs; one->e[3][1] += one->e[3][2] * ys; two->e[2][0] -= two->e[0][0] * xs + two->e[1][0] * ys; two->e[2][1] -= two->e[0][1] * xs + two->e[1][1] * ys; two->e[2][2] -= two->e[0][2] * xs + two->e[1][2] * ys; } VOID m_3shearxz(FLOAT xs,FLOAT zs,MAT3 *one,MAT3 *two) { one->e[0][0] += one->e[0][1] * xs; one->e[0][2] += one->e[0][1] * zs; one->e[1][0] += one->e[1][1] * xs; one->e[1][2] += one->e[1][1] * zs; one->e[2][0] += one->e[2][1] * xs; one->e[2][2] += one->e[2][1] * zs; one->e[3][0] += one->e[3][1] * xs; one->e[3][2] += one->e[3][1] * zs; two->e[1][0] -= two->e[0][0] * xs + two->e[2][0] * zs; two->e[1][1] -= two->e[0][1] * xs + two->e[2][1] * zs; two->e[1][2] -= two->e[0][2] * xs + two->e[2][2] * zs; } VOID m_3shearyz(FLOAT ys,FLOAT zs,MAT3 *one,MAT3 *two) { one->e[0][1] += one->e[0][0] * ys; one->e[0][2] += one->e[0][0] * zs; one->e[1][1] += one->e[1][0] * ys; one->e[1][2] += one->e[1][0] * zs; one->e[2][1] += one->e[2][0] * ys; one->e[2][2] += one->e[2][0] * zs; one->e[3][1] += one->e[3][0] * ys; one->e[3][2] += one->e[3][0] * zs; two->e[0][0] -= two->e[1][0] * ys + two->e[2][0] * zs; two->e[0][1] -= two->e[1][1] * ys + two->e[2][1] * zs; two->e[0][2] -= two->e[1][2] * ys + two->e[2][2] * zs; } #endif ) { one->e[0][1] += one->e[0][0] * ys; one->e[0][2] += one->e[0][0] * zs; one->e[1][1] += one->e[1][0] * ys; one->e[1][2] += one->e[1][0] * zs; one->e[2][1] += one->e[2][0] * ys; one->e[2][2] += one->e[2][0] * zs; one->e[3][1] += one->e[3][0] * ys; one->e[3][2] += one->e[3][0] * zs; two->e[0][0] -= two->e[1][0] * ys + two->e[2][0] * zs; two->e[0][1] -= two->e[1][1] * ys + two->e[2][1] * zs; two->e[0][2] -= two->e[1][2] * ys + two->e[2][2] * zs; }Flirt/geometr3.d000644 000316 000311 00000002721 06103226556 013657 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : geometr3.d Header file for basic geometric types DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef GEOMETR3_D #define GEOMETR3_D #include "system.d" #include "flirt.d" #define TURN_QUANT ((BYTE) 0x03) #define TURN_INVTYP ((BYTE) 0x04) #define TURN_XSIGN ((BYTE) 0x08) #define TURN_YSIGN ((BYTE) 0x10) #define TURN_ZSIGN ((BYTE) 0x20) #define TURN_NODISTORT ((BYTE) 0x40) typedef BYTE TURNINFO; typedef struct { FLOAT x; FLOAT y; FLOAT z; } VEC3, PNT3; typedef struct { INT x; INT y; INT z; } INTPNT3; typedef struct { FLOAT e[4][3]; } MAT3; typedef struct { PNT3 origin; VEC3 direction; } AXIS3; typedef struct { PNT3 origin; VEC3 direction; VEC3 inv_dir; } RAY3; typedef struct { PNT3 min; PNT3 max; } BOX3; typedef struct { PNT3 center; FLOAT radius_2; } SPHERE3; typedef struct { PNT3 origin; VEC3 normal; FLOAT ndotp; } PLANE3; typedef struct pointarray { UINT number; PNT3 *element; } POINTARRAY; #endif PNT3 origin; VEC3 direction; } Flirt/geometr3.f000644 000316 000311 00000117346 06104111050 013652 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : geometr3.f 3-d Vector macros DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef GEOMETR3_F #define GEOMETR3_F #include "geometr3.d" #include "numeric.f" #if defined(MSDOS) && ! defined(__GNUC__) #define G3_MAT_FUNCTIONS /* define if you have short macros */ #define G3_VEC_FUNCTIONS /* define if you have very short macros */ #endif Extern MAT3 M3ZERO; Extern MAT3 M3UNIT; Extern VEC3 V3ZERO; Extern VEC3 V3ONE; Extern VEC3 V3XUNIT; Extern VEC3 V3YUNIT; Extern VEC3 V3ZUNIT; Extern VEC3 V3XNEGUNIT; Extern VEC3 V3YNEGUNIT; Extern VEC3 V3ZNEGUNIT; Extern VEC3 V3SCENE_EPS; VOID readpnt3 PP((PNT3 *pnt)); VOID readvec3 PP((VEC3 *vec)); VOID readmat3 PP((MAT3 *mat)); VOID readtransform PP((MAT3 *to,MAT3 *from)); VOID readspheretrans PP((MAT3 *to,MAT3 *from)); VOID readcubetrans PP((MAT3 *to,MAT3 *from)); VOID writepnt3 PP((PNT3 *pnt)); VOID writevec3 PP((VEC3 *vec)); VOID writemat3 PP((MAT3 *mat)); VOID writetransform PP((MAT3 *to,MAT3 *from)); POINTARRAY *readnamepoints PP((VOID)); POINTARRAY *readpointarray PP((VOID)); VOID writenamepoints PP((POINTARRAY *points)); VOID writepointarray PP((POINTARRAY *pointarray)); BOOLEAN mat2turnbox PP((MAT3 *mat,TURNINFO *turninfo,BOX3 *box)); VOID turnbox2mat PP((TURNINFO turninfo,BOX3 *box,MAT3 *one,MAT3 *two)); BOOLEAN mat2turnsphere PP((MAT3 *mat,TURNINFO *turninfo,SPHERE3 *sphere)); VOID turnsphere2mat PP((TURNINFO turninfo,SPHERE3 *sphere,MAT3 *one,MAT3 *two)); VOID m3invert PP((MAT3 *in,MAT3 *out)); #ifdef G3_MAT_FUNCTIONS VOID m_3mmulm PP((MAT3 *m1,MAT3 *m2,MAT3 *m)); #define m3mmulm(m1,m2,m) m_3mmulm(&(m1),&(m2),&(m)) #else /* m1 = m NOT ok */ #define m3mmulm(m1,m2,m)\ {\ (m).e[0][0] =(m1).e[0][0] * (m2).e[0][0] + (m1).e[0][1] * (m2).e[1][0] +\ (m1).e[0][2] * (m2).e[2][0];\ (m).e[0][1] =(m1).e[0][0] * (m2).e[0][1] + (m1).e[0][1] * (m2).e[1][1] +\ (m1).e[0][2] * (m2).e[2][1];\ (m).e[0][2] =(m1).e[0][0] * (m2).e[0][2] + (m1).e[0][1] * (m2).e[1][2] +\ (m1).e[0][2] * (m2).e[2][2];\ (m).e[1][0] =(m1).e[1][0] * (m2).e[0][0] + (m1).e[1][1] * (m2).e[1][0] +\ (m1).e[1][2] * (m2).e[2][0];\ (m).e[1][1] =(m1).e[1][0] * (m2).e[0][1] + (m1).e[1][1] * (m2).e[1][1] +\ (m1).e[1][2] * (m2).e[2][1];\ (m).e[1][2] =(m1).e[1][0] * (m2).e[0][2] + (m1).e[1][1] * (m2).e[1][2] +\ (m1).e[1][2] * (m2).e[2][2];\ (m).e[2][0] =(m1).e[2][0] * (m2).e[0][0] + (m1).e[2][1] * (m2).e[1][0] +\ (m1).e[2][2] * (m2).e[2][0];\ (m).e[2][1] =(m1).e[2][0] * (m2).e[0][1] + (m1).e[2][1] * (m2).e[1][1] +\ (m1).e[2][2] * (m2).e[2][1];\ (m).e[2][2] =(m1).e[2][0] * (m2).e[0][2] + (m1).e[2][1] * (m2).e[1][2] +\ (m1).e[2][2] * (m2).e[2][2];\ (m).e[3][0] =(m1).e[3][0] * (m2).e[0][0] + (m1).e[3][1] * (m2).e[1][0] +\ (m1).e[3][2] * (m2).e[2][0] + (m2).e[3][0];\ (m).e[3][1] =(m1).e[3][0] * (m2).e[0][1] + (m1).e[3][1] * (m2).e[1][1] +\ (m1).e[3][2] * (m2).e[2][1] + (m2).e[3][1];\ (m).e[3][2] =(m1).e[3][0] * (m2).e[0][2] + (m1).e[3][1] * (m2).e[1][2] +\ (m1).e[3][2] * (m2).e[2][2] + (m2).e[3][2];\ } #endif VOID v3vmulminv PP((VEC3 v1, MAT3 *m, VEC3 *v)); #ifdef G3_VEC_FUNCTIONS FLOAT v_3length_2 PP((VEC3 *v)); FLOAT v_3length PP((VEC3 *v)); FLOAT v_3dot PP((VEC3 *v1,VEC3 *v2)); VOID v_3dist_2 PP((VEC3 *v1,VEC3 *v2,FLOAT *dist_2)); VOID v_3dist PP((VEC3 *v1,VEC3 *v2,FLOAT *dist)); VOID v_3pmin PP((PNT3 *p1,PNT3 *p2,PNT3 *p)); VOID v_3pmax PP((PNT3 *p1,PNT3 *p2,PNT3 *p)); VOID v_3normalize PP((VEC3 *v)); VOID v_3invdir PP((VEC3 *v,VEC3 *v1)); VOID r_3normalize PP((RAY3 *r)); VOID v_3negate PP((VEC3 *v)); VOID v_3scale PP((VEC3 *v,FLOAT s)); VOID v_3divk PP((VEC3 *v,FLOAT k)); VOID v_3add PP((VEC3 *v1,VEC3 *v2,VEC3 *v)); VOID v_3addto PP((VEC3 *v,VEC3 *v1)); VOID v_3sub PP((VEC3 *v1,VEC3 *v2,VEC3 *v)); VOID v_3subfrom PP((VEC3 *v,VEC3 *v1)); VOID v_3multk PP((VEC3 *v1,FLOAT k,VEC3 *v)); VOID v_3mult PP((VEC3 *v1,VEC3 *v2,VEC3 *v)); VOID v_3div PP((VEC3 *v1,VEC3 *v2,VEC3 *v)); VOID v_3cross PP((VEC3 *v1,VEC3 *v2,VEC3 *v)); VOID v_3interpol PP((VEC3 *v1,VEC3 *v2,FLOAT t,VEC3 *v)); VOID v_3addscaled PP((VEC3 *v1,VEC3 *v2,FLOAT t,VEC3 *v)); VOID v_3add2scaled PP((VEC3 *v1,FLOAT t1,VEC3 *v2,FLOAT t2,VEC3 *v)); FLOAT m_3det PP((MAT3 *m)); FLOAT v_3det PP((VEC3 *v1,VEC3 *v2,VEC3 *v3)); VOID v_3pmulm PP((PNT3 *p1,MAT3 *m,PNT3 *p)); VOID v_3vmulm PP((VEC3 *v1,MAT3 *m,VEC3 *v)); VOID v_3vmultransm PP((VEC3 *v1,MAT3 *m,VEC3 *v)); VOID m_3trans PP((FLOAT xt,FLOAT yt,FLOAT zt,MAT3 *one,MAT3 *two)); VOID m_3rotx PP((FLOAT alpha,MAT3 *one,MAT3 *two)); VOID m_3roty PP((FLOAT alpha,MAT3 *one,MAT3 *two)); VOID m_3rotz PP((FLOAT alpha,MAT3 *one,MAT3 *two)); VOID m_3scale PP((FLOAT xs,FLOAT ys,FLOAT zs,MAT3 *one,MAT3 *two)); VOID m_3shearxy PP((FLOAT xs,FLOAT ys,MAT3 *one,MAT3 *two)); VOID m_3shearxz PP((FLOAT xs,FLOAT zs,MAT3 *one,MAT3 *two)); VOID m_3shearyz PP((FLOAT ys,FLOAT zs,MAT3 *one,MAT3 *two)); #define v3length_2(v) v_3length_2(&(v)) #define v3length(v) v_3length(&(v)) #define v3dot(v1,v2) v_3dot(&(v1),&(v2)) #define v3dist_2(v1,v2,d) v_3dist_2(&(v1),&(v2),&d) #define v3dist(v1,v2,d) v_3dist(&(v1),&(v2),&d) #define v3pmin(p1,p2,p) v_3pmin(&(p1),&(p2),&(p)) #define v3pmax(p1,p2,p) v_3pmax(&(p1),&(p2),&(p)) #define v3normalize(v) v_3normalize(&(v)) #define v3invdir(v,v1) v_3invdir(&(v),&(v1)) #define r3normalize(r) r_3normalize(&(r)) #define v3negate(v) v_3negate(&(v)) #define v3scale(v,s) v_3scale(&(v),s) #define v3divk(v,k) v_3divk(&(v),k) #define v3add(v1,v2,v) v_3add(&(v1),&(v2),&(v)) #define v3addto(v,v1) v_3addto(&(v),&(v1)) #define v3sub(v1,v2,v) v_3sub(&(v1),&(v2),&(v)) #define v3subfrom(v,v1) v_3subfrom(&(v),&(v1)) #define v3multk(v1,k,v) v_3multk(&(v1),k,&(v)) #define v3mult(v1,v2,v) v_3mult(&(v1),&(v2),&(v)) #define v3div(v1,v2,v) v_3div(&(v1),&(v2),&(v)) #define v3cross(v1,v2,v) v_3cross(&(v1),&(v2),&(v)) #define v3interpol(v1,v2,t,v) v_3interpol(&(v1),&(v2),t,&(v)) #define v3addscaled(v1,v2,t,v) v_3addscaled(&(v1),&(v2),t,&(v)) #define v3add2scaled(v1,t1,v2,t2,v) v_3add2scaled(&(v1),t1,&(v2),t2,&(v)) #define m3det(m) m_3det(&(m)) #define v3det(v1,v2,v3) v_3det(&(v1),&(v2),&(v3)) #define v3pmulm(p1,m,p) v_3pmulm(&(p1),&(m),&(p)) #define v3vmulm(v1,m,v) v_3vmulm(&(v1),&(m),&(v)) #define v3vmultransm(v1,m,v) v_3vmultransm(&(v1),&(m),&(v)) #define m3trans(xt,yt,zt,one,two) m_3trans(xt,yt,zt,&(one),&(two)) #define m3rotx(alpha,one,two) m_3rotx(alpha,&(one),&(two)) #define m3roty(alpha,one,two) m_3roty(alpha,&(one),&(two)) #define m3rotz(alpha,one,two) m_3rotz(alpha,&(one),&(two)) #define m3scale(xs,ys,zs,one,two) m_3scale(xs,ys,zs,&(one),&(two)) #define m3shearxy(xs,ys,one,two) m_3shearxy(xs,ys,&(one),&(two)) #define m3shearxz(xs,zs,one,two) m_3shearxz(xs,zs,&(one),&(two)) #define m3shearyz(ys,zs,one,two) m_3shearyz(ys,zs,&(one),&(two)) #else #define v3length_2(v) ((v).x * (v).x + (v).y * (v).y + (v).z * (v).z) #define v3length(v) f_sqrt(v3length_2(v)) #define v3dot(v1,v2) ((v1).x * (v2).x + (v1).y * (v2).y + (v1).z * (v2).z) #define v3dist_2(v1,v2,dist_2) \ { \ VEC3 _t; \ \ _t.x = (v1).x - (v2).x; \ _t.y = (v1).y - (v2).y; \ _t.z = (v1).z - (v2).z; \ dist_2 = _t.x * _t.x + _t.y * _t.y + _t.z * _t.z; \ } #define v3dist(v1,v2,dist) \ { \ VEC3 _t; \ \ _t.x = (v1).x - (v2).x; \ _t.y = (v1).y - (v2).y; \ _t.z = (v1).z - (v2).z; \ dist = f_sqrt(_t.x * _t.x + _t.y * _t.y + _t.z * _t.z); \ } #define v3pmin(p1,p2,p) \ { \ (p).x = mini((p1).x,(p2).x); \ (p).y = mini((p1).y,(p2).y); \ (p).z = mini((p1).z,(p2).z); \ } #define v3pmax(p1,p2,p) \ { \ (p).x = maxi((p1).x,(p2).x); \ (p).y = maxi((p1).y,(p2).y); \ (p).z = maxi((p1).z,(p2).z); \ } #define v3normalize(v) \ { \ FLOAT _len = v3length_2(v); \ \ if (! f_iszero(_len)) \ { \ _len = f_sqrt(_len); \ v3divk(v,_len); \ } \ } #define v3invdir(v,v1) \ { \ if (f_iszero((v).x)) \ (v1).x = sign((v).x) * F_HUGE; \ else \ (v1).x = 1.0 / (v).x; \ if (f_iszero((v).y)) \ (v1).y = sign((v).y) * F_HUGE; \ else \ (v1).y = 1.0 / (v).y; \ if (f_iszero((v).z)) \ (v1).z = sign((v).z) * F_HUGE; \ else \ (v1).z = 1.0 / (v).z; \ } #define r3normalize(r) \ { \ v3normalize((r).direction); \ v3invdir((r).direction,(r).inv_dir); \ } #define v3negate(v) \ { \ (v).x = -(v).x; \ (v).y = -(v).y; \ (v).z = -(v).z; \ } #define v3scale(v,s) \ { \ (v).x *= (s); \ (v).y *= (s); \ (v).z *= (s); \ } #define v3divk(v,k) \ { \ (v).x /= (k); \ (v).y /= (k); \ (v).z /= (k); \ } /* v1 = v ok */ #define v3add(v1,v2,v) \ { \ (v).x = (v1).x + (v2).x; \ (v).y = (v1).y + (v2).y; \ (v).z = (v1).z + (v2).z; \ } #define v3addto(v,v1) \ { \ (v).x += (v1).x; \ (v).y += (v1).y; \ (v).z += (v1).z; \ } /* v1 = v ok */ #define v3sub(v1,v2,v) \ { \ (v).x = (v1).x - (v2).x; \ (v).y = (v1).y - (v2).y; \ (v).z = (v1).z - (v2).z; \ } #define v3subfrom(v,v1) \ { \ (v).x -= (v1).x; \ (v).y -= (v1).y; \ (v).z -= (v1).z; \ } #define v3multk(v1,k,v) \ { \ (v).x = (v1).x * k; \ (v).y = (v1).y * k; \ (v).z = (v1).z * k; \ } /* v1 = v ok */ #define v3mult(v1,v2,v) \ { \ (v).x = (v1).x * (v2).x; \ (v).y = (v1).y * (v2).y; \ (v).z = (v1).z * (v2).z; \ } /* v1 = v ok */ #define v3div(v1,v2,v) \ { \ (v).x = (v1).x / (v2).x; \ (v).y = (v1).y / (v2).y; \ (v).z = (v1).z / (v2).z; \ } /* v1 = v NOT ok */ #define v3cross(v1,v2,v) \ { \ (v).x = (v1).y * (v2).z - (v1).z * (v2).y; \ (v).y = (v1).z * (v2).x - (v1).x * (v2).z; \ (v).z = (v1).x * (v2).y - (v1).y * (v2).x; \ } /* v1 = v ok */ #define v3interpol(v1,v2,t,v) \ { \ (v).x = interpol((v1).x,(v2).x,t); \ (v).y = interpol((v1).y,(v2).y,t); \ (v).z = interpol((v1).z,(v2).z,t); \ } /* v1 = v ok */ #define v3addscaled(v1,v2,t,v) \ { \ (v).x = (v1).x + (t) * (v2).x; \ (v).y = (v1).y + (t) * (v2).y; \ (v).z = (v1).z + (t) * (v2).z; \ } #define v3add2scaled(v1,t1,v2,t2,v) \ { \ (v).x = (t1) * (v1).x + (t2) * (v2).x; \ (v).y = (t1) * (v1).y + (t2) * (v2).y; \ (v).z = (t1) * (v1).z + (t2) * (v2).z; \ } #define m3det(m) \ ((m).e[0][0] * (m).e[1][1] * (m).e[2][2] + \ (m).e[0][1] * (m).e[1][2] * (m).e[2][0] + \ (m).e[0][2] * (m).e[1][0] * (m).e[2][1] - \ (m).e[0][2] * (m).e[1][1] * (m).e[2][0] - \ (m).e[0][1] * (m).e[1][0] * (m).e[2][2] - \ (m).e[0][0] * (m).e[1][2] * (m).e[2][1]) #define v3det(v1,v2,v3) \ ((v1).x * (v2).y * (v3).z + (v1).y * (v2).z * (v3).x + \ (v1).z * (v2).x * (v3).y - (v1).z * (v2).y * (v3).x - \ (v1).y * (v2).x * (v3).z - (v1).x * (v2).z * (v3).y) /* p1 = p NOT ok */ #define v3pmulm(p1,m,p) \ { \ (p).x = (p1).x * (m).e[0][0] + (p1).y * (m).e[1][0] + \ (p1).z * (m).e[2][0] + (m).e[3][0]; \ (p).y = (p1).x * (m).e[0][1] + (p1).y * (m).e[1][1] + \ (p1).z * (m).e[2][1] + (m).e[3][1]; \ (p).z = (p1).x * (m).e[0][2] + (p1).y * (m).e[1][2] + \ (p1).z * (m).e[2][2] + (m).e[3][2]; \ } /* v1 = v NOT ok */ #define v3vmulm(v1,m,v) \ { \ (v).x = (v1).x * (m).e[0][0] + (v1).y * (m).e[1][0] + \ (v1).z * (m).e[2][0]; \ (v).y = (v1).x * (m).e[0][1] + (v1).y * (m).e[1][1] + \ (v1).z * (m).e[2][1]; \ (v).z = (v1).x * (m).e[0][2] + (v1).y * (m).e[1][2] + \ (v1).z * (m).e[2][2]; \ } /* v1 = v NOT ok */ #define v3vmultransm(v1,m,v) \ { \ (v).x = (v1).x * (m).e[0][0] + (v1).y * (m).e[0][1] + \ (v1).z * (m).e[0][2]; \ (v).y = (v1).x * (m).e[1][0] + (v1).y * (m).e[1][1] + \ (v1).z * (m).e[1][2]; \ (v).z = (v1).x * (m).e[2][0] + (v1).y * (m).e[2][1] + \ (v1).z * (m).e[2][2]; \ } #define m3trans(xt,yt,zt,one,two) \ { \ (one).e[3][0] += xt; \ (one).e[3][1] += yt; \ (one).e[3][2] += zt; \ (two).e[3][0] -= (two).e[0][0] * xt + (two).e[1][0] * yt + \ (two).e[2][0] * zt; \ (two).e[3][1] -= (two).e[0][1] * xt + (two).e[1][1] * yt + \ (two).e[2][1] * zt; \ (two).e[3][2] -= (two).e[0][2] * xt + (two).e[1][2] * yt + \ (two).e[2][2] * zt; \ } #define m3rotx(alpha,one,two) \ { \ FLOAT _t; \ FLOAT _s = f_sin(alpha); \ FLOAT _c = f_cos(alpha); \ \ _t = (one).e[0][1]; \ (one).e[0][1] = _t * _c - (one).e[0][2] * _s; \ (one).e[0][2] = _t * _s + (one).e[0][2] * _c; \ _t = (one).e[1][1]; \ (one).e[1][1] = _t * _c - (one).e[1][2] * _s; \ (one).e[1][2] = _t * _s + (one).e[1][2] * _c; \ _t = (one).e[2][1]; \ (one).e[2][1] = _t * _c - (one).e[2][2] * _s; \ (one).e[2][2] = _t * _s + (one).e[2][2] * _c; \ _t = (one).e[3][1]; \ (one).e[3][1] = _t * _c - (one).e[3][2] * _s; \ (one).e[3][2] = _t * _s + (one).e[3][2] * _c; \ _t = (two).e[1][0]; \ (two).e[1][0] = _t * _c - (two).e[2][0] * _s; \ (two).e[2][0] = _t * _s + (two).e[2][0] * _c; \ _t = (two).e[1][1]; \ (two).e[1][1] = _t * _c - (two).e[2][1] * _s; \ (two).e[2][1] = _t * _s + (two).e[2][1] * _c; \ _t = (two).e[1][2]; \ (two).e[1][2] = _t * _c - (two).e[2][2] * _s; \ (two).e[2][2] = _t * _s + (two).e[2][2] * _c; \ } #define m3roty(alpha,one,two) \ { \ FLOAT _t; \ FLOAT _s = f_sin(alpha); \ FLOAT _c = f_cos(alpha); \ \ _t = (one).e[0][0]; \ (one).e[0][0] = _t * _c + (one).e[0][2] * _s; \ (one).e[0][2] = -_t * _s + (one).e[0][2] * _c; \ _t = (one).e[1][0]; \ (one).e[1][0] = _t * _c + (one).e[1][2] * _s; \ (one).e[1][2] = -_t * _s + (one).e[1][2] * _c; \ _t = (one).e[2][0]; \ (one).e[2][0] = _t * _c + (one).e[2][2] * _s; \ (one).e[2][2] = -_t * _s + (one).e[2][2] * _c; \ _t = (one).e[3][0]; \ (one).e[3][0] = _t * _c + (one).e[3][2] * _s; \ (one).e[3][2] = -_t * _s + (one).e[3][2] * _c; \ _t = (two).e[0][0]; \ (two).e[0][0] = _t * _c + (two).e[2][0] * _s; \ (two).e[2][0] = -_t * _s + (two).e[2][0] * _c; \ _t = (two).e[0][1]; \ (two).e[0][1] = _t * _c + (two).e[2][1] * _s; \ (two).e[2][1] = -_t * _s + (two).e[2][1] * _c; \ _t = (two).e[0][2]; \ (two).e[0][2] = _t * _c + (two).e[2][2] * _s; \ (two).e[2][2] = -_t * _s + (two).e[2][2] * _c; \ } #define m3rotz(alpha,one,two) \ { \ FLOAT _t; \ FLOAT _s = f_sin(alpha); \ FLOAT _c = f_cos(alpha); \ \ _t = (one).e[0][0]; \ (one).e[0][0] = _t * _c - (one).e[0][1] * _s; \ (one).e[0][1] = _t * _s + (one).e[0][1] * _c; \ _t = (one).e[1][0]; \ (one).e[1][0] = _t * _c - (one).e[1][1] * _s; \ (one).e[1][1] = _t * _s + (one).e[1][1] * _c; \ _t = (one).e[2][0]; \ (one).e[2][0] = _t * _c - (one).e[2][1] * _s; \ (one).e[2][1] = _t * _s + (one).e[2][1] * _c; \ _t = (one).e[3][0]; \ (one).e[3][0] = _t * _c - (one).e[3][1] * _s; \ (one).e[3][1] = _t * _s + (one).e[3][1] * _c; \ _t = (two).e[0][0]; \ (two).e[0][0] = _t * _c - (two).e[1][0] * _s; \ (two).e[1][0] = _t * _s + (two).e[1][0] * _c; \ _t = (two).e[0][1]; \ (two).e[0][1] = _t * _c - (two).e[1][1] * _s; \ (two).e[1][1] = _t * _s + (two).e[1][1] * _c; \ _t = (two).e[0][2]; \ (two).e[0][2] = _t * _c - (two).e[1][2] * _s; \ (two).e[1][2] = _t * _s + (two).e[1][2] * _c; \ } #define m3scale(xs,ys,zs,one,two) \ { \ FLOAT _x = 1.0 / (xs); \ FLOAT _y = 1.0 / (ys); \ FLOAT _z = 1.0 / (zs); \ \ (one).e[0][0] *= xs; \ (one).e[0][1] *= ys; \ (one).e[0][2] *= zs; \ (one).e[1][0] *= xs; \ (one).e[1][1] *= ys; \ (one).e[1][2] *= zs; \ (one).e[2][0] *= xs; \ (one).e[2][1] *= ys; \ (one).e[2][2] *= zs; \ (one).e[3][0] *= xs; \ (one).e[3][1] *= ys; \ (one).e[3][2] *= zs; \ (two).e[0][0] *= _x; \ (two).e[0][1] *= _x; \ (two).e[0][2] *= _x; \ (two).e[1][0] *= _y; \ (two).e[1][1] *= _y; \ (two).e[1][2] *= _y; \ (two).e[2][0] *= _z; \ (two).e[2][1] *= _z; \ (two).e[2][2] *= _z; \ } #define m3shearxy(xs,ys,one,two) \ { \ (one).e[0][0] += (one).e[0][2] * xs; \ (one).e[0][1] += (one).e[0][2] * ys; \ (one).e[1][0] += (one).e[1][2] * xs; \ (one).e[1][1] += (one).e[1][2] * ys; \ (one).e[2][0] += (one).e[2][2] * xs; \ (one).e[2][1] += (one).e[2][2] * ys; \ (one).e[3][0] += (one).e[3][2] * xs; \ (one).e[3][1] += (one).e[3][2] * ys; \ (two).e[2][0] -= (two).e[0][0] * xs + (two).e[1][0] * ys; \ (two).e[2][1] -= (two).e[0][1] * xs + (two).e[1][1] * ys; \ (two).e[2][2] -= (two).e[0][2] * xs + (two).e[1][2] * ys; \ } #define m3shearxz(xs,zs,one,two) \ { \ (one).e[0][0] += (one).e[0][1] * xs; \ (one).e[0][2] += (one).e[0][1] * zs; \ (one).e[1][0] += (one).e[1][1] * xs; \ (one).e[1][2] += (one).e[1][1] * zs; \ (one).e[2][0] += (one).e[2][1] * xs; \ (one).e[2][2] += (one).e[2][1] * zs; \ (one).e[3][0] += (one).e[3][1] * xs; \ (one).e[3][2] += (one).e[3][1] * zs; \ (two).e[1][0] -= (two).e[0][0] * xs + (two).e[2][0] * zs; \ (two).e[1][1] -= (two).e[0][1] * xs + (two).e[2][1] * zs; \ (two).e[1][2] -= (two).e[0][2] * xs + (two).e[2][2] * zs; \ } #define m3shearyz(ys,zs,one,two) \ { \ (one).e[0][1] += (one).e[0][0] * ys; \ (one).e[0][2] += (one).e[0][0] * zs; \ (one).e[1][1] += (one).e[1][0] * ys; \ (one).e[1][2] += (one).e[1][0] * zs; \ (one).e[2][1] += (one).e[2][0] * ys; \ (one).e[2][2] += (one).e[2][0] * zs; \ (one).e[3][1] += (one).e[3][0] * ys; \ (one).e[3][2] += (one).e[3][0] * zs; \ (two).e[0][0] -= (two).e[1][0] * ys + (two).e[2][0] * zs; \ (two).e[0][1] -= (two).e[1][1] * ys + (two).e[2][1] * zs; \ (two).e[0][2] -= (two).e[1][2] * ys + (two).e[2][2] * zs; \ } #define m3trans1(xt,yt,zt,one) \ { \ (one).e[3][0] += xt; \ (one).e[3][1] += yt; \ (one).e[3][2] += zt; \ } #define m3rotx1(alpha,one) \ { \ FLOAT _t; \ FLOAT _s = f_sin(alpha); \ FLOAT _c = f_cos(alpha); \ \ _t = (one).e[0][1]; \ (one).e[0][1] = _t * _c - (one).e[0][2] * _s; \ (one).e[0][2] = _t * _s + (one).e[0][2] * _c; \ _t = (one).e[1][1]; \ (one).e[1][1] = _t * _c - (one).e[1][2] * _s; \ (one).e[1][2] = _t * _s + (one).e[1][2] * _c; \ _t = (one).e[2][1]; \ (one).e[2][1] = _t * _c - (one).e[2][2] * _s; \ (one).e[2][2] = _t * _s + (one).e[2][2] * _c; \ _t = (one).e[3][1]; \ (one).e[3][1] = _t * _c - (one).e[3][2] * _s; \ (one).e[3][2] = _t * _s + (one).e[3][2] * _c; \ } #define m3roty1(alpha,one) \ { \ FLOAT _t; \ FLOAT _s = f_sin(alpha); \ FLOAT _c = f_cos(alpha); \ \ _t = (one).e[0][0]; \ (one).e[0][0] = _t * _c + (one).e[0][2] * _s; \ (one).e[0][2] = -_t * _s + (one).e[0][2] * _c; \ _t = (one).e[1][0]; \ (one).e[1][0] = _t * _c + (one).e[1][2] * _s; \ (one).e[1][2] = -_t * _s + (one).e[1][2] * _c; \ _t = (one).e[2][0]; \ (one).e[2][0] = _t * _c + (one).e[2][2] * _s; \ (one).e[2][2] = -_t * _s + (one).e[2][2] * _c; \ _t = (one).e[3][0]; \ (one).e[3][0] = _t * _c + (one).e[3][2] * _s; \ (one).e[3][2] = -_t * _s + (one).e[3][2] * _c; \ } #define m3rotz1(alpha,one) \ { \ FLOAT _t; \ FLOAT _s = f_sin(alpha); \ FLOAT _c = f_cos(alpha); \ \ _t = (one).e[0][0]; \ (one).e[0][0] = _t * _c - (one).e[0][1] * _s; \ (one).e[0][1] = _t * _s + (one).e[0][1] * _c; \ _t = (one).e[1][0]; \ (one).e[1][0] = _t * _c - (one).e[1][1] * _s; \ (one).e[1][1] = _t * _s + (one).e[1][1] * _c; \ _t = (one).e[2][0]; \ (one).e[2][0] = _t * _c - (one).e[2][1] * _s; \ (one).e[2][1] = _t * _s + (one).e[2][1] * _c; \ _t = (one).e[3][0]; \ (one).e[3][0] = _t * _c - (one).e[3][1] * _s; \ (one).e[3][1] = _t * _s + (one).e[3][1] * _c; \ } #define m3scale1(xs,ys,zs,one) \ { \ (one).e[0][0] *= xs; \ (one).e[0][1] *= ys; \ (one).e[0][2] *= zs; \ (one).e[1][0] *= xs; \ (one).e[1][1] *= ys; \ (one).e[1][2] *= zs; \ (one).e[2][0] *= xs; \ (one).e[2][1] *= ys; \ (one).e[2][2] *= zs; \ (one).e[3][0] *= xs; \ (one).e[3][1] *= ys; \ (one).e[3][2] *= zs; \ } #define m3shearxy1(xs,ys,one) \ { \ (one).e[0][0] += (one).e[0][2] * xs; \ (one).e[0][1] += (one).e[0][2] * ys; \ (one).e[1][0] += (one).e[1][2] * xs; \ (one).e[1][1] += (one).e[1][2] * ys; \ (one).e[2][0] += (one).e[2][2] * xs; \ (one).e[2][1] += (one).e[2][2] * ys; \ (one).e[3][0] += (one).e[3][2] * xs; \ (one).e[3][1] += (one).e[3][2] * ys; \ } #define m3shearxz1(xs,zs,one) \ { \ (one).e[0][0] += (one).e[0][1] * xs; \ (one).e[0][2] += (one).e[0][1] * zs; \ (one).e[1][0] += (one).e[1][1] * xs; \ (one).e[1][2] += (one).e[1][1] * zs; \ (one).e[2][0] += (one).e[2][1] * xs; \ (one).e[2][2] += (one).e[2][1] * zs; \ (one).e[3][0] += (one).e[3][1] * xs; \ (one).e[3][2] += (one).e[3][1] * zs; \ } #define m3shearyz1(ys,zs,one) \ { \ (one).e[0][1] += (one).e[0][0] * ys; \ (one).e[0][2] += (one).e[0][0] * zs; \ (one).e[1][1] += (one).e[1][0] * ys; \ (one).e[1][2] += (one).e[1][0] * zs; \ (one).e[2][1] += (one).e[2][0] * ys; \ (one).e[2][2] += (one).e[2][0] * zs; \ (one).e[3][1] += (one).e[3][0] * ys; \ (one).e[3][2] += (one).e[3][0] * zs; \ } #define m3trans2(xt,yt,zt,two) \ { \ (two).e[3][0] -= (two).e[0][0] * xt + (two).e[1][0] * yt + \ (two).e[2][0] * zt; \ (two).e[3][1] -= (two).e[0][1] * xt + (two).e[1][1] * yt + \ (two).e[2][1] * zt; \ (two).e[3][2] -= (two).e[0][2] * xt + (two).e[1][2] * yt + \ (two).e[2][2] * zt; \ } #define m3rotx2(alpha,two) \ { \ FLOAT _t; \ FLOAT _s = f_sin(alpha); \ FLOAT _c = f_cos(alpha); \ \ _t = (two).e[1][0]; \ (two).e[1][0] = _t * _c - (two).e[2][0] * _s; \ (two).e[2][0] = _t * _s + (two).e[2][0] * _c; \ _t = (two).e[1][1]; \ (two).e[1][1] = _t * _c - (two).e[2][1] * _s; \ (two).e[2][1] = _t * _s + (two).e[2][1] * _c; \ _t = (two).e[1][2]; \ (two).e[1][2] = _t * _c - (two).e[2][2] * _s; \ (two).e[2][2] = _t * _s + (two).e[2][2] * _c; \ } #define m3roty2(alpha,two) \ { \ FLOAT _t; \ FLOAT _s = f_sin(alpha); \ FLOAT _c = f_cos(alpha); \ \ _t = (two).e[0][0]; \ (two).e[0][0] = _t * _c + (two).e[2][0] * _s; \ (two).e[2][0] = -_t * _s + (two).e[2][0] * _c; \ _t = (two).e[0][1]; \ (two).e[0][1] = _t * _c + (two).e[2][1] * _s; \ (two).e[2][1] = -_t * _s + (two).e[2][1] * _c; \ _t = (two).e[0][2]; \ (two).e[0][2] = _t * _c + (two).e[2][2] * _s; \ (two).e[2][2] = -_t * _s + (two).e[2][2] * _c; \ } #define m3rotz2(alpha,two) \ { \ FLOAT _t; \ FLOAT _s = f_sin(alpha); \ FLOAT _c = f_cos(alpha); \ \ _t = (two).e[0][0]; \ (two).e[0][0] = _t * _c - (two).e[1][0] * _s; \ (two).e[1][0] = _t * _s + (two).e[1][0] * _c; \ _t = (two).e[0][1]; \ (two).e[0][1] = _t * _c - (two).e[1][1] * _s; \ (two).e[1][1] = _t * _s + (two).e[1][1] * _c; \ _t = (two).e[0][2]; \ (two).e[0][2] = _t * _c - (two).e[1][2] * _s; \ (two).e[1][2] = _t * _s + (two).e[1][2] * _c; \ } #define m3scale2(xs,ys,zs,two) \ { \ FLOAT _x = 1.0 / (xs); \ FLOAT _y = 1.0 / (ys); \ FLOAT _z = 1.0 / (zs); \ \ (two).e[0][0] *= _x; \ (two).e[0][1] *= _x; \ (two).e[0][2] *= _x; \ (two).e[1][0] *= _y; \ (two).e[1][1] *= _y; \ (two).e[1][2] *= _y; \ (two).e[2][0] *= _z; \ (two).e[2][1] *= _z; \ (two).e[2][2] *= _z; \ } #define m3shearxy2(xs,ys,two) \ { \ (two).e[2][0] -= (two).e[0][0] * xs + (two).e[1][0] * ys; \ (two).e[2][1] -= (two).e[0][1] * xs + (two).e[1][1] * ys; \ (two).e[2][2] -= (two).e[0][2] * xs + (two).e[1][2] * ys; \ } #define m3shearxz2(xs,zs,two) \ { \ (two).e[1][0] -= (two).e[0][0] * xs + (two).e[2][0] * zs; \ (two).e[1][1] -= (two).e[0][1] * xs + (two).e[2][1] * zs; \ (two).e[1][2] -= (two).e[0][2] * xs + (two).e[2][2] * zs; \ } #define m3shearyz2(ys,zs,two) \ { \ (two).e[0][0] -= (two).e[1][0] * ys + (two).e[2][0] * zs; \ (two).e[0][1] -= (two).e[1][1] * ys + (two).e[2][1] * zs; \ (two).e[0][2] -= (two).e[1][2] * ys + (two).e[2][2] * zs; \ } #endif #endif o).e[2][0] * zs; \ (two).e[1][1] -= (two).e[0][1] * xs + (two).e[2][1] * zs; \ (two).e[1][2] -= (two).e[0][2] * xs + (two).e[2][2] * zs; \ } #define m3shearyz2(ys,zs,two) \ { Flirt/grid.c000644 000316 000311 00000026517 06103226514 013061 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : grid.c grid manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "objects.f" #include "csg.f" #include "readdata.f" #include "writdata.f" #include "scene.f" /* scene_eps */ #include "grid.f" Static OBJECT *readgrid(VOID) { ULONG size; OBJECT *obj; obj = newonlyvar(OBJECT,GRIDOBJ); obj->typ = GRID; readconststring("dimension"); obj->u.grid.dim.x = (INT) readuint(); obj->u.grid.dim.y = (INT) readuint(); obj->u.grid.dim.z = (INT) readuint(); option_read_bool("optimisation", obj->u.grid.optimize,FALSE); obj->u.grid.original = readobjects(); size = (ULONG)obj->u.grid.dim.x * (ULONG)obj->u.grid.dim.y * (ULONG)obj->u.grid.dim.z * (ULONG)sizeof(OBJECT *); obj->u.grid.grid = (OBJECT **)newonlymem(size); return(obj); } Static OBJECT *copygrid(OBJECT *obj,BOOLEAN recurse,MAT3 *to,MAT3 *fr, MATERIAL *mat,TEXTURE *tex) { ULONG size; OBJECT *newobj; newobj = newonlyvar(OBJECT,GRID); newobj->typ = obj->typ; newobj->u.grid = obj->u.grid; size = (ULONG)newobj->u.grid.dim.x * (ULONG)newobj->u.grid.dim.y * (ULONG)newobj->u.grid.dim.z * (ULONG)sizeof(OBJECT *); newobj->u.grid.grid = (OBJECT **)newonlymem(size); if (recurse) newobj->u.grid.original = copyobj[obj->u.grid.original->typ](obj->u.grid.original,TRUE, to,fr,mat,tex); else newobj->u.grid.original = obj->u.grid.original; return(newobj); } Static VOID writegrid(OBJECT *obj) { writestring("dimension"); writeuint(obj->u.grid.dim.x); writeuint(obj->u.grid.dim.y); writeuint(obj->u.grid.dim.z); writelf(); write_string_bool("optimisation",obj->u.grid.optimize); writeobjects(obj->u.grid.original); } Static VOID boundgrid(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { boundobj[obj->u.grid.original->typ](obj->u.grid.original,bbox_test, bsphere_test,bounds_test,bbox,bsphere,bounds); obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_ALL; obj->test_bsphere = (bsphere_test) ? FALSE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; obj->bbox = obj->u.grid.original->bbox; obj->bsphere = obj->u.grid.original->bsphere; *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static UINT bbox_test(OBJECT *obj,VOIDPTR bound_volume) { PNT3 pmin,pmax; BOX3 *box; box = (BOX3 *) bound_volume; v3pmax(obj->bbox.min,box->min,pmin); v3pmin(obj->bbox.max,box->max,pmax); if (pmin.x <= pmax.x && pmin.y <= pmax.y && pmin.z <= pmax.z) { if (obj->bbox.min.x >= box->min.x && obj->bbox.min.y >= box->min.y && obj->bbox.min.z >= box->min.z && obj->bbox.max.x <= box->max.x && obj->bbox.max.y <= box->max.y && obj->bbox.max.z <= box->max.z) return(2); /* totally inside */ return(1); /* boxes intersect */ } return(0); /* no intersection */ } Static ULONG setupgrid(OBJECT *obj,BOOLEAN in_or_tree,BOOLEAN space_opt) { BOOLEAN changed; INT i,j,k; ULONG number_of_objects,num_objects; FLOAT lefty,leftz; OBJECT **node; GRIDOBJ *grid; BOX3 bbox; if (! in_or_tree) fatal("grid not in or-tree"); number_of_objects = setupobjects(obj->u.grid.original,TRUE,TRUE); grid = &(obj->u.grid); node = grid->grid; bbox = obj->bbox; v3sub(bbox.max,bbox.min,grid->el_len); grid->el_len.x /= grid->dim.x; grid->el_len.y /= grid->dim.y; grid->el_len.z /= grid->dim.z; v3add(bbox.min,grid->el_len,bbox.max); lefty = bbox.min.y; leftz = bbox.min.z; for (i = 0; i < grid->dim.x; i++) { for (j = 0; j < grid->dim.y; j++) { for (k = 0; k < grid->dim.z; k++) { changed = TRUE; /* split them */ *node = splitobj[grid->original->typ](grid->original, (VOIDPTR) &bbox,bbox_test,&changed,&num_objects); node++; bbox.min.z = bbox.max.z; bbox.max.z += grid->el_len.z; } bbox.min.z = leftz; bbox.max.z = leftz + grid->el_len.z; bbox.min.y = bbox.max.y; bbox.max.y += grid->el_len.y; } bbox.min.y = lefty; bbox.max.y = lefty + grid->el_len.y; bbox.min.x = bbox.max.x; bbox.max.x += grid->el_len.x; } return(number_of_objects); } Static OBJECT *insidegrid(PNT3 *pnt,OBJECT *obj) { INSIDE_BOUND_TEST(obj,pnt); /* FIXME: could be improved */ return(inside[obj->u.grid.original->typ](pnt,obj->u.grid.original)); } #define walk(cur_el,increment,mindist,dist,maxdist) \ { \ if (mindist != dist) \ dist -= mindist; \ else \ { \ cur_el = (UINT) ((INT) cur_el + increment); \ dist = maxdist; \ } \ } /* ------------------------------------------------------------------------ */ Static BOOLEAN hitgrid(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) /* --------------------------------------------------------------------------- calculate intersection with grid --------------------------------------------------------------------------- */ { BOOLEAN ray_hit_obj; UINT cur_el,num_gridels; FLOAT mindist; FLOAT loctmin,loctmax,loctmax_; INTPNT3 begin_el,increment; PNT3 begin; VEC3 dist,maxdist; OBJECT *node; GRIDOBJ *grid; HITLIST lochitlist; HITINFO *help; BOOLEAN lochit = FALSE; PRE_OBJECT(obj,hitlist); grid = &(obj->u.grid); v3addscaled(rci.ray.origin,rci.ray.direction,tmin,begin); begin_el.x = (INT) f_floor((begin.x - obj->bbox.min.x) / grid->el_len.x); begin_el.y = (INT) f_floor((begin.y - obj->bbox.min.y) / grid->el_len.y); begin_el.z = (INT) f_floor((begin.z - obj->bbox.min.z) / grid->el_len.z); begin_el.x = maxi(mini(begin_el.x,grid->dim.x - 1),0); begin_el.y = maxi(mini(begin_el.y,grid->dim.y - 1),0); begin_el.z = maxi(mini(begin_el.z,grid->dim.z - 1),0); if (rci.ray.inv_dir.x == 0.0) { increment.x = 0; dist.x = F_HUGE; } else { if (rci.ray.inv_dir.x < 0.0) { increment.x = - (grid->dim.y * grid->dim.z); dist.x = (begin_el.x * grid->el_len.x - (begin.x - obj->bbox.min.x)) * rci.ray.inv_dir.x; } else { increment.x = grid->dim.y * grid->dim.z; dist.x = ((begin_el.x + 1) * grid->el_len.x - (begin.x - obj->bbox.min.x)) * rci.ray.inv_dir.x; } maxdist.x = grid->el_len.x * f_abs(rci.ray.inv_dir.x); } if (rci.ray.inv_dir.y == 0.0) { increment.y = 0; dist.y = F_HUGE; } else { if (rci.ray.inv_dir.y < 0.0) { increment.y = - grid->dim.z; dist.y = (begin_el.y * grid->el_len.y - (begin.y - obj->bbox.min.y)) * rci.ray.inv_dir.y; } else { increment.y = grid->dim.z; dist.y = ((begin_el.y + 1) * grid->el_len.y - (begin.y - obj->bbox.min.y)) * rci.ray.inv_dir.y; } maxdist.y = grid->el_len.y * f_abs(rci.ray.inv_dir.y); } if (rci.ray.inv_dir.z == 0.0) { increment.z = 0; dist.z = F_HUGE; } else { if (rci.ray.inv_dir.z < 0.0) { increment.z = -1; dist.z = (begin_el.z * grid->el_len.z - (begin.z - obj->bbox.min.z)) * rci.ray.inv_dir.z; } else { increment.z = 1; dist.z = ((begin_el.z + 1) * grid->el_len.z - (begin.z - obj->bbox.min.z)) * rci.ray.inv_dir.z; } maxdist.z = grid->el_len.z * f_abs(rci.ray.inv_dir.z); } cur_el = (UINT) (begin_el.z + grid->dim.z * (begin_el.y + grid->dim.y * begin_el.x)); loctmin = tmin; loctmax = tmin; num_gridels = (UINT) grid->dim.x * (UINT) grid->dim.y * (UINT) grid->dim.z; if (grid->optimize) rci.save_hitlist++; while (loctmin < tmax - scene_eps) { mindist = mini(dist.x,mini(dist.y,dist.z)); loctmax += mindist; if (cur_el >= num_gridels) { message("WARNING: walked out of grid: %d\n",cur_el); break; } node = grid->grid[cur_el]; if (node != NULL) { lochitlist = emptyhitlist; loctmax_ = loctmax; /* HITOBJ aendert loctmax ! */ HITOBJ(node,loctmin,loctmax_,&lochitlist,ray_hit_obj); if (ray_hit_obj) { if ( ( ! rci.shadow ) && ( lochitlist.first != NULL ) ) { help = lochitlist.first; do { if ( help->t > scene_eps ) lochit = TRUE; help = help->next; } while ( help != NULL ); } if (hitlist->first != NULL ) { hitlist->last->next = lochitlist.first; hitlist->last = lochitlist.last; } else *hitlist = lochitlist; if (lochit) break; } } loctmin = loctmax; walk(cur_el,increment.x,mindist,dist.x,maxdist.x); walk(cur_el,increment.y,mindist,dist.y,maxdist.y); walk(cur_el,increment.z,mindist,dist.z,maxdist.z); } if (grid->optimize) rci.save_hitlist--; POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } Static VOID endgrid(OBJECT *obj) { endobj[obj->u.grid.original->typ](obj->u.grid.original); } VOID initgrid(VOID) { nameobj[GRID] = "grid"; readobj[GRID] = readgrid; copyobj[GRID] = copygrid; writeobj[GRID] = writegrid; boundobj[GRID] = boundgrid; setupobj[GRID] = setupgrid; splitobj[GRID] = split_primitiv; inside[GRID] = insidegrid; hitobj[GRID] = hitgrid; endobj[GRID] = endgrid; } POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } Static VOID endgrid(OBJECT *obj) { endobj[obj->u.grid.original->typ](obj->u.grid.original); } VOID iFlirt/grid.f000644 000316 000311 00000000717 06103226612 013055 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : grid.f Grid optimisation obj DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef GRID_F #define GRID_F #include "system.d" VOID initgrid PP((VOID)); #endif iginal->typ](obj-µ¯ «ö¨pinal); } VOID iFlirt/hitlist.c000644 000316 000311 00000051664 06114641323 013616 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : hitlist.c for lists of ray hits DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "geometr3.f" #include "hitlist.f" /* ------------------------------------------------------------------------ */ FLOAT hit_eps; INT usedhits = 0; HITINFO *freehits = NULL; HITLIST emptyhitlist = { NULL, NULL, NULL }; Static UINT freehitcopies = HITBLOCK; Static HITINFO *hitcopy = NULL; Static hit_id = SYSTEM; Static hitcopy_id = SYSTEM; /* ------------------------------------------------------------------------ the following macros are local and were introduced to increase the readability of the combination routines for the hitlists ------------------------------------------------------------------------ */ #define takehit(hit,nobj,chit) \ { \ chit->next = hit; \ chit = hit; \ chit->newobj = nobj; \ hit = hit->next; \ } /* ------------------------------------------------------------------------ the combination macros have been designed so that left objects have precedence ------------------------------------------------------------------------ */ #define orobj(left,right) (((left) != NULL) ? (left) : (right)) #define andobj(left,right) (((right) != NULL) ? (left) : NULL) #define subobj(left,right) (((right) != NULL) ? NULL : (left)) /* ------------------------------------------------------------------------ */ VOID inithitlist(VOID) { hit_id = getallocid(sizeof(HITINFO) * HITBLOCK); hitcopy_id = getallocid(sizeof(HITINFO) * HITBLOCK); freehits = NULL; freehitcopies = 0; hitcopy = NULL; } VOID releasehitlists(HITLIST *hitlist) { if (hitlist != NULL) /* free a hitlist */ { if (hitlist->first != NULL) freelist(hitlist->first, hitlist->last); hitlist->first = NULL; } #ifdef DB_HITCOUNT if (usedhits != 0) { message("WARNING: releasehitlists: %d hits not freed\n",usedhits); usedhits = 0; } #endif freemem(hitcopy_id,NULL); freehitcopies = 0; hitcopy = NULL; } /* ------------------------------------------------------------------------ we allocate the hits in blocks, and chain the hits in order to allow fast hitlist manipulation ------------------------------------------------------------------------ */ VOID newfreehits(VOID) { INT i; HITINFO *hittable; hittable = (HITINFO *)newmem(hit_id,sizeof(HITINFO) * HITBLOCK); freehits = NULL; for (i = 0; i < HITBLOCK; i++) { hittable->next = freehits; freehits = hittable; hittable++; } } /* ------------------------------------------------------------------------ */ VOID freehitlist(HITLIST *hitlist) { if (hitlist->first != NULL) freelist(hitlist->first, hitlist->last); hitlist->first = NULL; } /* ------------------------------------------------------------------------ */ VOID copyhitlist(HITLIST *fromlist, HITLIST *tolist,BOOLEAN as_normal_hits) { HITINFO *hit,*newhit,*next; tolist->firstobj = fromlist->firstobj; /* copy that anyway */ if (! as_normal_hits) /* use hitcopy_id */ { /* --------------------------------------------- the first kludge ! */ /* This ensures, that entering the first hit into the new list can */ /* be done with the same code as for all other hits; this works */ /* because the first field in 'HITINFO' is the 'next' field. */ /* You'll find the same kludge in 'or-', 'and-' and 'subhitlists' */ newhit = (HITINFO *)((VOIDPTR)&(tolist->first)); for (hit = fromlist->first; hit != NULL; hit = hit->next) { if (freehitcopies == 0) /* go get more */ { hitcopy = (HITINFO *)newmem(hitcopy_id, sizeof(HITINFO) * HITBLOCK); freehitcopies = HITBLOCK; } *hitcopy = *hit; newhit->next = hitcopy; newhit = hitcopy; freehitcopies--; hitcopy++; } newhit->next = NULL; /* finish chain ! */ tolist->last = newhit; /* set last hit */ } else { if (freehits == NULL) newfreehits(); tolist->first = freehits; newhit = freehits; for (hit = fromlist->first; hit != NULL; hit = hit->next) { next = newhit->next; /* save ptr to next */ *newhit = *hit; /* copy hit */ if (hit->next == NULL) /* end of list */ { freehits = next; /* restore freehits */ newhit->next = NULL; /* terminate list */ tolist->last = newhit; /* set last pointer */ break; } if (next == NULL) /* no more free hits */ { newfreehits(); /* get some more */ next = freehits; } newhit->next = next; /* chain again */ newhit = next; /* walk on */ } } } /*************************************************************************/ /* ------------------------------------------------------------------------ this is for debugging purposes ------------------------------------------------------------------------ */ VOID dumphitlist(HITLIST *hitlist) { HITINFO *hit; if (hitlist == NULL) { message(" HITLIST is empty!\n"); return; } message(" hitlist: first: %8lx, last: %8lx, firstobj: %8lx\n", hitlist->first,hitlist->last,hitlist->firstobj); for (hit = hitlist->first; hit != NULL; hit = hit->next) { message(" t: %8.4f, obj: %8lx, face: %3ld, newobj: %8lx\n", hit->t,hit->obj,hit->face,hit->newobj); } } /* ------------------------------------------------------------------------ combinehitlists ------------------------------------------------------------------------ -> lefthitlist -> righthitlist ------------------------------------------------------------------------ <- combihitlist ------------------------------------------------------------------------ These routines have been written with the precondition that both hit- lists are valid for the same interval. (This condition is a byproduct of the way the CSG-trees are handled.) ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ BOOLEAN orhitlists(HITLIST *leftlist,HITLIST *rightlist,HITLIST *combilist) { OBJECT *leftobj = leftlist->firstobj; OBJECT *rightobj = rightlist->firstobj; OBJECT *newobj = orobj(leftobj,rightobj); OBJECT *oldobj; HITINFO *lefthit = leftlist->first; HITINFO *righthit = rightlist->first; HITINFO *combihit; /* ------------------------------------------- the first kludge again ! */ combihit = (HITINFO *)((VOIDPTR)&(combilist->first)); combilist->firstobj = newobj; while (lefthit != NULL && righthit != NULL) { oldobj = newobj; if (lefthit->t == righthit->t) { leftobj = lefthit->newobj; rightobj = righthit->newobj; newobj = orobj(leftobj,rightobj); takehit(lefthit,newobj,combihit); skiphit(righthit); } else if (lefthit->t < righthit->t) { leftobj = lefthit->newobj; newobj = orobj(leftobj,rightobj); takehit(lefthit,newobj,combihit); } else { rightobj = righthit->newobj; newobj = orobj(leftobj,rightobj); if (newobj == oldobj) { skiphit(righthit); } else { takehit(righthit,newobj,combihit); } } } if (lefthit != NULL) { if (rightobj != NULL) { while (lefthit != NULL) { leftobj = lefthit->newobj; newobj = orobj(leftobj,rightobj); takehit(lefthit,newobj,combihit); } combihit->next = NULL; combilist->last = combihit; } else { combihit->next = lefthit; combilist->last = leftlist->last; } } else { if (leftobj != NULL) { if (righthit != NULL) freelist(righthit,rightlist->last); combihit->next = NULL; combilist->last = combihit; } else { combihit->next = righthit; if (righthit != NULL) combilist->last = rightlist->last; else combilist->last = combihit; } } returnhitlist(combilist); } /* ------------------------------------------------------------------------ */ BOOLEAN andhitlists(HITLIST *leftlist,HITLIST *rightlist,HITLIST *combilist) { OBJECT *leftobj = leftlist->firstobj; OBJECT *rightobj = rightlist->firstobj; OBJECT *newobj = andobj(leftobj,rightobj); OBJECT *oldobj; HITINFO *lefthit = leftlist->first; HITINFO *righthit = rightlist->first; HITINFO *combihit; /* ------------------------------------------- the first kludge again ! */ combihit = (HITINFO *)((VOIDPTR)&(combilist->first)); combilist->firstobj = newobj; while (lefthit != NULL && righthit != NULL) { oldobj = newobj; if (lefthit->t == righthit->t) { leftobj = lefthit->newobj; rightobj = righthit->newobj; newobj = andobj(leftobj,rightobj); if (newobj == oldobj) { skiphit(lefthit); } else { takehit(lefthit,newobj,combihit); } skiphit(righthit); } else if (lefthit->t < righthit->t) { leftobj = lefthit->newobj; newobj = andobj(leftobj,rightobj); if (newobj == oldobj) { skiphit(lefthit); } else { takehit(lefthit,newobj,combihit); } } else /* righthit->t < lefthit->t */ { rightobj = righthit->newobj; newobj = andobj(leftobj,rightobj); if (newobj == oldobj) { skiphit(righthit); } else { takehit(righthit,newobj,combihit); } } } if (lefthit != NULL) { if (rightobj != NULL) { combihit->next = lefthit; combilist->last = leftlist->last; } else { freelist(lefthit,leftlist->last); combihit->next = NULL; combilist->last = combihit; } } else { if (leftobj != NULL) { while (righthit != NULL) { oldobj = newobj; rightobj = righthit->newobj; newobj = andobj(leftobj,rightobj); if (newobj == oldobj) { skiphit(righthit); } else { takehit(righthit,newobj,combihit); } } } else { if (righthit != NULL) freelist(righthit,rightlist->last); } combihit->next = NULL; combilist->last = combihit; } returnhitlist(combilist); } /* ------------------------------------------------------------------------ */ BOOLEAN subhitlists(HITLIST *leftlist,HITLIST *rightlist,HITLIST *combilist) { OBJECT *leftobj = leftlist->firstobj; OBJECT *rightobj = rightlist->firstobj; OBJECT *newobj = subobj(leftobj,rightobj); OBJECT *oldobj; HITINFO *lefthit = leftlist->first; HITINFO *righthit = rightlist->first; HITINFO *combihit; /* ------------------------------------------- the first kludge again ! */ combihit = (HITINFO *)((VOIDPTR)&(combilist->first)); combilist->firstobj = newobj; while (lefthit != NULL && righthit != NULL) { oldobj = newobj; if (lefthit->t == righthit->t) { leftobj = lefthit->newobj; rightobj = righthit->newobj; newobj = subobj(leftobj,rightobj); if (newobj == oldobj) { skiphit(lefthit); } else { takehit(lefthit,newobj,combihit); } skiphit(righthit); } else if (lefthit->t < righthit->t) { leftobj = lefthit->newobj; newobj = subobj(leftobj,rightobj); if (newobj == oldobj) { skiphit(lefthit); } else { takehit(lefthit,newobj,combihit); } } else /* righthit->t < lefthit->t */ { rightobj = righthit->newobj; newobj = subobj(leftobj,rightobj); if (newobj == oldobj) { skiphit(righthit); } else { takehit(righthit,newobj,combihit); } } } if (lefthit != NULL) { if (rightobj == NULL) { combihit->next = lefthit; combilist->last = leftlist->last; } else { freelist(lefthit,leftlist->last); combihit->next = NULL; combilist->last = combihit; } } else { if (leftobj != NULL) { while (righthit != NULL) { oldobj = newobj; rightobj = righthit->newobj; newobj = subobj(leftobj,rightobj); if (newobj == oldobj) { skiphit(righthit); } else { takehit(righthit,newobj,combihit); } } } else { if (righthit != NULL) freelist(righthit,rightlist->last); } combihit->next = NULL; /* this may set combilist->first */ combilist->last = combihit; } returnhitlist(combilist); } VOID replacenull(HITLIST *hitlist,OBJECT *obj) { HITINFO *hit; if (hitlist->firstobj == NULL) hitlist->firstobj = obj; for (hit = hitlist->first; hit != NULL; hit = hit->next) { if (hit->newobj == NULL) hit->newobj = obj; } } VOID replaceobj(HITLIST *hitlist,OBJECT *obj) { HITINFO *hit; HITINFO *oldhit; OBJECT *oldobj; if (hitlist->firstobj != NULL) hitlist->firstobj = obj; oldobj = hitlist->firstobj; oldhit = (HITINFO *)((VOIDPTR)&(hitlist->first)); for (hit = hitlist->first; hit != NULL; hit = oldhit->next) { if (hit->newobj != NULL) hit->newobj = obj; if (oldobj == hit->newobj) { oldhit->next = hit->next; freehit(hit); } else { oldobj = hit->newobj; oldhit = hit; } } } VOID replaceall(HITLIST *hitlist,OBJECT *obj) { HITINFO *hit; HITINFO *oldhit; OBJECT *oldobj; if (hitlist->firstobj != NULL) hitlist->firstobj = NULL; else hitlist->firstobj = obj; oldobj = hitlist->firstobj; oldhit = (HITINFO *)((VOIDPTR)&(hitlist->first)); for (hit = hitlist->first; hit != NULL; hit = oldhit->next) { if (hit->newobj != NULL) hit->newobj = NULL; else hit->newobj = obj; if (oldobj == hit->newobj) { oldhit->next = hit->next; freehit(hit); } else { oldobj = hit->newobj; oldhit = hit; } } } BOOLEAN or2hits(OBJECT *obj,HITINFO *hit1,HITINFO *hit2,HITLIST *hitlist) { HITLIST newlist,oldlist; if (hitlist->first == NULL) { if (hitlist->firstobj == NULL) { prepare2hits(obj,hit1,hit2,hitlist); returnhitlist(hitlist); } else return(FALSE); /* already full hitlist */ } newlist = emptyhitlist; if (hit1 != NULL) { newlist.firstobj = NULL; newlist.first = hit1; hit1->obj = obj; hit1->newobj = obj; if (hit2 != NULL) { hit1->next = hit2; hit2->obj = obj; hit2->newobj = NULL; hit2->next = NULL; newlist.last = hit2; } else { hit1->next = NULL; newlist.last = hit1; } } else { newlist.firstobj = obj; if (hit2 != NULL) { hit2->next = NULL; hit2->obj = obj; hit2->newobj = NULL; newlist.first = hit2; newlist.last = hit2; } else returnhitlist(hitlist); } oldlist = *hitlist; return(orhitlists(&oldlist,&newlist,hitlist)); } BOOLEAN and2hits(OBJECT *obj,HITINFO *hit1,HITINFO *hit2,HITLIST *hitlist) { HITLIST newlist,oldlist; if (hitlist->first == NULL && hitlist->firstobj == NULL) return(FALSE); newlist = emptyhitlist; if (hit1 != NULL) { newlist.firstobj = NULL; newlist.first = hit1; hit1->obj = obj; hit1->newobj = obj; if (hit2 != NULL) { hit1->next = hit2; hit2->obj = obj; hit2->newobj = NULL; hit2->next = NULL; newlist.last = hit2; } else { hit1->next = NULL; newlist.last = hit1; } } else { newlist.firstobj = obj; if (hit2 != NULL) { hit2->next = NULL; hit2->obj = obj; hit2->newobj = NULL; newlist.first = hit2; newlist.last = hit2; } else { /* obj is always the same ! */ freehitlist(hitlist); hitlist->firstobj = obj; return(FALSE); } } oldlist = *hitlist; return(andhitlists(&oldlist,&newlist,hitlist)); } BOOLEAN sub2hits(OBJECT *obj,HITINFO *hit1,HITINFO *hit2,HITLIST *hitlist) { HITLIST newlist,oldlist; if (hitlist->first == NULL && hitlist->firstobj == NULL) return(FALSE); newlist = emptyhitlist; if (hit1 != NULL) { newlist.firstobj = NULL; newlist.first = hit1; hit1->obj = obj; hit1->newobj = obj; if (hit2 != NULL) { hit1->next = hit2; hit2->obj = obj; hit2->newobj = NULL; hit2->next = NULL; newlist.last = hit2; } else { hit1->next = NULL; newlist.last = hit1; } } else { newlist.firstobj = obj; if (hit2 != NULL) { hit2->next = NULL; hit2->obj = obj; hit2->newobj = NULL; newlist.first = hit2; newlist.last = hit2; } else { /* subtracted everything ! */ freehitlist(hitlist); return(FALSE); } } oldlist = *hitlist; return(subhitlists(&oldlist,&newlist,hitlist)); } lse { newlist.firstobj = obj; if (hit2 != NULL) Flirt/hitlist.d000644 000316 000311 00000003244 06114641417 013612 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : hitlist.d header file for lists of ray hits DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef HITLIST_D #define HITLIST_D #include "geometr2.d" #include "objects.d" #include "flirt.d" #define HITBLOCK 100 /* chunk size for hitlist allocation */ typedef struct mat_tree { MAT3 trans; struct mat_tree *next; } MATRIXNODE; typedef struct hitinfo { struct hitinfo *next; /* this field must!! be first of structure */ /* the reason for this is explained in */ /* 'hitlist.c', start of 'orhitlists' */ ULONG face; FLOAT t; OBJECT *obj; OBJECT *newobj; RAY3 ray; /* objects may use invdir */ /* for their own purposes */ VEC3 normal; /* optional mailbox from */ /* hitobj to normvec */ PNT2 uv; PNT3 local_point; VEC3 local_normal; MAT3 *transform; } HITINFO; typedef struct hitlist { HITINFO *first; HITINFO *last; OBJECT *firstobj; } HITLIST; #endif /* for their own purposes */ VEC3 normal; /* optional mailbox from */ /* hitobj to normvec */ PNT2 uv; PNT3 local_point; VEC3 local_normal; MAT3 *transform; } HFlirt/hitlist.f000644 000316 000311 00000025731 06114641265 013622 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : hitlist.f header file for lists of ray hits DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef HITLIST_F #define HITLIST_F #include "hitlist.d" Extern FLOAT hit_eps; Extern HITINFO *freehits; Extern HITLIST emptyhitlist; Extern INT usedhits; /* only used if DB_HITCOUNT is set */ #ifdef DB_HITCOUNT #define INCHIT usedhits++ #define DECHIT usedhits-- #else #define INCHIT #define DECHIT #endif /* ------------------------------------------------------------------------ The two checkadd macros have been introduced for the implementation of primitives which are the intersection of halfspaces. They provide early exits by checking against the t-intervall. ------------------------------------------------------------------------ */ #define checkaddmin(hitface,hit,tminface,tmin,tmax) \ { \ if (hit >= tmax) \ return FALSE; \ if (hit >= tmin) \ { \ tmin = hit; \ tminface = hitface; \ } \ } #define checkaddmax(hitface,hit,tmaxface,tmin,tmax) \ { \ if (hit <= tmin) \ return FALSE; \ if (hit <= tmax) \ { \ tmax = hit; \ tmaxface = hitface; \ } \ } /* ------------------------------------------------------------------------ the makehit macros help generating hitlists ------------------------------------------------------------------------ */ #define makehit(hitface,hitt,hit) \ { \ if (freehits == NULL) \ newfreehits(); \ hit = freehits; \ freehits = freehits->next; \ (hit)->t = hitt; \ (hit)->face = hitface; \ INCHIT; \ } #define checkmakehit(face,t,hit) \ { \ if (face != 0L) \ { \ makehit(face,t,hit); \ } \ else \ hit = NULL; \ } #define makerayhit(face,t,hitray,hit) \ { \ makehit(face,t,hit); \ hit->ray = hitray; \ } #define checkmakerayhit(face,t,hitray,hit) \ { \ if (face != 0L) \ { \ makerayhit(face,t,hitray,hit); \ } \ else \ hit = NULL; \ } /* ------------------------------------------------------------------------ the following two macros are used for processing single hits within a hitlist ------------------------------------------------------------------------ */ #define freehit(hit) \ { \ hit->next = freehits; \ freehits = hit; \ DECHIT; \ } #define skiphit(hit) \ { \ HITINFO *_help = hit; \ \ hit = hit->next; \ freehit(_help); \ } #ifdef DB_HITCOUNT #define freelist(fhit,lhit) \ { \ HITINFO *_hit,*_h; \ \ _hit = fhit; \ while (_hit != lhit && _hit != NULL) \ { \ _h = _hit->next; \ freehit(_hit); \ _hit = _h; \ } \ freehit(lhit); \ } #else #define freelist(fhit,lhit) \ { \ lhit->next = freehits; \ freehits = fhit; \ } #endif #define returnhitlist(hl) return((hl->first) != NULL ? TRUE : FALSE) /* ------------------------------------------------------------------------ prepare n hits (n = 2,4) ------------------------------------------------------------------------ -> hitobj the object that was hit -> hit1 the n hits, where hit1->t < ... < hitn->t ... -> hitn ----------------------------------------------------------------------- <- hitlist the readymade hitlist ------------------------------------------------------------------------ a value of NULL in the first/last hit signals that the hitintervall starts/ends at tmin/tmax ------------------------------------------------------------------------ */ #define prepare2hits(hitobj,hit1,hit2,hitlist) \ { \ if (hit1 != NULL) \ { \ (hitlist)->firstobj = NULL; \ (hitlist)->first = hit1; \ hit1->obj = hitobj; \ hit1->newobj = hitobj; \ if (hit2 != NULL) \ { \ hit1->next = hit2; \ hit2->obj = hitobj; \ hit2->newobj = NULL; \ hit2->next = NULL; \ (hitlist)->last = hit2; \ } \ else \ { \ hit1->next = NULL; \ (hitlist)->last = hit1; \ } \ } \ else \ { \ (hitlist)->firstobj = hitobj; \ if (hit2 != NULL) \ { \ (hitlist)->first = hit2; \ hit2->obj = hitobj; \ hit2->newobj = NULL; \ hit2->next = NULL; \ (hitlist)->last = hit2; \ } \ else \ (hitlist)->first = NULL; \ } \ } #define prepare4hits(hitobj,hit1,hit2,hit3,hit4,hitlist) \ { \ if (hit1 != NULL) \ { \ (hitlist)->firstobj = NULL; \ (hitlist)->first = hit1; \ hit1->obj = hitobj; \ hit1->newobj = hitobj; \ hit1->next = hit2; \ } \ else \ { \ (hitlist)->firstobj = hitobj; \ (hitlist)->first = hit2; \ } \ hit2->obj = hitobj; \ hit2->newobj = NULL; \ hit2->next = hit3; \ hit3->obj = hitobj; \ hit3->newobj = hitobj; \ if (hit4 != NULL) \ { \ hit3->next = hit4; \ hit4->obj = hitobj; \ hit4->newobj = NULL; \ hit4->next = NULL; \ (hitlist)->last = hit4; \ } \ else \ { \ hit3->next = NULL; \ (hitlist)->last = hit3; \ } \ } VOID inithitlist PP((VOID)); VOID releasehitlists PP((HITLIST *hitlist)); VOID newfreehits PP((VOID)); VOID freehitlist PP((HITLIST *hitlist)); VOID copyhitlist PP((HITLIST *fromlist, HITLIST *tolist, BOOLEAN as_normal_hits)); VOID dumphitlist PP((HITLIST *list)); BOOLEAN orhitlists PP((HITLIST *leftlist, HITLIST *rightlist, HITLIST *combilist)); BOOLEAN andhitlists PP((HITLIST *leftlist, HITLIST *rightlist, HITLIST *combilist)); BOOLEAN subhitlists PP((HITLIST *leftlist, HITLIST *rightlist, HITLIST *combilist)); VOID replacenull PP((HITLIST *hitlist,OBJECT *obj)); VOID replaceobj PP((HITLIST *hitlist,OBJECT *obj)); VOID replaceall PP((HITLIST *hitlist,OBJECT *obj)); BOOLEAN or2hits PP((OBJECT *obj,HITINFO *hit1,HITINFO *hit2,HITLIST *hitlist)); BOOLEAN and2hits PP((OBJECT *obj,HITINFO *hit1,HITINFO *hit2,HITLIST *hitlist)); BOOLEAN sub2hits PP((OBJECT *obj,HITINFO *hit1,HITINFO *hit2,HITLIST *hitlist)); #endif EAN subhitlists PP((HITLIST *leftlist, Flirt/hyperbol.c000644 000316 000311 00000024175 06103226516 013760 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : hyperbol.c hyperbol manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr2.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "material.f" #include "texture.f" #include "objects.f" #include "readdata.f" #include "hyperbol.f" Static OBJECT *readhyperbol(VOID) { OBJECT *obj; obj = newonlyvar(OBJECT,PAROBJ); obj->typ = HYPERBOLOID; match_read_real("radius", obj->u.parobj.floatpar); readtransform(&(obj->u.parobj.obj2world),&(obj->u.parobj.world2obj)); obj->u.parobj.material = readnamematerial(); obj->u.parobj.texture = readnametexture(); return(obj); } #define DIS 0.414213562 /* tan(22.5 * F_PI/180.0) == sqrt(2.0) - 1.0 */ Static PNT3 hull_hyperbol[16] = { { 1.0, DIS, -1.0 }, { 1.0, DIS, 1.0 }, { DIS, 1.0, -1.0 }, { DIS, 1.0, 1.0 }, { -DIS, 1.0, -1.0 }, { -DIS, 1.0, 1.0 }, { -1.0, DIS, -1.0 }, { -1.0, DIS, 1.0 }, { -1.0, -DIS, -1.0 }, { -1.0, -DIS, 1.0 }, { -DIS, -1.0, -1.0 }, { -DIS, -1.0, 1.0 }, { DIS, -1.0, -1.0 }, { DIS, -1.0, 1.0 }, { 1.0, -DIS, -1.0 }, { 1.0, -DIS, 1.0 } }; Static VOID plane2point(VEC3 *normal,MAT3 *obj2world,PNT3 *point,FLOAT rad) { VEC3 vec; v3vmultransm(*normal,*obj2world,vec); v2normalize(vec); v2scale(vec,rad); if (vec.z >= 0.0) vec.z = 1.0; else vec.z = -1.0; v3pmulm(vec,*obj2world,*point); } Static VOID boundhyperbol(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { FLOAT rad; PNT3 pnt; MAT3 m1,m2,m3; obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? TRUE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; rad = obj->u.parobj.floatpar; if (rad >= 0.0) rad = 1.0 + rad * rad; else rad = 1.0 - rad * rad; rad = f_sqrt(rad); m1 = M3UNIT; m2 = M3UNIT; m3 = obj->u.parobj.obj2world; m3scale(rad,rad,1.0,m1,m2); m3mmulm(m1,m3,m2); /* silly lint */ v3pmulm(V3ZERO,obj->u.parobj.obj2world,obj->bsphere.center); plane2point(&V3XUNIT,&(obj->u.parobj.obj2world),&pnt,rad); obj->bbox.max.x = pnt.x; obj->bbox.min.x = 2 * obj->bsphere.center.x - pnt.x; plane2point(&V3YUNIT,&(obj->u.parobj.obj2world),&pnt,rad); obj->bbox.max.y = pnt.y; obj->bbox.min.y = 2 * obj->bsphere.center.y - pnt.y; plane2point(&V3ZUNIT,&(obj->u.parobj.obj2world),&pnt,rad); obj->bbox.max.z = pnt.z; obj->bbox.min.z = 2 * obj->bsphere.center.z - pnt.z; bounds4points(16,hull_hyperbol,NULL,&(obj->bsphere),&pnt,&m2); *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static OBJECT *insidehyperbol(PNT3 *pnt,OBJECT *obj) { FLOAT r; PNT3 locpnt; INSIDE_BOUND_TEST(obj,pnt); v3pmulm(*pnt,obj->u.parobj.world2obj,locpnt); if (locpnt.z <= -1.0 || 1.0 <= locpnt.z) return(NULL); r = obj->u.parobj.floatpar; if (r >= 0.0) { if (locpnt.x * locpnt.x + locpnt.y * locpnt.y < r * r + locpnt.z * locpnt.z) return(obj); } if (locpnt.x * locpnt.x + locpnt.y * locpnt.y + r * r < locpnt.z * locpnt.z) return(obj); return(NULL); } /* ------------------------------------------------------------------------ */ Static BOOLEAN hithyperbol(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) /* ------------------------------------------------------------------------ calculate intersection of ray and hyperbol ------------------------------------------------------------------------ */ { ULONG tminface = 0L; ULONG tmaxface = 0L; HITINFO *hit1,*hit2; FLOAT a,b,c,d,tone,ttwo; FLOAT r; RAY3 locray; PRE_OBJECT(obj,hitlist); v3pmulm(rci.ray.origin,obj->u.parobj.world2obj,locray.origin); v3vmulm(rci.ray.direction,obj->u.parobj.world2obj,locray.direction); if (f_iszero(locray.direction.z)) /* ray parallel to z-planes ? */ { if (locray.origin.z <= -1.0 || locray.origin.z >= 1.0) return(FALSE); } else if (locray.direction.z > 0.0) { tone = (-1.0 - locray.origin.z) / locray.direction.z; checkaddmin(2L,tone,tminface,tmin,tmax); ttwo = (1.0 - locray.origin.z) / locray.direction.z; checkaddmax(3L,ttwo,tmaxface,tmin,tmax); } else { tone = (1.0 - locray.origin.z) / locray.direction.z; checkaddmin(3L,tone,tminface,tmin,tmax); ttwo = (-1.0 - locray.origin.z) / locray.direction.z; checkaddmax(2L,ttwo,tmaxface,tmin,tmax); } r = obj->u.parobj.floatpar; a = locray.direction.x * locray.direction.x + locray.direction.y * locray.direction.y - locray.direction.z * locray.direction.z; b = locray.origin.x * locray.direction.x + locray.origin.y * locray.direction.y - locray.origin.z * locray.direction.z; c = locray.origin.x * locray.origin.x + locray.origin.y * locray.origin.y - locray.origin.z * locray.origin.z - sign(r) * r * r; if (f_iszero(a)) /* linear equation ? */ { if (! f_iszero(b)) /* solvable ? */ { tone = - c / (2.0 * b); if (c > 0.0) /* eye outside contour */ { checkaddmin(1L,tone,tminface,tmin,tmax); } else { checkaddmax(1L,tone,tmaxface,tmin,tmax); } } else if (r <= 0.0) return(FALSE); } else { /* quadric equation : a t^2 + 2b t + c = 0 */ d = b * b - a * c; /* factor 2 was eliminated! */ if (d <= 0.0) /* no root ? */ { if (r < 0.0) /* didn't hithypertwoboloid */ return(FALSE); if (a > 0.0) return(FALSE); checkmakerayhit(tminface,tmin,locray,hit1); checkmakerayhit(tmaxface,tmax,locray,hit2); prepare2hits(obj,hit1,hit2,hitlist); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } if (b > 0.0) /* stable way to calculate */ d = - f_sqrt(d) - b; /* the roots of a quadratic */ else /* equation */ d = f_sqrt(d) - b; tone = d / a; ttwo = c / d; /* VIETA : tone * ttwo == c/a */ if (a <= 0) /* ray intersecting both */ { /* parts of hyperbolid : */ if (tone > ttwo) /* subtract interval */ { d = tone; tone = ttwo; ttwo = d; } if (tmin < tone && ttwo < tmax) /* 4 hits */ { HITINFO *hit3,*hit4; checkmakerayhit(tminface,tmin,locray,hit1); makerayhit(1L,tone,locray,hit2); makerayhit(1L,ttwo,locray,hit3); checkmakerayhit(tmaxface,tmax,locray,hit4); prepare4hits(obj,hit1,hit2,hit3,hit4,hitlist); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } if (tone < tmin) { checkaddmin(1L,ttwo,tminface,tmin,tmax); } else { checkaddmax(1L,tone,tmaxface,tmin,tmax); } } else /* ray intersecting only */ { /* one part of hyperbolid ? */ if (tone < ttwo) { checkaddmin(1L,tone,tminface,tmin,tmax); checkaddmax(1L,ttwo,tmaxface,tmin,tmax); } else { checkaddmin(1L,ttwo,tminface,tmin,tmax); checkaddmax(1L,tone,tmaxface,tmin,tmax); } } } checkmakerayhit(tminface,tmin,locray,hit1); checkmakerayhit(tmaxface,tmax,locray,hit2); prepare2hits(obj,hit1,hit2,hitlist); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } Static VOID normhyperbol(HITINFO *hit) { VEC3 locnormal; if (hit->face == 1L) { locnormal.x = hit->ray.origin.x + hit->t * hit->ray.direction.x; locnormal.y = hit->ray.origin.y + hit->t * hit->ray.direction.y; locnormal.z = - hit->ray.origin.z - hit->t * hit->ray.direction.z; v3vmultransm(locnormal,hit->obj->u.parobj.world2obj,hit->normal); } else if (hit->face == 2L) { v3vmultransm(V3ZNEGUNIT,hit->obj->u.parobj.world2obj,hit->normal); } else { v3vmultransm(V3ZUNIT,hit->obj->u.parobj.world2obj,hit->normal); } v3normalize(hit->normal); } VOID inithyperbol(VOID) { nameobj[HYPERBOLOID] = "hyperboloid"; surfaces[HYPERBOLOID] = 3L; readobj[HYPERBOLOID] = readhyperbol; copyobj[HYPERBOLOID] = copypobj; writeobj[HYPERBOLOID] = writepobj; boundobj[HYPERBOLOID] = boundhyperbol; setupobj[HYPERBOLOID] = setup_primitiv; splitobj[HYPERBOLOID] = split_primitiv; inside[HYPERBOLOID] = insidehyperbol; hitobj[HYPERBOLOID] = hithyperbol; normalvec[HYPERBOLOID] = normhyperbol; endobj[HYPERBOLOID] = end_primitiv; } perbol(VOID) { nameobj[HYPERBOLOID] = "hyperboloid"; surfaces[HYPERBOLOID] = 3L; readobj[HYPERBOLOID] = readhyperbol; copyobj[HYPERBOLOID] = copypobj; writeobj[HYPERBOLOID] = writepobj; boundobj[HYPERBOLOID] = boundhyperbol; setupobj[HYPERBOLOID] = setup_primitiv; splitobj[HYPERBOLOID] = split_primitiv; inside[HYPERBOLOID] = insidehyperbol; Flirt/hyperbol.f000644 000316 000311 00000000753 06103226612 013754 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : hyperbol.f hyperboloid manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef HYPERBOL_F #define HYPERBOL_F #include "system.d" VOID inithyperbol PP((VOID)); #endif Àinsidehyperbol; Flirt/hyperell.c000644 000316 000311 00000016407 06103226516 013757 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : hyperell.c hyperellipsoid manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "objects.f" #include "scene.f" /* scene_eps */ #include "readdata.f" #include "material.f" #include "texture.f" #include "writdata.f" #include "hyperell.f" Static OBJECT *readhyperell(VOID) { OBJECT *obj; obj = newonlyvar(OBJECT,HYPERELLOBJ); obj->typ = HYPERELLIPSOID; readconststring("order"); readvec3(&(obj->u.hyperell.order)); readtransform(&(obj->u.hyperell.obj2world),&(obj->u.hyperell.world2obj)); obj->u.hyperell.material = readnamematerial(); obj->u.hyperell.texture = readnametexture(); return(obj); } Static OBJECT *copyhyperell(OBJECT *obj,BOOLEAN recurse,MAT3 *to,MAT3 *fr, MATERIAL *mat,TEXTURE *tex) { OBJECT *newobj; newobj = newonlyvar(OBJECT,HYPERELLOBJ); newobj->typ = obj->typ; newobj->u.hyperell = obj->u.hyperell; if (mat != NULL) newobj->u.hyperell.material = mat; if (tex != NULL) newobj->u.hyperell.texture = tex; if (to != NULL && fr != NULL) { MAT3 m,m1; m1 = obj->u.hyperell.obj2world; m3mmulm(m1,*to,m); /* silly lint */ newobj->u.hyperell.obj2world = m; m1 = obj->u.hyperell.world2obj; m3mmulm(*fr,m1,m); /* silly lint */ newobj->u.hyperell.world2obj = m; } return(newobj); } Static VOID writehyperell(OBJECT *obj) { writestring("order"); writevec3(&(obj->u.hyperell.order)); writetransform(&(obj->u.obj.obj2world),&(obj->u.obj.world2obj)); writenamematerial(obj->u.obj.material); writenametexture(obj->u.obj.texture); } Static PNT3 hull_hyperellipsoid[8] = { { -1.0, -1.0, -1.0 }, { -1.0, -1.0, 1.0 }, { -1.0, 1.0, -1.0 }, { -1.0, 1.0, 1.0 }, { 1.0, -1.0, -1.0 }, { 1.0, -1.0, 1.0 }, { 1.0, 1.0, -1.0 }, { 1.0, 1.0, 1.0 } }; Static VOID boundhyperell(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? TRUE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; bounds4points(8,hull_hyperellipsoid,&(obj->bbox),&(obj->bsphere), &V3ZERO,&(obj->u.hyperell.obj2world)); *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static OBJECT *insidehyperell(PNT3 *pnt,OBJECT *obj) { PNT3 locpnt; INSIDE_BOUND_TEST(obj,pnt); v3pmulm(*pnt,obj->u.hyperell.world2obj,locpnt); if (f_pow(locpnt.x,obj->u.hyperell.order.x) + f_pow(locpnt.y,obj->u.hyperell.order.y) + f_pow(locpnt.z,obj->u.hyperell.order.z) < 1.0) return(obj); return(NULL); } Static BOX3 hyperellipsoid_box = { { -1.0, -1.0, -1.0 }, { 1.0, 1.0, 1.0 }, }; #define hyper_eq(pnt,order) f_pow(f_abs(pnt.x),order.x) + \ f_pow(f_abs(pnt.y),order.y) + \ f_pow(f_abs(pnt.z),order.z) - 1.0 #define hyper_eq1(pnt,t,vec,order) \ f_pow(f_abs(pnt.x + t * vec.x),order.x) + \ f_pow(f_abs(pnt.y + t * vec.y),order.y) + \ f_pow(f_abs(pnt.z + t * vec.z),order.z) - 1.0 /* ------------------------------------------------------------------------ */ Static BOOLEAN hithyperell(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) /* ------------------------------------------------------------------------ calculate intersection of ray and hyperellipsoid ------------------------------------------------------------------------ */ { ULONG tminface = 0L; ULONG tmaxface = 0L; FLOAT t1,t2,oldt; FLOAT v,oldv,diff; VEC3 order; RAY3 lr; HITINFO *hit1,*hit2; PRE_OBJECT(obj,hitlist); v3pmulm(rci.ray.origin,obj->u.hyperell.world2obj,lr.origin); v3vmulm(rci.ray.direction,obj->u.hyperell.world2obj,lr.direction); v3invdir(lr.direction,lr.inv_dir); t1 = 0.0; t2 = F_HUGE; if (! hitbbox(&lr,&t1,&t2,BOUNDTEST_ALL,&hyperellipsoid_box)) return(FALSE); order = obj->u.hyperell.order; v = hyper_eq(lr.origin,order); if (v <= scene_eps) oldt = t1 + scene_eps * 10.0; else oldt = t1 - scene_eps * 10.0; v = hyper_eq1(lr.origin,oldt,lr.direction,order); while (v > scene_eps * 10.0) { oldv = v; v = hyper_eq1(lr.origin,t1,lr.direction,order); if (v >= oldv) { t1 = -1.0; break; } diff = (v * (t1 - oldt)) / (v - oldv); oldt = t1; t1 -= diff; } oldt = t2 + scene_eps; v = hyper_eq1(lr.origin,oldt,lr.direction,order); while (v > scene_eps * 10.0) { oldv = v; v = hyper_eq1(lr.origin,t2,lr.direction,order); if (v >= oldv) { t2 = -1.0; break; } diff = (v * (t2 - oldt)) / (v - oldv); oldt = t2; t2 -= diff; } if (t1 < t2) { checkaddmin(1L,t1,tminface,tmin,tmax); checkaddmax(1L,t2,tmaxface,tmin,tmax); } else { checkaddmin(1L,t2,tminface,tmin,tmax); checkaddmax(1L,t1,tmaxface,tmin,tmax); } checkmakerayhit(tminface,tmin,lr,hit1); checkmakerayhit(tmaxface,tmax,lr,hit2); prepare2hits(obj,hit1,hit2,hitlist); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } Static VOID normhyperell(HITINFO *hit) { VEC3 p,locnormal,order; v3addscaled(hit->ray.origin,hit->ray.direction,hit->t,p); order = hit->obj->u.hyperell.order; locnormal.x = (p.x >= 0.0) ? f_pow(p.x,order.x - 1.0) : - f_pow(- p.x,order.x - 1.0); locnormal.y = (p.y >= 0.0) ? f_pow(p.y,order.y - 1.0) : - f_pow(- p.y,order.y - 1.0); locnormal.z = (p.z >= 0.0) ? f_pow(p.z,order.z - 1.0) : - f_pow(- p.z,order.z - 1.0); v3mult(locnormal,order,locnormal); v3vmultransm(locnormal,hit->obj->u.hyperell.world2obj,hit->normal); v3normalize(hit->normal); } VOID inithyperell(VOID) { nameobj[HYPERELLIPSOID] = "hyperellipsoid"; surfaces[HYPERELLIPSOID] = 1L; readobj[HYPERELLIPSOID] = readhyperell; copyobj[HYPERELLIPSOID] = copyhyperell; writeobj[HYPERELLIPSOID] = writehyperell; boundobj[HYPERELLIPSOID] = boundhyperell; setupobj[HYPERELLIPSOID] = setup_primitiv; splitobj[HYPERELLIPSOID] = split_primitiv; inside[HYPERELLIPSOID] = insidehyperell; hitobj[HYPERELLIPSOID] = hithyperell; normalvec[HYPERELLIPSOID] = normhyperell; endobj[HYPERELLIPSOID] = end_primitiv; } = "hyperellipsoid"; surfaces[HYPERELLIPSOID] = 1L; readobj[HYPERELLIPSOID] = readhyperell; copyobj[HYPERELLIPSOID] = copyhyperell; writeobj[HYPERELLIPSOID] = writehyperell; boundobj[HYPERELLIPSOID] = boundhyperell; setupobj[HFlirt/hyperell.f000644 000316 000311 00000000756 06103226612 013757 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : hyperell.f hyperellipsoid manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef HYPERELL_F #define HYPERELL_F #include "system.d" VOID inithyperell PP((VOID)); #endif ll; setupobj[HFlirt/hypsweep.c000644 000316 000311 00000023523 06103226516 013774 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : hypsweep.c hypsweep manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "material.f" #include "texture.f" #include "objects.f" #include "readdata.f" #include "hypsweep.f" Static OBJECT *readhypsweep(VOID) { OBJECT *obj; obj = newonlyvar(OBJECT,PAROBJ); obj->typ = HYPERBOLASWEEP; match_read_real("radius", obj->u.parobj.floatpar); readtransform(&(obj->u.parobj.obj2world),&(obj->u.parobj.world2obj)); obj->u.parobj.material = readnamematerial(); obj->u.parobj.texture = readnametexture(); return(obj); } Static PNT3 hull_hypsweep[] = { { 1.0, 1.0, 0.0 }, { 1.0, 1.0, 1.0 }, { -1.0, 1.0, 0.0 }, { -1.0, 1.0, 1.0 }, { -1.0, -1.0, 0.0 }, { -1.0, -1.0, 1.0 }, { 1.0, -1.0, 0.0 }, { 1.0, -1.0, 1.0 }, }; Static VEC3 midhypsweep = { 0.0, 0.0, 0.5 }; Static VOID boundhypsweep(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { FLOAT rad; MAT3 m1,m2,m3; obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? TRUE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; rad = obj->u.parobj.floatpar; if (rad >= 0.0) rad = 1.0 + rad * rad; else rad = 1.0 - rad * rad; rad = f_sqrt(rad); m1 = M3UNIT; m2 = M3UNIT; m3 = obj->u.parobj.obj2world; m3scale(rad,1.0,1.0,m1,m2); m3mmulm(m1,m3,m2); /* silly lint */ v3pmulm(midhypsweep,obj->u.parobj.obj2world,obj->bsphere.center); bounds4points(8,hull_hypsweep,&(obj->bbox),&(obj->bsphere), &(obj->bsphere.center),&m2); *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static OBJECT *insidehypsweep(PNT3 *pnt,OBJECT *obj) { FLOAT r; PNT3 locpnt; INSIDE_BOUND_TEST(obj,pnt); v3pmulm(*pnt,obj->u.parobj.world2obj,locpnt); if (locpnt.z <= 0.0 || 1.0 <= locpnt.y) return(NULL); if (locpnt.y <= -1.0 || 1.0 <= locpnt.y) return(NULL); r = obj->u.parobj.floatpar; if (r >= 0.0 && locpnt.x * locpnt.x < r * r + locpnt.y * locpnt.y) return(obj); if (locpnt.x * locpnt.x + r * r < locpnt.y * locpnt.y) return(obj); return(NULL); } /* ------------------------------------------------------------------------ */ Static BOOLEAN hithypsweep(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) /* ------------------------------------------------------------------------ calculate intersection of ray and hypsweep ------------------------------------------------------------------------ */ { ULONG tminface = 0L; ULONG tmaxface = 0L; FLOAT a,b,c,d,tone,ttwo; FLOAT r; RAY3 locray; HITINFO *hit1,*hit2; PRE_OBJECT(obj,hitlist); v3pmulm(rci.ray.origin,obj->u.parobj.world2obj,locray.origin); v3vmulm(rci.ray.direction,obj->u.parobj.world2obj,locray.direction); if (f_iszero(locray.direction.z)) /* ray parallel to z-planes ? */ { if (locray.origin.z <= 0.0 || locray.origin.z >= 1.0) return(FALSE); } else if (locray.direction.z > 0.0) { tone = - locray.origin.z / locray.direction.z; checkaddmin(4L,tone,tminface,tmin,tmax); ttwo = (1.0 - locray.origin.z) / locray.direction.z; checkaddmax(5L,ttwo,tmaxface,tmin,tmax); } else { tone = (1.0 - locray.origin.z) / locray.direction.z; checkaddmin(5L,tone,tminface,tmin,tmax); ttwo = - locray.origin.z / locray.direction.z; checkaddmax(4L,ttwo,tmaxface,tmin,tmax); } if (f_iszero(locray.direction.y)) /* ray parallel to y-planes ? */ { if (locray.origin.y <= -1.0 || locray.origin.y >= 1.0) return(FALSE); } else if (locray.direction.y > 0.0) { tone = (-1.0 - locray.origin.y) / locray.direction.y; checkaddmin(2L,tone,tminface,tmin,tmax); ttwo = (1.0 - locray.origin.y) / locray.direction.y; checkaddmax(3L,ttwo,tmaxface,tmin,tmax); } else { tone = (1.0 - locray.origin.y) / locray.direction.y; checkaddmin(3L,tone,tminface,tmin,tmax); ttwo = (-1.0 - locray.origin.y) / locray.direction.y; checkaddmax(2L,ttwo,tmaxface,tmin,tmax); } r = obj->u.parobj.floatpar; c = locray.origin.x * locray.origin.x - locray.origin.y * locray.origin.y - sign(r) * r * r; a = locray.direction.x * locray.direction.x; d = locray.direction.y * locray.direction.y; b = a + d; if (f_iszero(b) && c >= 0.0) return(FALSE); a = a - d; b = locray.origin.x * locray.direction.x - locray.origin.y * locray.direction.y; if (f_iszero(a)) /* linear equation ? */ { if (! f_iszero(b)) /* solvable ? */ { tone = - c / (2.0 * b); if (c > 0.0) /* this may be a bug */ { checkaddmin(1L,tone,tminface,tmin,tmax); } else { checkaddmax(1L,tone,tmaxface,tmin,tmax); } } else if (r <= 0.0) return(FALSE); } else { /* quadric equation : a t^2 + 2b t + c = 0 */ d = b * b - a * c; /* factor 2 was eliminated! */ if (d <= 0.0) /* no root ? */ { if (r < 0.0) return(FALSE); /* then exit */ if (a > 0.0) return(FALSE); checkmakerayhit(tminface,tmin,locray,hit1); checkmakerayhit(tmaxface,tmax,locray,hit2); prepare2hits(obj,hit1,hit2,hitlist); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } if (b > 0.0) /* stable way to calculate */ d = - f_sqrt(d) - b; /* the roots of a quadratic */ else /* equation */ d = f_sqrt(d) - b; tone = d / a; ttwo = c / d; /* VIETA : tone * ttwo == c/a */ if (a <= 0.0) /* ray intersecting both */ { /* parts of hypsweepid : */ if (tone > ttwo) /* subtract interval */ { d = tone; tone = ttwo; ttwo = d; } if (tmin < tone && ttwo < tmax) /* 4 hits */ { HITINFO *hit3,*hit4; checkmakerayhit(tminface,tmin,locray,hit1); makerayhit(1L,tone,locray,hit2); makerayhit(1L,ttwo,locray,hit3); checkmakerayhit(tmaxface,tmax,locray,hit4); prepare4hits(obj,hit1,hit2,hit3,hit4,hitlist); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } if (tone < tmin) { checkaddmin(1L,ttwo,tminface,tmin,tmax); } else { checkaddmax(1L,tone,tmaxface,tmin,tmax); } } else /* ray intersecting only */ { /* one part of hypsweepid ? */ if (tone < ttwo) { checkaddmin(1L,tone,tminface,tmin,tmax); checkaddmax(1L,ttwo,tmaxface,tmin,tmax); } else { checkaddmin(1L,ttwo,tminface,tmin,tmax); checkaddmax(1L,tone,tmaxface,tmin,tmax); } } } checkmakerayhit(tminface,tmin,locray,hit1); checkmakerayhit(tmaxface,tmax,locray,hit2); prepare2hits(obj,hit1,hit2,hitlist); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } Static VEC3 hypsweep_normal[] = { { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { 0.0, -1.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, -1.0 }, { 0.0, 0.0, 1.0 } }; Static VOID normhypsweep(HITINFO *hit) { VEC3 locnormal; if (hit->face == 1L) { locnormal.x = hit->ray.origin.x + hit->t * hit->ray.direction.x; locnormal.y = - hit->ray.origin.y - hit->t * hit->ray.direction.y; locnormal.z = 0.0; v3vmultransm(locnormal,hit->obj->u.parobj.world2obj,hit->normal); } else { v3vmultransm(hypsweep_normal[hit->face], hit->obj->u.parobj.world2obj,hit->normal); } v3normalize(hit->normal); } VOID inithypsweep(VOID) { nameobj[HYPERBOLASWEEP] = "hyperbolasweep"; surfaces[HYPERBOLASWEEP] = 5L; readobj[HYPERBOLASWEEP] = readhypsweep; copyobj[HYPERBOLASWEEP] = copypobj; writeobj[HYPERBOLASWEEP] = writepobj; boundobj[HYPERBOLASWEEP] = boundhypsweep; setupobj[HYPERBOLASWEEP] = setup_primitiv; splitobj[HYPERBOLASWEEP] = split_primitiv; inside[HYPERBOLASWEEP] = insidehypsweep; hitobj[HYPERBOLASWEEP] = hithypsweep; normalvec[HYPERBOLASWEEP] = normhypsweep; endobj[HYPERBOLASWEEP] = end_primitiv; } ASWEEP] = "hyperbolasweep"; surfaces[HYPERBOLASWEEP] = 5L; readobj[HYPERBOLASWEEP] = readhypsweep; copyobj[HYPERBOLASWEEP] = copypobj; writeobj[HYPERBOLASWEEFlirt/hypsweep.f000644 000316 000311 00000000756 06103226614 014001 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : hypsweep.f hyperbolasweep manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef HYPSWEEP_F #define HYPSWEEP_F #include "system.d" VOID inithypsweep PP((VOID)); #endif eobj[HYPERBOLASWEEFlirt/init.c000644 000316 000311 00000004261 06114642060 013067 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : init.c initialize modules DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "random.f" #include "light.f" #include "hitlist.f" #include "objects.f" #include "csg.f" #include "mcsg.f" #include "named.f" #include "repeat.f" #include "grid.f" #include "octree.f" #include "cylcube.f" #include "fived.f" #include "esbuf.f" #include "scube.f" #include "ssphere.f" #include "cube.f" #include "sphere.f" #include "cylinder.f" #include "parabol.f" #include "parsweep.f" #include "hyperbol.f" #include "hypsweep.f" #include "torus.f" #include "hyperell.f" #include "plane.f" #include "triangle.f" #include "smplmat.f" #include "stdmat.f" #include "rissmat.f" #include "texture.f" #include "symbols.f" #include "init.f" VOID initmodules(MATERIALTYP mattyp) { init_numeric(); init_random(); init_lights(); inithitlist(); initobjects(); /* must be called before init of special objects */ initcsg(); initmcsg(); initnamed(); initrepeat(); initgrid(); initoctree(); initcylcube(); initfived(); initesbuffer(); initcube(TRUE); /* allow simple objects */ initsphere(TRUE); /* allow simple objects */ initcylinder(); initscube(); initssphere(); initparabol(); initparsweep(); inithyperbol(); inithypsweep(); inittorus(); inithyperell(); initplane(); inittriangle(); inittexture(); initsymbols(); /* must be called after init of special objects */ /*init_math();*/ switch (mattyp) { case STANDARDMATERIALS: initstdmat(); break; case SIMPLEMATERIALS: initsmplmat(); break; case RISSMATERIALS: initrissmat(); break; } } VOID endmodules(VOID) { endobjects(); message("\nMODULE STATISTICS:\n"); exitobjects(); } ngle(); inittexture(); initsymbols(); /* must be called after init of special objects */ /*init_math();*/ switch (mattyp) { case STANDARDMATERIALS: initstdmat(); break; case SIMPLEMATERIALS: initsmplmat(); break; case RISSMATERIALS:Flirt/init.f000644 000316 000311 00000000775 06103226614 013101 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : init.f initialize modules DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef INIT_F #define INIT_F #include "material.d" VOID initmodules PP((MATERIALTYP mattyp)); VOID endmodules PP((VOID)); #endif LS:Flirt/light.c000644 000316 000311 00000054110 06103226520 013226 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : light.c light sources DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "color.f" #include "geometr3.f" #include "readdata.f" #include "symbols.f" #include "writdata.f" #include "light.f" #include "random.f" LIGHT *global_lights; LIGHTFUN_INTENSITY lightintensity[LAST_LIGHT]; /****************** GW - CHANGE *********************************/ LIGHTFUN_INIT lightinit [LAST_LIGHT]; LIGHTFUN_RAY lightray [LAST_LIGHT]; /*****************************************************************/ LIGHT *readlights(BOOLEAN readin) { UINT i; LIGHT *newlight,*oldlight,*lights; LIGHT loclight; lights = NULL; oldlight = NULL; while (matchreadconststring("typ")) { if (readin) newlight = newonlytyp(LIGHT); else newlight = &loclight; newlight->typ = readnameconst(CONST_LIGHT,TRUE); switch (newlight->typ) { case LIGHT_AMBIENT: break; case LIGHT_INFINITY: readconststring("direction"); readpnt3(&(newlight->position)); break; case LIGHT_POINT: readconststring("position"); readpnt3(&(newlight->position)); break; case LIGHT_SPHERE: readconststring("position"); readpnt3(&(newlight->position)); match_read_real("radius", newlight->u.sphere.radius); match_read_uint("samples", newlight->u.sphere.samples); break; case LIGHT_SPOT: readconststring("position"); readpnt3(&(newlight->position)); readconststring("direction"); readvec3(&(newlight->u.spot.direction)); match_read_real("power", newlight->u.spot.power); match_read_real("minangle", newlight->u.spot.minangle); match_read_real("maxangle", newlight->u.spot.maxangle); if (newlight->u.spot.minangle < 0.0 || newlight->u.spot.minangle > 180.0) fatal("spotlight: minangle too small or too big"); if (newlight->u.spot.maxangle < 0.0 || newlight->u.spot.maxangle > 180.0) fatal("spotlight: minangle too small or too big"); newlight->u.spot.minangle = f_cos(newlight->u.spot.minangle * F_DEG2RAD); newlight->u.spot.maxangle = f_cos(newlight->u.spot.maxangle * F_DEG2RAD); break; case LIGHT_DISTRIBUTION: readconststring("position"); readpnt3(&(newlight->position)); readconststring("direction"); readvec3(&(newlight->u.distribution.direction)); readconststring("distribution"); for (i = 0; i < LIGHTSAMPLES; i++) { newlight->u.distribution.sample[i] = readreal(); if (newlight->u.distribution.sample[i] < 0.0 || newlight->u.distribution.sample[i] > 1.0) fatal("distriblight: value too small or too big"); } break; /***************************/ /* GW - CHANGE */ /***************************/ case LIGHT_AREA_DISK: readconststring("position"); readpnt3(&(newlight->position)); readconststring("direction"); readvec3(&(newlight->u.area_disk.direction)); v3normalize(newlight->u.area_disk.direction); block { VEC3 vn,pre1; vn = newlight->u.area_disk.direction; v3negate (vn); do { pre1.x = rand01(); pre1.y = rand01(); pre1.z = rand01(); v3normalize(pre1); } while ( f_iszero(f_abs(v3dot(pre1, vn) - 1.0))); v3cross (vn, pre1, newlight->u.area_disk.v1); v3normalize (newlight->u.area_disk.v1); v3cross (vn, newlight->u.area_disk.v1, newlight->u.area_disk.v2); v3normalize (newlight->u.area_disk.v2); } match_read_uint("accuracy", newlight->u.area_disk.accuracy); match_read_real("radius", newlight->u.area_disk.radius); break; case LIGHT_AREA_TRIANGULAR: match_read_uint("accuracy",newlight->u.area_triangular.accuracy); readconststring("points"); readpnt3(&(newlight->u.area_triangular.p1)); readpnt3(&(newlight->u.area_triangular.p2)); readpnt3(&(newlight->u.area_triangular.p3)); v3sub (newlight->u.area_triangular.p2, newlight->u.area_triangular.p1, newlight->u.area_triangular.v1); v3sub (newlight->u.area_triangular.p3, newlight->u.area_triangular.p1, newlight->u.area_triangular.v2); v3cross (newlight->u.area_triangular.v1, newlight->u.area_triangular.v2, newlight->u.area_triangular.direction); v3normalize(newlight->u.area_triangular.direction); break; case LIGHT_AREA_SPHERE: readconststring("position"); readpnt3(&(newlight->position)); match_read_uint("accuracy",newlight->u.area_sphere.accuracy); match_read_real("radius", newlight->u.area_sphere.radius); break; default: break; } readconststring("color"); readcolor(&(newlight->color)); newlight->next = NULL; if (readin) { if (oldlight == NULL) lights = newlight; else oldlight->next = newlight; oldlight = newlight; } } return(lights); } VOID writelights(LIGHT *light) { UINT i; while (light != NULL) { writestring("typ"); writestring(lookupstring(CONST_LIGHT,(UINT) light->typ)); writelf(); switch (light->typ) { case LIGHT_AMBIENT: break; case LIGHT_INFINITY: writestring("direction"); writepnt3(&(light->position)); break; case LIGHT_POINT: writestring("position"); writepnt3(&(light->position)); break; case LIGHT_SPHERE: writestring("position"); writepnt3(&(light->position)); write_string_real("radius", light->u.sphere.radius); write_string_uint("samples", light->u.sphere.samples); break; case LIGHT_SPOT: writestring("position"); writepnt3(&(light->position)); writestring("direction"); writevec3(&(light->u.spot.direction)); write_string_real("power", light->u.spot.power); write_string_real("minangle", f_acos(light->u.spot.minangle) * F_RAD2DEG); write_string_real("maxangle", f_acos(light->u.spot.maxangle) * F_RAD2DEG); break; case LIGHT_DISTRIBUTION: writestring("position"); writepnt3(&(light->position)); writestring("direction"); writevec3(&(light->u.distribution.direction)); writestring("distribution"); for (i = 0; i < LIGHTSAMPLES / 2; i++) writereal(light->u.distribution.sample[i]); writelf(); for (i = LIGHTSAMPLES / 2; i < LIGHTSAMPLES; i++) writereal(light->u.distribution.sample[i]); writelf(); break; /***************************/ /* GW - CHANGE */ /***************************/ case LIGHT_AREA_DISK: writestring("position"); writepnt3(&(light->position)); writestring("direction"); writevec3(&(light->u.area_disk.direction)); write_string_uint("accuracy", light->u.area_disk.accuracy); write_string_real("radius", light->u.area_disk.radius); break; case LIGHT_AREA_TRIANGULAR: write_string_uint("accuracy", light->u.area_triangular.accuracy); writestring("points"); writepnt3(&(light->u.area_triangular.p1)); writepnt3(&(light->u.area_triangular.p2)); writepnt3(&(light->u.area_triangular.p3)); break; case LIGHT_AREA_SPHERE: writestring("position"); writepnt3(&(light->position)); write_string_uint("accuracy", light->u.area_sphere.accuracy); write_string_real("radius", light->u.area_sphere.radius); break; default: break; } writestring("color"); writecolor(&(light->color)); light = light->next; } } /************************************************************************/ /* L I G H T I N I T - F U N C T I O N S */ /************************************************************************/ Static UINT light_default_init (LIGHT *light) { return 1; } Static UINT light_area_disk_init (LIGHT *light) { return light->u.area_disk.accuracy; } Static UINT light_area_triangular_init (LIGHT *light) { return light->u.area_triangular.accuracy; } Static UINT light_area_sphere_init (LIGHT *light) { return light->u.area_sphere.accuracy; } Static VOID spotintensity(LIGHT *light,RAY3 *ray, FLOAT len, COLOR *color) { FLOAT costheta,t; costheta = - v3dot(ray->direction, light->u.spot.direction); if (costheta <= 0.0) { colorinit(*color,0.0); return; } /* Intensity is the product of costheta raised to power and */ /* a function that smoothly interpolates from */ /* 0 at costheta = maxangle to 1 at costheta = minangle. */ t = 1.0; if (light->u.spot.minangle < 1.0 - F_SMALL) /* cos(0) = 1 */ { if (costheta < light->u.spot.maxangle || light->u.spot.minangle == light->u.spot.maxangle) t = 0.0; else if (costheta > light->u.spot.minangle) t = 1.0; /* dummy op, fer readability */ else { /* Cubic interpolation between 0 at maxangle and 1 at minangle */ t = (costheta - light->u.spot.maxangle) / (light->u.spot.minangle - light->u.spot.maxangle); t = (3.0 - 2.0 * t) * t * t; } } if (light->u.spot.power != 0.0) t *= f_pow(costheta, light->u.spot.power); colormultk(light->color,t,*color); } Static VOID distributionintensity(LIGHT *light,RAY3 *ray, FLOAT len, COLOR *color) { UINT entry; FLOAT h,angle; h = - v3dot(ray->direction,light->u.distribution.direction) / F_PI * LIGHTSAMPLES; angle = f_acos(h); if (angle < 0.0) { message("distributionlight: angle < 0.0: %f\n",angle); angle = 0.0; } else if (angle >= LIGHTSAMPLES) { message("distributionlight: angle too big: %f\n",angle); angle = LIGHTSAMPLES - 1; } entry = (UINT) f_floor(angle); h = angle - (FLOAT) entry; h = light->u.distribution.sample[entry] * (1.0 - h) + light->u.distribution.sample[entry + 1] * h; colormultk(light->color,h,*color); } /********************************************************************/ Static VOID no_ray_intensity (LIGHT *light, RAY3 *ray, FLOAT len, COLOR *color) { *color = light->color; } Static VOID diskintensity(LIGHT *light,RAY3 *ray, FLOAT len, COLOR *color) { FLOAT h; DOUBLE t; h = - v3dot(ray->direction,light->u.area_disk.direction); if (h <= 0.0) { colorinit (light->color, 0.0); } else { t = h * light->u.area_disk.radius * light->u.area_disk.radius * F_PI / (len * len); colormultk(light->color,t,*color); } } Static VOID triangularintensity (LIGHT *light, RAY3 *ray, FLOAT len, COLOR *color) { FLOAT h; DOUBLE t; VEC3 psi_normalized; h = - v3dot (ray->direction, light->u.area_triangular.direction); if (h <= 0.0) { colorinit (light->color, 0.0); } else { psi_normalized = light->u.area_triangular.psi; v3normalize(psi_normalized); t = (light->u.area_triangular.area * - v3dot (light->u.area_triangular.normal_htr, psi_normalized)) / v3length_2(light->u.area_triangular.psi); colormultk (light->color,t,*color); } } Static VOID sphereintensity(LIGHT *light,RAY3 *ray, FLOAT len, COLOR *color) { DOUBLE t; t = 2.0 * F_PI * (1.0 - f_cos(light->u.area_sphere.phi_max)); colormultk (light->color, t, *color); } /********************************************************************/ Static VOID light_error(LIGHT *light,RAY3 *ray, FLOAT len, COLOR *color) { if (light == NULL) message("LIGHT *light == NULL\n"); if (ray == NULL) message("RAY3 *ray == NULL\n"); if (color == NULL) message("COLOR *color == NULL\n"); fatal("light_error called"); } /************************************************************************/ /* L I G H T R A Y - F U N C T I O N S */ /************************************************************************/ Static FLOAT light_default_ray (LIGHT *light, PNT3 *point, RAY3 *ray) { FLOAT tmp_len; v3sub (light->position, *point, ray->direction); tmp_len = v3length(ray->direction); v3divk(ray->direction, tmp_len); return tmp_len; } Static FLOAT light_infinity_ray (LIGHT *light, PNT3 *point, RAY3 *ray) { FLOAT tmp_len; ray->direction = light->position; tmp_len = v3length(ray->direction); v3divk(ray->direction, tmp_len); return tmp_len; } Static FLOAT light_area_disk_ray (LIGHT *light, PNT3 *point, RAY3 *ray) { FLOAT r, phi; FLOAT u, v; FLOAT rand1, rand2; FLOAT len_tmp; VEC3 v1_tmp, v2_tmp; PNT3 actualpos; rand1 = rand01(); /* Get two randoms */ rand2 = rand01(); /* Calc radius and phi in 2nd dimension */ r = (light->u.area_disk.radius) * f_sqrt(rand1); phi = 2.0 * F_PI * rand2; /* Transform from spherical coords to normal coords */ u = r * f_cos(phi); v = r * f_sin(phi); /* 2nd dim to 3rd dim on disk-lite */ v3multk(light->u.area_disk.v1, u, v1_tmp); v3multk(light->u.area_disk.v2, v, v2_tmp); v3add(v1_tmp, v2_tmp, v2_tmp); /* Calc actaul point on disk-lite */ v3add(light->position , v2_tmp, actualpos); /* Get vector from object's point to actual disk-lite-point */ v3sub( actualpos, *point, ray->direction); len_tmp = v3length(ray->direction); v3divk(ray->direction,len_tmp); return(len_tmp); } Static FLOAT light_area_triangular_ray(LIGHT *light, PNT3 *point, RAY3 *ray) { FLOAT u, v; FLOAT rand1, rand2; FLOAT dist; FLOAT tmp_len; VEC3 tempvect1, tempvect2; FLOAT a0, rayshort_t, hlp; v3sub (light->u.area_triangular.p1, *point, light->u.area_triangular.p1_); v3normalize (light->u.area_triangular.p1_); v3add (*point, light->u.area_triangular.p1_, light->u.area_triangular.p1_); v3sub (light->u.area_triangular.p2, *point, light->u.area_triangular.p2_); v3normalize (light->u.area_triangular.p2_); v3add (*point, light->u.area_triangular.p2_, light->u.area_triangular.p2_); v3sub (light->u.area_triangular.p3, *point, light->u.area_triangular.p3_); v3normalize (light->u.area_triangular.p3_); v3add (*point, light->u.area_triangular.p3_, light->u.area_triangular.p3_); rand1 = rand01(); /* Get two randoms */ rand2 = rand01(); u = 1.0 - f_sqrt (1.0 - rand1); v = rand2 * f_sqrt (1.0 - rand1); v3sub (light->u.area_triangular.p2_, light->u.area_triangular.p1_, tempvect1); v3sub (light->u.area_triangular.p3_, light->u.area_triangular.p1_, tempvect2); /* Calc normal-vector of help_triangle and store it */ v3cross (tempvect1, tempvect2, light->u.area_triangular.normal_htr); light->u.area_triangular.area = v3length(light->u.area_triangular.normal_htr) / 2.0; v3normalize(light->u.area_triangular.normal_htr); v3multk (tempvect1, u, tempvect1); v3multk (tempvect2, v, tempvect2); v3add (light->u.area_triangular.p1_, tempvect1, light->u.area_triangular.x_htr); v3add (light->u.area_triangular.x_htr, tempvect2, light->u.area_triangular.x_htr); /* Vector from *point to random point on triangle_for_help */ v3sub (light->u.area_triangular.x_htr, *point, light->u.area_triangular.psi); /* Calc right side of plane_equation */ a0 = v3dot(light->u.area_triangular.p1, light->u.area_triangular.direction); /* set in straight_line_equation into plane_equation, get factor rayshort_t which is multiplied to vector from *point to random point on triangle_for_help */ rayshort_t = (a0 - v3dot(*point, light->u.area_triangular.direction)) / v3dot (light->u.area_triangular.psi, light->u.area_triangular.direction); v3multk ( light->u.area_triangular.psi, rayshort_t, ray->direction); v3add (*point, ray->direction, light->u.area_triangular.x_light); tmp_len = v3length(ray->direction); v3divk(ray->direction, tmp_len); return tmp_len; } Static FLOAT light_area_sphere_ray(LIGHT *light, PNT3 *point, RAY3 *ray) { FLOAT theta, phi; FLOAT rand1, rand2; FLOAT tmp_len; VEC3 v1_tmp, v2_tmp; PNT3 actualpos; FLOAT dist; VEC3 psi_tmp, psi; VEC3 X, Y, Z, preX; VEC3 eo; FLOAT v, d; v3dist (*point, light->position, dist); light->u.area_sphere.phi_max = f_asin (light->u.area_sphere.radius / dist); rand1 = rand01(); /* Get two randoms */ rand2 = rand01(); /* Calc radius and phi in 2nd dimension */ theta = (f_acos(1.0 - rand1 + rand1 * f_cos(light->u.area_sphere.phi_max))); phi = 2.0 * F_PI * rand2; psi.x = f_sin(theta) * f_cos(phi); psi.y = f_sin(theta) * f_sin(phi); psi.z = f_cos(theta); /* eo: vector *point to center of sphere_light */ v3sub(light->position, *point, eo); Z = eo; v3normalize(Z); do { preX.x = rand01(); preX.y = rand01(); preX.z = rand01(); v3normalize(preX); } while ( f_iszero(f_abs(v3dot(preX, Z) - 1.0))); v3cross (Z, preX, X); v3cross (Z, X, Y); /* psi = M * psi */ psi_tmp.x = X.x * psi.x + Y.x * psi.y + Z.x * psi.z; psi_tmp.y = X.y * psi.x + Y.y * psi.y + Z.y * psi.z; psi_tmp.z = X.z * psi.x + Y.z * psi.y + Z.z * psi.z; light->u.area_sphere.psi = psi_tmp; /* Find point on sphere_light */ v3normalize(psi_tmp); v = v3dot (eo, psi_tmp); d = light->u.area_sphere.radius * light->u.area_sphere.radius - (v3dot (eo,eo) - v * v); if (d < 0.0) fatal ("Can't get an intersection sphere-light with ray, disc is %f.\n",d); d = f_sqrt(d); tmp_len = v - d; v3multk (psi_tmp, tmp_len, psi_tmp); v3add (*point, psi_tmp, light->u.area_sphere.x_light); /* Calc direction from point to point_on_light */ v3sub (light->u.area_sphere.x_light, *point, ray->direction); /* Calc normal-vector at point_on_sphere */ v3sub ( light->u.area_sphere.x_light, light->position, light->u.area_sphere.x_normal); tmp_len = v3length(ray->direction); v3divk(ray->direction, tmp_len); return tmp_len; } VOID init_lights(VOID) { lightintensity[LIGHT_UNKNOWN] = light_error; lightintensity[LIGHT_AMBIENT] = light_error; lightintensity[LIGHT_SPHERE] = sphereintensity; lightintensity[LIGHT_SPOT] = spotintensity; lightintensity[LIGHT_DISTRIBUTION] = distributionintensity; /***************************/ /* GW - CHANGE */ /***************************/ lightintensity[LIGHT_INFINITY] = no_ray_intensity; lightintensity[LIGHT_POINT] = no_ray_intensity; lightintensity[LIGHT_AREA_DISK] = diskintensity; lightintensity[LIGHT_AREA_TRIANGULAR] = triangularintensity; lightintensity[LIGHT_AREA_SPHERE] = sphereintensity; lightinit[LIGHT_UNKNOWN] = light_default_init; lightinit[LIGHT_AMBIENT] = light_default_init; lightinit[LIGHT_INFINITY] = light_default_init; lightinit[LIGHT_POINT] = light_default_init; lightinit[LIGHT_SPHERE] = light_default_init; lightinit[LIGHT_SPOT] = light_default_init; lightinit[LIGHT_DISTRIBUTION] = light_default_init; lightinit[LIGHT_AREA_DISK] = light_area_disk_init; lightinit[LIGHT_AREA_TRIANGULAR] = light_area_triangular_init; lightinit[LIGHT_AREA_SPHERE] = light_area_sphere_init; lightray[LIGHT_UNKNOWN] = light_default_ray; lightray[LIGHT_AMBIENT] = light_default_ray; lightray[LIGHT_INFINITY] = light_infinity_ray; lightray[LIGHT_POINT] = light_default_ray; lightray[LIGHT_SPHERE] = light_default_ray; lightray[LIGHT_SPOT] = light_default_ray; lightray[LIGHT_DISTRIBUTION] = light_default_ray; lightray[LIGHT_AREA_DISK] = light_area_disk_ray; lightray[LIGHT_AREA_TRIANGULAR] = light_area_triangular_ray; lightray[LIGHT_AREA_SPHERE] = light_area_sphere_ray; } _UNKNOWN] = light_default_ray; lightray[LIGHT_AMBIENT] = light_default_ray; lightray[LIGHT_INFINITY] = light_infinity_ray; lightray[LIGHT_POINT] = light_default_ray; lightray[LIGHT_SPHERE] = light_default_ray; lightray[LIGHT_SPOT] = light_default_ray; lightray[LIGHT_DISTRIBUTION] = light_default_ray; lightray[LIGHT_AREA_DISK] = light_area_disk_ray; lightray[LIGHT_AREA_TRIANGULAR] = light_area_triangular_rFlirt/light.d000644 000316 000311 00000004361 06103226560 013236 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : light.d Header file for light sources DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef LIGHT_D #define LIGHT_D #include "color.d" #include "geometr3.d" #include "flirt.d" #include "esbuf.d" #define LIGHTSAMPLES 19 /* 0..180 in steps of 10 */ typedef enum { LIGHT_UNKNOWN, LIGHT_AMBIENT, LIGHT_INFINITY, LIGHT_POINT, LIGHT_SPHERE, LIGHT_SPOT, LIGHT_DISTRIBUTION, LIGHT_AREA_DISK, LIGHT_AREA_TRIANGULAR, LIGHT_AREA_SPHERE, LAST_LIGHT } LIGHTTYP; typedef struct light { LIGHTTYP typ; PNT3 position; /* light_infinity = direction */ COLOR color; RAYBUFFER *shadow_buf[6]; struct light *next; union { struct { FLOAT radius; UINT samples; } sphere; struct { VEC3 direction; FLOAT power; FLOAT minangle; FLOAT maxangle; } spot; struct { VEC3 direction; FLOAT sample[LIGHTSAMPLES]; } distribution; struct { VEC3 direction; UINT accuracy; FLOAT radius; VEC3 v1, v2; VEC3 normal; } area_disk; struct { VEC3 direction; UINT accuracy; PNT3 p1, p2, p3; PNT3 p1_, p2_, p3_; PNT3 x_light, x_htr; VEC3 psi, normal_htr; VEC3 v1, v2; FLOAT area; VEC3 normal; } area_triangular; struct { UINT accuracy; FLOAT radius; VEC3 psi, x_normal; PNT3 x_light; FLOAT phi_max; VEC3 normal; } area_sphere; } u; } LIGHT; #endif p1, p2, p3; PNT3 p1_, p2_, p3_; PNT3 x_light, x_htr; VEC3 psi, normal_htr; VEC3 v1, v2; FLOAT area; VEC3 normal; } area_triangular; struct { Flirt/light.f000644 000316 000311 00000002237 06103226614 013240 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : light.f light handling DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef LIGHT_F #define LIGHT_F #include "light.d" typedef VOID (*LIGHTFUN_INTENSITY) PP((LIGHT *light,RAY3 *ray, FLOAT len, COLOR *color)); /****************** GW - CHANGE *********************************/ typedef UINT (*LIGHTFUN_INIT) PP((LIGHT *light)); typedef FLOAT (*LIGHTFUN_RAY) PP((LIGHT *light, PNT3 *point, RAY3 *ray)); /*****************************************************************/ Extern LIGHT *global_lights; Extern LIGHTFUN_INTENSITY lightintensity[]; /****************** GW - CHANGE *********************************/ Extern LIGHTFUN_INIT lightinit[]; Extern LIGHTFUN_RAY lightray[]; /*****************************************************************/ LIGHT *readlights PP((BOOLEAN readin)); VOID writelights PP((LIGHT *light)); VOID init_lights PP((VOID)); #endif *light, PNT3 *point, RAY3 *ray)); /*****************************************************************/ Extern LIGHT *global_lights; Extern LIGHTFUN_INTENSITY lightintensity[]; /****************** GW - CHANGE *********************************/ Extern LIGHTFUN_INIT lightinit[]; Extern LIGHTFUN_RAY lightray[]; /*************************Flirt/material.c000644 000316 000311 00000005172 06103226520 013721 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : material.c material handling DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "symbols.f" #include "readdata.f" #include "writdata.f" #include "material.f" MATERIAL *global_material; MATPAR frommatpar; MATPAR hitmatpar; MATPAR tomatpar; DEFAULTMATFUN defaultmaterial; MATNEWFUN newmaterial; MATREADFUN readmaterial; MATWRITEFUN writematerial; MATSETUPFUN setupmaterial; MATABSORBFUN absorbmaterial; MATOPAQUEFUN opaquematerial; MATINTERPOLFUN materialinterpol; MAT2SURFFUN material2surface; SURFAMBIENTFUN ambientsurface; SURFEMISSIONFUN emissionsurface; SURFDIFFFUN diffusesurface; SURFSPECFUN specularsurface; SURFINDEXFUN invindexsurface; SURFREFLECTFUN reflectsurface; SURFREFRACTFUN refractsurface; MATERIAL *readnamematerial(VOID) { MATERIAL *material; readconststring(lookupstring(CONST_DATA,DATA_MATERIAL)); material = (MATERIAL *)findname(INFO_MATERIAL,token); if (material == NULL) { material = newmaterial(); savename(INFO_MATERIAL,token,(VOIDPTR) material); } nexttoken(); return(material); } VOID writenamematerial(MATERIAL *material) { UCHAR Const *x; writestring(lookupstring(CONST_DATA,DATA_MATERIAL)); x = findinfo(INFO_MATERIAL,(VOIDPTR) material); if (x == NULL) writestring("default"); else writestring(x); writelf(); } VOID setupallmaterials(VOID) { BOOLEAN read; INFOITERATOR iterator; MATERIAL *material; material = (MATERIAL *)infoiterator(INFO_MATERIAL,&iterator,&read,NULL); while (material != NULL) { if (read) setupmaterial(material); material = (MATERIAL *)infoiterator(INFO_NEXT,&iterator,&read,NULL); } } VOID writeallmaterials(VOID) { UCHAR Const *name; BOOLEAN read; INFOITERATOR iterator; MATERIAL *material; material = (MATERIAL *)infoiterator(INFO_MATERIAL,&iterator,&read,&name); while (material != NULL) { if (read) { writestring(lookupstring(CONST_DATA,DATA_MATERIAL)); writestring(name); writelf(); writematerial(material); writelf(); } material = (MATERIAL *)infoiterator(INFO_NEXT,&iterator,&read,&name); } } ame; BOOLEAN read; INFOITERATOR iterator; MATERIAL *material; material = (MATERIAL *)infoiterator(INFO_MATERIAL,&iterator,&read,&name); while (material != NULL) { if (read) { writestring(lookupstring(CONST_DATA,DATA_MATERIAL)); writestring(name); writelf(); writematerial(material); Flirt/material.d000644 000316 000311 00000007130 06103226560 013722 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : material.d Header file for material descriptions DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef MATERIAL_D #define MATERIAL_D #include "color.d" #include "flirt.d" typedef enum { SIMPLEMATERIALS, STANDARDMATERIALS, RISSMATERIALS } MATERIALTYP; typedef UINT MATPAR; #define MATPAR_NONE 0x0000 #define MATPAR_ALL 0xffff /*-------------------------- smpl mat --------------------------------*/ typedef struct { BOOLEAN opaque; FLOAT inverse_index; FLOAT h; /* this is calculated on reading */ FLOAT smoothness; FLOAT metalness; FLOAT transparency; FLOAT refract_index; COLOR color; } SMPLMAT; #define SMPL_SMOOTHNESS 0x0001 #define SMPL_METALNESS 0x0002 #define SMPL_TRANSPARENCY 0x0004 #define SMPL_REFRACT_INDEX 0x0008 #define SMPL_COLOR 0x0010 typedef struct { FLOAT inverse_index; FLOAT h; FLOAT d; FLOAT rd; FLOAT smoothness; FLOAT metalness; FLOAT transparency; FLOAT refract_index; COLOR color; } SMPLSURF; /*-------------------------- std mat --------------------------------*/ typedef struct { BOOLEAN opaque; FLOAT inverse_index; FLOAT specpow; FLOAT reflectivity; FLOAT transparency; FLOAT translucency; FLOAT extinction; FLOAT refract_index; COLOR ambient; COLOR diffuse; COLOR specular; COLOR body; COLOR emission; } STDMAT; #define STD_SPECPOW 0x0001 #define STD_REFLECTIVITY 0x0002 #define STD_TRANSPARENCY 0x0004 #define STD_TRANSLUCENCY 0x0008 #define STD_EXTINCTION 0x0010 #define STD_REFRACT_INDEX 0x0020 #define STD_AMBIENT 0x0040 #define STD_DIFFUSE 0x0080 #define STD_SPECULAR 0x0100 #define STD_BODY 0x0200 #define STD_EMISSION 0x0400 typedef struct { FLOAT inverse_index; FLOAT specpow; FLOAT reflectivity; FLOAT transparency; FLOAT translucency; FLOAT extinction; FLOAT refract_index; COLOR ambient; COLOR diffuse; COLOR specular; COLOR body; COLOR emission; } STDSURF; /*-------------------------- riss mat --------------------------------*/ #define FACETSAMPLES 20 typedef struct { FLOAT sample[FACETSAMPLES]; } FACETS; typedef struct { BOOLEAN opaque; COLOR diffuse; FLOAT refract_index; FLOAT inverse_index; COLOR invrefract; FLOAT specular; COLOR extinction; COLOR absorption; COLOR emission; COLOR refraction; FACETS facets; } RISSMAT; #define RISS_SPECULAR 0x0001 #define RISS_ABSORPTION 0x0002 #define RISS_EMISSION 0x0004 #define RISS_FACETS 0x0008 #define RISS_DIFFUSE 0x0010 typedef struct { COLOR diffuse; FLOAT refract_index; FLOAT inverse_index; COLOR refraction_2; COLOR invrefract_2; FLOAT specular; COLOR extinction; COLOR emission; FACETS facets; } RISSSURF; typedef union { SMPLMAT smpl; STDMAT std; RISSMAT riss; } MATERIAL; typedef union { SMPLSURF smpl; STDSURF std; RISSSURF riss; } SURFACE; #endif define RISS_DIFFUSE 0x0010 typedef struct { COLOR diffuse; FLOAT refract_index; FLOAT inverse_index; COLOR refraction_2; COLOR invrefract_2; FLOAT specular; COLOR extinction; COLOR emission; FACETS facets; } RISSSURF; typedef union { SMPLMAT smpl; STDMAT std; RISSMAT riss; } MATERIAL; typedef union { SFlirt/material.f000644 000316 000311 00000005531 06103226614 013727 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : material.f material handling DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef MATERIAL_F #define MATERIAL_F #include "material.d" typedef MATERIAL * (* MATNEWFUN) PP((VOID)); typedef VOID (* DEFAULTMATFUN) PP((MATERIAL *def)); typedef VOID (* MATREADFUN) PP((MATERIAL *material)); typedef VOID (* MATWRITEFUN) PP((MATERIAL *material)); typedef VOID (* MATSETUPFUN) PP((MATERIAL *material)); typedef VOID (* MATABSORBFUN) PP((MATERIAL *material,FLOAT length, COLOR *absorption)); typedef BOOLEAN (* MATOPAQUEFUN) PP((MATERIAL *material)); typedef VOID (* MATINTERPOLFUN) PP((MATERIAL *mat1,MATERIAL *mat2, FLOAT t,MATPAR changes,MATERIAL *material)); typedef VOID (* MAT2SURFFUN) PP((MATERIAL *frommaterial,MATERIAL *material, MATERIAL *tomaterial,SURFACE *surface)); typedef VOID (* SURFEMISSIONFUN) PP((SURFACE *surface,COLOR *attenuation)); typedef VOID (* SURFAMBIENTFUN) PP((SURFACE *surface,COLOR *attenuation)); typedef VOID (* SURFDIFFFUN) PP((SURFACE *surface,FLOAT ndotl, COLOR *attenuation)); typedef VOID (* SURFSPECFUN) PP((SURFACE *surface,FLOAT ldotv,FLOAT ndotl, FLOAT ndotv,COLOR *attenuation)); typedef FLOAT (* SURFINDEXFUN) PP((SURFACE *surface)); typedef VOID (* SURFREFLECTFUN) PP((SURFACE *surface,FLOAT ndotv, FLOAT minusndott_2,COLOR *attenuation)); typedef VOID (* SURFREFRACTFUN) PP((SURFACE *surface,FLOAT ndotv, FLOAT minusndott,COLOR *attenuation)); Extern MATERIAL *global_material; Extern MATPAR frommatpar; Extern MATPAR hitmatpar; Extern MATPAR tomatpar; Extern DEFAULTMATFUN defaultmaterial; Extern MATNEWFUN newmaterial; Extern MATREADFUN readmaterial; Extern MATWRITEFUN writematerial; Extern MATSETUPFUN setupmaterial; Extern MATABSORBFUN absorbmaterial; Extern MATOPAQUEFUN opaquematerial; Extern MATINTERPOLFUN materialinterpol; Extern MAT2SURFFUN material2surface; Extern SURFEMISSIONFUN emissionsurface; Extern SURFAMBIENTFUN ambientsurface; Extern SURFDIFFFUN diffusesurface; Extern SURFSPECFUN specularsurface; Extern SURFINDEXFUN invindexsurface; Extern SURFREFLECTFUN reflectsurface; Extern SURFREFRACTFUN refractsurface; MATERIAL *readnamematerial PP((VOID)); VOID writenamematerial PP((MATERIAL *material)); VOID setupallmaterials PP((VOID)); VOID writeallmaterials PP((VOID)); #endif materialinterpol; Extern MAT2SURFFUN material2surface; Extern SURFEMISSIONFUN emissionsurface; Extern SURFAMBIENTFUN ambientsurface; Extern SURFDIFFFUN dFlirt/mcsg.c000644 000316 000311 00000022633 06103226522 013057 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : mcsg.c routines for multipe-csg-objects DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "objects.f" #include "random.f" /* for crc_random's */ #include "scene.f" /* scene_eps */ #include "readdata.f" #include "writdata.f" #include "csg.f" #include "mcsg.f" #define SAVE_CRC if (rci.do_crc) old_crc = crc_rand; #define UPDATE_CRC(x) if (rci.do_crc) crc_rand_update(x); #define RESTORE_CRC if (rci.do_crc) crc_rand = old_crc; #define SAVE_UPDATE_CRC(x) \ if (rci.do_crc) \ { \ old_crc = crc_rand; \ crc_rand_update(x); \ } #define RESTORE_UPDATE_CRC(x) \ if (rci.do_crc) \ { \ crc_rand = old_crc; \ crc_rand_update(x); \ } Static OBJECT *readmcsgor(VOID) { UINT i; OBJECT *obj; obj = newonlyvar(OBJECT,MCSGOBJ); obj->typ = MULTIPLE_OR; match_read_uint("number", obj->u.mcsg.number); obj->u.mcsg.child = (OBJECT **) newonlymem(sizeof(OBJECT *) * obj->u.mcsg.number); for (i = 0; i < obj->u.mcsg.number; i++) obj->u.mcsg.child[i] = readobjects(); return(obj); } Static OBJECT *readmcsgand(VOID) { UINT i; OBJECT *obj; obj = newonlyvar(OBJECT,MCSGOBJ); obj->typ = MULTIPLE_AND; match_read_uint("number", obj->u.mcsg.number); obj->u.mcsg.child = (OBJECT **) newonlymem(sizeof(OBJECT *) * obj->u.mcsg.number); for (i = 0; i < obj->u.mcsg.number; i++) obj->u.mcsg.child[i] = readobjects(); return(obj); } Static OBJECT *copymcsg(OBJECT *obj,BOOLEAN recurse,MAT3 *obj2world, MAT3 *world2obj,MATERIAL *mat,TEXTURE *tex) { UINT i; OBJECT *newobj; newobj = newonlyvar(OBJECT,MCSGOBJ); newobj->typ = obj->typ; newobj->u.mcsg.in_or_tree = obj->u.mcsg.in_or_tree; newobj->u.mcsg.number = obj->u.mcsg.number; newobj->u.mcsg.child = (OBJECT **) newonlymem(sizeof(OBJECT *) * obj->u.mcsg.number); for (i = 0; i < obj->u.mcsg.number; i++) { if (recurse) newobj->u.mcsg.child[i] = copyobj[obj->u.mcsg.child[i]->typ]( obj->u.mcsg.child[i],TRUE,obj2world,world2obj,mat,tex); else newobj->u.mcsg.child[i] = obj->u.mcsg.child[i]; } return(newobj); } Static VOID writemcsg(OBJECT *obj) { UINT i; write_string_uint("number", obj->u.mcsg.number); for (i = 0; i < obj->u.mcsg.number; i++) writeobjects(obj->u.mcsg.child[i]); } Static VOID boundmcsgor(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { UINT i; ULONG old_crc; OBJECT temp; SAVE_UPDATE_CRC(0); boundobj[obj->u.mcsg.child[0]->typ](obj->u.mcsg.child[0], bbox_test,bsphere_test,bounds_test,bbox,bsphere,bounds); temp = *(obj->u.mcsg.child[0]); for (i = 1; i < obj->u.mcsg.number; i++) { RESTORE_UPDATE_CRC(i); boundobj[obj->u.mcsg.child[i]->typ](obj->u.mcsg.child[i], bbox_test,bsphere_test,bounds_test,bbox,bsphere,bounds); combinecsgor(&temp,obj->u.mcsg.child[i],obj); temp = *obj; } RESTORE_CRC; /* FIXME: do boundoptimize here ! */ obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? TRUE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static VOID boundmcsgand(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { UINT i; ULONG old_crc; OBJECT temp; SAVE_UPDATE_CRC(0); boundobj[obj->u.mcsg.child[0]->typ](obj->u.mcsg.child[0], bbox_test,bsphere_test,bounds_test,bbox,bsphere,bounds); temp = *(obj->u.mcsg.child[0]); for (i = 1; i < obj->u.mcsg.number; i++) { RESTORE_UPDATE_CRC(i); boundobj[obj->u.mcsg.child[i]->typ](obj->u.mcsg.child[i], bbox_test,bsphere_test,bounds_test,bbox,bsphere,bounds); combinecsgand(&temp,obj->u.mcsg.child[i],obj); temp = *obj; } RESTORE_CRC; /* FIXME: do boundoptimize / shrinkcsg here ! */ obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? TRUE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static ULONG setupmcsg(OBJECT *obj,BOOLEAN in_or_tree,BOOLEAN space_opt) { UINT i; ULONG objcount; if (obj->typ != MULTIPLE_OR) in_or_tree = FALSE; objcount = 0L; for (i = 0; i < obj->u.mcsg.number; i++) objcount += setupobjects(obj->u.mcsg.child[i],in_or_tree,space_opt); return(objcount); } Static OBJECT *insidemcsgor(PNT3 *pnt,OBJECT *obj) { UINT i; ULONG old_crc; OBJECT *c; if (obj->test_bbox && ! insidebbox(pnt,&(obj->bbox))) return(NULL); SAVE_CRC; for (i = 0; i < obj->u.mcsg.number; i++) { UPDATE_CRC(i); c = inside[obj->u.mcsg.child[i]->typ](pnt,obj->u.mcsg.child[i]); RESTORE_CRC; if (c != NULL) return(c); } return(c); /* equivalent to return(NULL) */ } Static OBJECT *insidemcsgand(PNT3 *pnt,OBJECT *obj) { UINT i; ULONG old_crc; OBJECT *c; if (obj->test_bbox && ! insidebbox(pnt,&(obj->bbox))) return(NULL); SAVE_CRC; for (i = 0; i < obj->u.mcsg.number; i++) { UPDATE_CRC(i); c = inside[obj->u.mcsg.child[i]->typ](pnt,obj->u.mcsg.child[i]); RESTORE_CRC; if (c == NULL) return(c); /* equivalent to return(NULL) */ } return(c); } /* FIXME: could be improved a lot ! */ Static BOOLEAN hitmcsgor(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) { UINT i; ULONG old_crc; BOOLEAN ray_hit_obj; FLOAT tmin1,tmax1; HITLIST lochitlist,temphitlist; tmin1 = tmin; tmax1 = tmax; SAVE_UPDATE_CRC(0); HITOBJ(obj->u.mcsg.child[0],tmin1,tmax1,hitlist,ray_hit_obj); RESTORE_CRC; if (! ray_hit_obj && hitlist->firstobj != NULL) /* inside child[0] */ return(FALSE); for (i = 1; i < obj->u.mcsg.number; i++) { tmin1 = tmin; tmax1 = tmax; lochitlist = emptyhitlist; UPDATE_CRC(i); HITOBJ(obj->u.mcsg.child[i],tmin1,tmax1,&lochitlist,ray_hit_obj); RESTORE_CRC; if (ray_hit_obj) { temphitlist = *hitlist; orhitlists(&temphitlist,&lochitlist,hitlist); } } returnhitlist(hitlist); } /* FIXME: should be improved a lot ! */ Static BOOLEAN hitmcsgand(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) { UINT i; ULONG old_crc; BOOLEAN ray_hit_obj; FLOAT tmin1,tmax1; HITLIST lochitlist,temphitlist; tmin1 = tmin; tmax1 = tmax; SAVE_UPDATE_CRC(0); HITOBJ(obj->u.mcsg.child[0],tmin1,tmax1,hitlist,ray_hit_obj); RESTORE_CRC; if (! ray_hit_obj && hitlist->firstobj == NULL) return(FALSE); for (i = 1; i < obj->u.mcsg.number; i++) { tmin1 = tmin; tmax1 = tmax; lochitlist = emptyhitlist; UPDATE_CRC(i); HITOBJ(obj->u.mcsg.child[i],tmin1,tmax1,&lochitlist,ray_hit_obj); RESTORE_CRC; if (ray_hit_obj || lochitlist.firstobj != NULL) { temphitlist = *hitlist; andhitlists(&temphitlist,&lochitlist,hitlist); } else /* if (lochitlist.firstobj == NULL) */ { freehitlist(hitlist); return(FALSE); } } returnhitlist(hitlist); } Static VOID endmcsg(OBJECT *obj) { UINT i; for (i = 0; i < obj->u.mcsg.number; i++) endobj[obj->u.mcsg.child[i]->typ](obj->u.mcsg.child[i]); } VOID initmcsg(VOID) { nameobj[MULTIPLE_OR] = "multiple_or"; readobj[MULTIPLE_OR] = readmcsgor; copyobj[MULTIPLE_OR] = copymcsg; writeobj[MULTIPLE_OR] = writemcsg; boundobj[MULTIPLE_OR] = boundmcsgor; setupobj[MULTIPLE_OR] = setupmcsg; splitobj[MULTIPLE_OR] = split_primitiv; /* FIXME: can be done better */ inside[MULTIPLE_OR] = insidemcsgor; hitobj[MULTIPLE_OR] = hitmcsgor; endobj[MULTIPLE_OR] = endmcsg; nameobj[MULTIPLE_AND] = "multiple_and"; readobj[MULTIPLE_AND] = readmcsgand; copyobj[MULTIPLE_AND] = copymcsg; writeobj[MULTIPLE_AND] = writemcsg; boundobj[MULTIPLE_AND] = boundmcsgand; setupobj[MULTIPLE_AND] = setupmcsg; splitobj[MULTIPLE_AND] = split_primitiv; /* FIXME: can be done better */ inside[MULTIPLE_AND] = insidemcsgand; hitobj[MULTIPLE_AND] = hitmcsgand; endobj[MULTIPLE_AND] = endmcsg; } MULTIPLE_OR] = hitmcsgor; endobj[MULTIPLE_OR] = endmcsg; nameobj[MULTIPLE_AND] = "multiple_aFlirt/mcsg.f000644 000316 000311 00000000753 06103226616 013065 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : mcsg.f classification routines for multiple csg-objects DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef MCSG_F #define MCSG_F #include "objects.d" VOID initmcsg PP((VOID)); #endif hE_AND] = "multiple_aFlirt/named.c000644 000316 000311 00000002255 06103226524 013212 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : named.c routines for named csg-objects DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "objects.f" #include "readdata.f" #include "material.f" #include "texture.f" #include "named.f" Static OBJECT *readnamed(VOID) { OBJECT *obj; MAT3 to,from; MATERIAL *material; TEXTURE *texture; obj = readnameobject(); readtransform(&to,&from); if (matchconststring("material")) material = readnamematerial(); else material = NULL; if (matchconststring("texture")) texture = readnametexture(); else texture = NULL; obj = copyobj[obj->typ](obj,TRUE,&to,&from,material,texture); return(obj); } VOID initnamed(VOID) { nameobj[NAMED_OBJECT] = "named"; readobj[NAMED_OBJECT] = readnamed; } terial; TEXTURE *texture; obj = readnameobject(); readtransform(&to,&from); if (matchconststring("material")) material = readnamematerial(); else material = NULL; if (matchconststring("texture")) texture = readnametexture(); else texture = NULL; obj = copyobj[obj->typ](Flirt/named.f000644 000316 000311 00000000734 06103226616 013217 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : named.f routines for named csg-objects DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef NAMED_F #define NAMED_F #include "system.d" VOID initnamed PP((VOID)); #endif NULµ¯ «ö¨pˆ= copyobj[obj->typ](Flirt/numeric.c000644 000316 000311 00000027140 06103226524 013570 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : numeric.c numeric routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #define F_SAFETY_FACTOR ((FLOAT) 2.0) #define D_SAFETY_FACTOR 2.0 FLOAT f_eps; FLOAT f_eps_factor; DOUBLE d_eps; DOUBLE d_eps_factor; VOID init_numeric(VOID) { FLOAT y; DOUBLE b; y = 0.5; while (((FLOAT) 1.0) + y != (FLOAT) 1.0) { f_eps = y; y /= 2.0; } f_eps_factor = ((FLOAT) 1.0) + f_eps * F_SAFETY_FACTOR; b = 0.5; while (1.0 + b != 1.0) { d_eps = b; b /= 2.0; } d_eps_factor = 1.0 + d_eps * F_SAFETY_FACTOR; } UINT npol2roots(DOUBLE *pol, DOUBLE *root) { DOUBLE p_2 = pol[1] / 2.0; DOUBLE d = p_2 * p_2 - pol[0]; if (d_iszero(d)) /* one double-root ? */ return (0); else if (d < 0.0) return (0); else { if (p_2 > 0.0) /* prevent cancellation */ { root[0] = -(p_2 + sqrt(d)); root[1] = pol[0] / root[0]; /* VIETA */ } else { root[1] = sqrt(d) - p_2; root[0] = pol[0] / root[1]; /* VIETA */ } return (2); } } UINT pol2roots(DOUBLE *pol, DOUBLE *root) { if (d_iszero(pol[2])) /* linear ? */ { if (d_iszero(pol[1])) /* constant ? */ { if (d_iszero(pol[0])) return (0); else return (0); } else /* solve linear equation */ { root[0] = -pol[0] / pol[1]; return (1); } } else /* solve quadric equation */ { DOUBLE d = pol[1] * pol[1] - 4 * pol[2] * pol[0]; if (d_iszero(d)) /* one double-root ? */ return (0); else if (d < 0.0) return (0); else { if (pol[1] > 0.0) /* prevent cancellation */ { d = -(sqrt(d) + pol[1]); if (pol[2] > 0.0) { root[0] = d / (pol[2] + pol[2]); /* VIETA */ root[1] = (pol[0] + pol[0]) / d; } else { root[1] = d / (pol[2] + pol[2]); /* VIETA */ root[0] = (pol[0] + pol[0]) / d; } } else { d = sqrt(d) - pol[1]; if (pol[2] < 0.0) { root[0] = d / (pol[2] + pol[2]); /* VIETA */ root[1] = (pol[0] + pol[0]) / d; } else { root[1] = d / (pol[2] + pol[2]); /* VIETA */ root[0] = (pol[0] + pol[0]) / d; } } } } return (2); } DOUBLE npol3oneroot(DOUBLE *pol) { DOUBLE d, p, q, p_3; /* ---- polynom is normalized: x^3 + pol[2] x^2 + pol[1] x + pol[0] = 0 */ /* ------- eliminate quadric term (x = y - pol[2]/3): x^3 + p x + q = 0 */ d = pol[2] * pol[2]; p = 1.0/3.0 * (-1.0/3.0 * d + pol[1]); q = 1.0/2.0 * ((2.0/27.0 * d - 1.0/3.0 * pol[1]) * pol[2] + pol[0]); /* ---------------------------------------------- use Cardano's formula */ p_3 = p * p * p; d = q * q + p_3; if (d_iszero(d)) { if (d_iszero(q)) /* one triple solution */ return (-1.0/3.0 * pol[2]); else /* one single and one double solution */ { q = d_cbrt(-q); return (q + q - 1.0/3.0 * pol[2]); } } else if (d < 0.0) /* Casus irreducibilis: three real solutions */ { return (2.0 * d_sqrt(-p) * d_cos(1.0/3.0 * d_acos(-q / d_sqrt(-p_3))) - 1.0/3.0 * pol[2]); } else { d = d_sqrt(d); /* use d as a temporary variable */ return (d_cbrt(d - q) - d_cbrt(d + q) - 1.0/3.0 * pol[2]); } } Static VOID sort3doubles(DOUBLE *real) { if (real[0] > real[1]) { if (real[0] > real[2]) /* real[0] is biggest */ { DOUBLE help = real[2]; real[2] = real[0]; if (real[1] > help) real[0] = help; else { real[0] = real[1]; real[1] = help; } } else { DOUBLE help = real[1]; real[1] = real[0]; real[0] = help; } } else { if (real[1] > real[2]) /* real[1] is biggest */ { DOUBLE help = real[2]; real[2] = real[1]; if (real[0] > help) { real[1] = real[0]; real[0] = help; } else real[1] = help; } } } Static UINT mergedoubles(UINT n1, DOUBLE *r1, UINT n2, DOUBLE *r2, DOUBLE *real) { UINT n = 0; while (n1 > 0 && n2 > 0) { if (*r1 < *r2) { *real++ = *r1++; n1--; } else { *real++ = *r2++; n2--; } n++; } while (n1 > 0) { *real++ = *r1++; n1--; n++; } while (n2 > 0) { *real++ = *r2++; n2--; n++; } return (n); } UINT npol3roots(DOUBLE *pol, DOUBLE *root) { DOUBLE d, p, q, p_3; /* ---- polynom is normalized: x^3 + pol[2] x^2 + pol[1] x + pol[0] = 0 */ /* ------- eliminate quadric term (x = y - pol[2]/3): x^3 + p x + q = 0 */ d = pol[2] * pol[2]; p = 1.0/3.0 * (-1.0/3.0 * d + pol[1]); q = 1.0/2.0 * ((2.0/27.0 * d - 1.0/3.0 * pol[1]) * pol[2] + pol[0]); /* ---------------------------------------------- use Cardano's formula */ p_3 = p * p * p; d = q * q + p_3; if (d_iszero(d)) { if (d_iszero(q)) /* one triple solution */ { root[0] = - 1.0/3.0 * pol[2]; return (1); } else /* one single and one double solution */ { DOUBLE u; u = d_cbrt(-q); root[0] = u + u - 1.0/3.0 * pol[2]; return (1); } } else if (d < 0.0) /* Casus irreducibilis: three real solutions */ { DOUBLE phi; DOUBLE t; phi = 1.0/3.0 * d_acos(-q / d_sqrt(-p_3)); t = 2.0 * d_sqrt(-p); root[0] = t * d_cos(phi) - 1.0/3.0 * pol[2]; root[1] = - t * d_cos(phi + D_PI / 3.0) - 1.0/3.0 * pol[2]; root[2] = - t * d_cos(phi - D_PI / 3.0) - 1.0/3.0 * pol[2]; sort3doubles(root); return (3); } else { d = d_sqrt(d); /* use d as a temporary variable */ root[0] = d_cbrt(d - q) - d_cbrt(d + q) - 1.0/3.0 * pol[2]; return (1); } } UINT pol3roots(DOUBLE *pol, DOUBLE *root) { DOUBLE a, b, c, d, p, q, p_3; /* ----------------------------- normal form: x^3 + a x^2 + b x + c = 0 */ a = pol[2] / pol[3]; b = pol[1] / pol[3]; c = pol[0] / pol[3]; /* ------------ eliminate quadric term (x = y - a/3): x^3 + p x + q = 0 */ d = a * a; p = 1.0/3.0 * (-1.0/3.0 * d + b); q = 1.0/2.0 * ((2.0/27.0 * d - 1.0/3.0 * b) * a + c); /* ---------------------------------------------- use Cardano's formula */ p_3 = p * p * p; d = q * q + p_3; if (d_iszero(d)) { if (d_iszero(q)) /* one triple solution */ { root[0] = - 1.0/3.0 * a; return (1); } else /* one single and one double solution */ { DOUBLE u; u = d_cbrt(-q); root[0] = u + u - 1.0/3.0 * a; return (1); } } else if (d < 0.0) /* Casus irreducibilis: three real solutions */ { DOUBLE phi; DOUBLE t; phi = 1.0/3.0 * d_acos(-q / d_sqrt(-p_3)); t = 2.0 * d_sqrt(-p); root[0] = t * d_cos(phi) - 1.0/3.0 * a; root[1] = - t * d_cos(phi + D_PI / 3.0) - 1.0/3.0 * a; root[2] = - t * d_cos(phi - D_PI / 3.0) - 1.0/3.0 * a; sort3doubles(root); return (3); } else { d = d_sqrt(d); /* use d as a temporary variable */ root[0] = d_cbrt(d - q) - d_cbrt(d + q) - 1.0/3.0 * a; return (1); } } UINT pol4roots(DOUBLE *pol, DOUBLE *root) { DOUBLE poly[4]; DOUBLE a,b,c,d,e,p,q,r,u,v,z; UINT i,num,n1,n2; /* --------------------- normal form: x^4 + a x^3 + b x^2 + c x + d = 0 */ a = pol[3] / pol[4]; b = pol[2] / pol[4]; c = pol[1] / pol[4]; d = pol[0] / pol[4]; /* ----- eliminate cubic term (x = y - a /4): x^4 + p x^2 + q x + r = 0 */ e = a * a; p = - 3.0/8.0 * e + b; q = (1.0/8.0 * e - 1.0/2.0 * b) * a + c; r = (1.0/16.0 * b - 3.0/256.0 * e) * e - 1.0/4.0 * a * c + d; if (d_iszero(r)) { /* ------------------------ no absolute term: y (y^3 + p y + q) = 0 */ poly[0] = q; poly[1] = p; poly[2] = 0.0; poly[3] = 1.0; num = npol3roots(poly,root); for (i = num; i > 0 && root[i - 1] > 0.0; i--) root[i] = root[i - 1]; /* insert the 0.0 root */ root[i] = 0.0; num++; } else { /* ---------------------------------- solve the resolvent cubic ... */ poly[0] = 1.0/2.0 * r * p - 1.0/8.0 * q * q; poly[1] = - r; poly[2] = -1.0/2.0 * p; poly[3] = 1.0; /* ------------------------- ... and take the one real solution ... */ z = npol3oneroot(poly); /* ------------------------- ... to build two quadric equations ... */ u = z * z - r; v = 2.0 * z - p; if (d_iszero(u)) u = 0.0; else if (u > 0.0) u = d_sqrt(u); else return (0); if (d_iszero(v)) v = 0.0; else if (v > 0.0) v = d_sqrt(v); else return (0); root[0] = z - u; /* use the root field for polynom */ root[1] = (q < 0.0) ? -v : v; root[2] = 1.0; n1 = npol2roots(root,poly); /* ... and the poly field for roots */ root[0] = z + u; /* the same misuse again */ root[1] = - root[1]; n2 = npol2roots(root,poly + 2); num = mergedoubles(n1,poly,n2,poly + 2,root); } e = 1.0/4.0 * a; for (i = 0; i < num; i++) root[i] -= e; return (num); } ; /* use the root field for polynom */ root[1] = (q < 0.0) ? -v : v; root[2] = 1.0; n1 = npol2roots(root,poly); /* ... and the poly field for roots */ root[0] = z + u; /* the same misuse again */ root[1] = - root[1]; n2 = npol2roots(root,poly + 2); num = mergedoubles(n1,poly,n2,poly + 2,root); } Flirt/numeric.f000644 000316 000311 00000010265 06103226620 013570 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : numeric.f numeric routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef NUMERIC_F #define NUMERIC_F #ifndef MATH_H #include #ifndef MATH_H #define MATH_H #endif #endif #include "system.d" #define d_floor(x) floor(x) #define d_abs(x) fabs(x) #define d_sqrt(x) sqrt(x) #define d_cbrt(x) (((x) < 0.0) ? -pow(-(x),D_THIRD) : pow((x),D_THIRD)) #define d_sin(x) sin(x) #define d_cos(x) cos(x) #define d_tan(x) tan(x) #define d_asin(x) asin(x) #define d_acos(x) acos(x) #define d_atan(x) atan(x) #define d_atan2(x,y) atan2(x,y) #define d_exp(x) exp(x) #define d_log(x) log(x) #define d_pow(x,y) pow(x,y) #define d_mod(x,y) fmod(x,y) #define d_hypot(x,y) hypot(x,y) /* broken on some machines :-( */ #define f_floor(x) ((FLOAT) floor(x)) #define f_abs(x) ((FLOAT) fabs(x)) #define f_sqrt(x) ((FLOAT) sqrt(x)) #define f_cbrt(x) ((FLOAT) (((x) < 0.0) ? -pow(-(x),D_THIRD) : \ pow((x),D_THIRD))) #define f_sin(x) ((FLOAT) sin(x)) #define f_cos(x) ((FLOAT) cos(x)) #define f_tan(x) ((FLOAT) tan(x)) #define f_asin(x) ((FLOAT) asin(x)) #define f_acos(x) ((FLOAT) acos(x)) #define f_atan(x) ((FLOAT) atan(x)) #define f_atan2(x,y) ((FLOAT) atan2(x,y)) #define f_exp(x) ((FLOAT) exp(x)) #define f_log(x) ((FLOAT) log(x)) #define f_pow(x,y) ((FLOAT) pow(x,y)) #define f_mod(x,y) ((FLOAT) fmod(x,y)) #define f_hypot(x,y) ((FLOAT) hypot(x,y)) /* broken on some machines :-( */ #define D_THIRD 0.3333333333333333333 #define D_E 2.7182818284590452353 #define D_PI 3.1415926535897932384 #define D_2PI 6.2831853071795864769 #define D_PI_HALF 1.5707963267948966192 #define D_SQRT2 1.4142135623730950488 #define D_SQRT3 1.7320508075688772935 #define D_DEG2RAD 0.0174532925199432958 #define D_RAD2DEG 57.295779513082320876 #define D_SMALL 1.0E-150 #define D_HUGE 1.0E+150 #define F_THIRD ((FLOAT) D_THIRD) #define F_E ((FLOAT) D_E) #define F_PI ((FLOAT) D_PI) #define F_2PI ((FLOAT) D_2PI) #define F_PI_HALF ((FLOAT) D_PI_HALF) #define F_SQRT2 ((FLOAT) D_SQRT2) #define F_SQRT3 ((FLOAT) D_SQRT3) #define F_DEG2RAD ((FLOAT) D_DEG2RAD) #define F_RAD2DEG ((FLOAT) D_RAD2DEG) #define F_SMALL ((FLOAT) 1.0E-16) #define F_HUGE ((FLOAT) 1.0E+16) #define d_round(x) floor((x) + 0.5) #define f_round(x) floor((x) + (FLOAT) 0.5) #define d_iszero(x) (d_abs(x) < D_SMALL) #define f_iszero(x) (f_abs(x) < F_SMALL) #define mini(x,y) ((x) < (y) ? (x) : (y)) #define maxi(x,y) ((x) > (y) ? (x) : (y)) #define abso(x) ((x) < 0 ? -(x) : (x)) #define sign(x) ((x) < 0 ? -1 : (x) > 0 ? 1 : 0) #define sqr(x) ((x) * (x)) #define interpol(l,h,t) ((l) + ((h) - (l)) * (t)) /* ------------------------------------------------------------------------ the following four macros can be used to scales values 'val' in the range [0..a] into the range [0..b], with rounding or truncating ------------------------------------------------------------------------ */ #define lroundscale(a,b,val) ((2L * ((ULONG)(val)) * (b) + (a)) / (2L * (a))) #define ltruncscale(a,b,val) (((ULONG)(val)) * (b) / (a)) #define iroundscale(a,b,val) ((UINT)lroundscale(a,b,val)) #define itruncscale(a,b,val) ((UINT)ltruncscale(a,b,val)) Extern FLOAT f_eps; Extern FLOAT f_eps_factor; Extern DOUBLE d_eps; Extern DOUBLE d_eps_factor; /* all following routines return sorted roots, but double-roots are skipped */ VOID init_numeric PP((VOID)); UINT npol2roots PP((DOUBLE *pol, DOUBLE *root)); UINT pol2roots PP((DOUBLE *pol, DOUBLE *root)); DOUBLE npol3oneroot PP((DOUBLE *pol)); UINT npol3roots PP((DOUBLE *pol, DOUBLE *root)); UINT pol3roots PP((DOUBLE *pol, DOUBLE *root)); UINT pol4roots PP((DOUBLE *pol, DOUBLE *root)); #endif ale(a,b,val)) Extern FLOAT f_eps; Extern FLOAT f_eps_factor; Extern DOUBLE d_eps; Extern DOUBLE d_eps_factor; /* all following routines return sorted roots, but double-roots are skipped */ VOID init_numeric PP((VOID)); UINT npol2roots PP((DOUBLE *pol, DOUBLE *root)); UINT pol2roots PP((DOUBLE *pol, DOUBLE *root)); DOUBLE npol3Flirt/objects.c000644 000316 000311 00000025361 06114641116 013562 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : objects.c classification routines for csg-objects lots of FUN in here ! DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version 260793 MS planes added, readobjects reads transformations and materials *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "raycount.f" #include "material.f" #include "texture.f" #include "readdata.f" #include "symbols.f" #include "writdata.f" #include "scene.f" /* scene_eps */ #include "objects.f" RAYCASTINFO rci; UCHAR Const *nameobj[LAST_OBJECT] = { "" }; ULONG surfaces[LAST_OBJECT]; ULONG raysobj[LAST_OBJECT]; Static ULONG numberobj[LAST_OBJECT]; READFUN readobj[LAST_OBJECT]; COPYFUN copyobj[LAST_OBJECT]; WRITEFUN writeobj[LAST_OBJECT]; BOUNDFUN boundobj[LAST_OBJECT]; SETUPFUN setupobj[LAST_OBJECT]; SPLITFUN splitobj[LAST_OBJECT]; INSIDEFUN inside[LAST_OBJECT]; HITFUN hitobj[LAST_OBJECT]; NORMALFUN normalvec[LAST_OBJECT]; PNTNORMFUN pntnormvec[LAST_OBJECT]; HITCOORDFUN hitcoord[LAST_OBJECT]; PNTCOORDFUN pntcoord[LAST_OBJECT]; ENDFUN endobj[LAST_OBJECT]; EXITFUN exitobj[LAST_OBJECT]; OBJECT *global_object; /*lint -e715 not referenced */ Static OBJECT *read_error(VOID) { fatal("read_error called"); return(NULL); } Static OBJECT *copy_error(OBJECT *obj,BOOLEAN recurse, MAT3 *obj2world,MAT3 *world2obj, MATERIAL *mat,TEXTURE *tex) { fatal("copy_error called"); return(NULL); } Static VOID write_error(OBJECT *obj) { fatal("write_error called"); } Static VOID bound_error(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { fatal("bound_error called"); } Static ULONG setup_error(OBJECT *obj,BOOLEAN in_or_tree,BOOLEAN space_opt) { fatal("setup_error called"); return(0L); } Static OBJECT *split_error(OBJECT *obj,VOIDPTR bound_volume, BVTESTFUN bv_test,BOOLEAN *changed,ULONG *number_of_objects) { fatal("split_error called"); return(NULL); } Static OBJECT *inside_error(PNT3 *pnt,OBJECT *obj) { fatal("inside_error called"); return(NULL); } Static BOOLEAN hitobj_error(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) { fatal("hitobj_error called"); return(FALSE); } Static VOID normal_error(HITINFO *hit) { message("normal_error: obj: %s",nameobj[hit->obj->typ]); fatal("normal_error called"); } Static VOID pntnorm_error(OBJECT *obj,ULONG surface,PNT2 *point, PNT3 *world,VEC3 *normal) { fatal("pntnorm_error called"); } Static VOID hitcoord_error(HITINFO *hit,GEOMPAR needed) { fatal("hitcoord_error called"); } Static BOOLEAN pntcoord_error(OBJECT *obj,GEOMPAR needed) { fatal("pntcoord_error called"); return(FALSE); } Static VOID end_error(OBJECT *obj) { fatal("end_error called"); } Static VOID exit_error(VOID) { fatal("exit_error called"); } /*--------------------------------------------------------------------------*/ Static UCHAR Const *emptystring = ""; VOID initobjects(VOID) { UINT i; for (i = UNKNOWN_OBJECT; i < LAST_OBJECT; i++) { nameobj[i] = emptystring; surfaces[i] = 0L; raysobj[i] = 0L; numberobj[i] = 0L; readobj[i] = read_error; copyobj[i] = copy_error; writeobj[i] = write_error; boundobj[i] = bound_error; setupobj[i] = setup_error; splitobj[i] = split_error; inside[i] = inside_error; hitobj[i] = hitobj_error; normalvec[i] = normal_error; pntnormvec[i] = pntnorm_error; hitcoord[i] = hitcoord_error; pntcoord[i] = pntcoord_error; endobj[i] = end_error; exitobj[i] = exit_error; } } OBJECT *readobjects(VOID) { OBJTYP typ; OBJECT *obj; readconststring("typ"); typ = readnameconst(CONST_OBJECT,FALSE); if (typ == NOCONST) obj = readobj[COMPATIBILITY](); /* fatal("line %d: unknown objecttyp '%s'",linenumber,token); */ else obj = readobj[typ](); return(obj); } OBJECT *readnameobject(VOID) { OBJECT *object; readconststring(lookupstring(CONST_DATA,DATA_OBJECT)); object = (OBJECT *)findname(INFO_OBJECT,token); if (object == NULL) fatal("line %d: unknown %s '%s'",linenumber, lookupstring(CONST_DATA,DATA_OBJECT),token); nexttoken(); return(object); } OBJECT *copysobj(OBJECT *obj,BOOLEAN recurse,MAT3 *to,MAT3 *fr, MATERIAL *mat,TEXTURE *tex) { OBJECT *newobj; newobj = newonlyvar(OBJECT,SIMPLEOBJ); newobj->typ = obj->typ; newobj->u.obj = obj->u.obj; if (mat != NULL) newobj->u.obj.material = mat; if (tex != NULL) newobj->u.obj.texture = tex; if (to != NULL && fr != NULL) { MAT3 m; m3mmulm(obj->u.obj.obj2world,*to,m); newobj->u.obj.obj2world = m; m3mmulm(*fr,obj->u.obj.world2obj,m); newobj->u.obj.world2obj = m; } return(newobj); } OBJECT *copypobj(OBJECT *obj,BOOLEAN recurse,MAT3 *to,MAT3 *fr, MATERIAL *mat,TEXTURE *tex) { OBJECT *newobj; newobj = newonlyvar(OBJECT,PAROBJ); newobj->typ = obj->typ; newobj->u.parobj = obj->u.parobj; if (mat != NULL) newobj->u.parobj.material = mat; if (tex != NULL) newobj->u.obj.texture = tex; if (to != NULL && fr != NULL) { MAT3 m,m1; m1 = obj->u.parobj.obj2world; m3mmulm(m1,*to,m); /* silly lint */ newobj->u.parobj.obj2world = m; m1 = obj->u.parobj.world2obj; m3mmulm(*fr,m1,m); /* silly lint */ newobj->u.parobj.world2obj = m; } return(newobj); } VOID writeobjects(OBJECT *obj) { writestring("typ"); writestring(nameobj[obj->typ]); writelf(); writeobj[obj->typ](obj); } VOID writesobj(OBJECT *obj) { writetransform(&(obj->u.obj.obj2world),&(obj->u.obj.world2obj)); writenamematerial(obj->u.obj.material); writenametexture(obj->u.obj.texture); } VOID writepobj(OBJECT *obj) { write_string_real("radius",obj->u.parobj.floatpar); writetransform(&(obj->u.obj.obj2world),&(obj->u.obj.world2obj)); writenamematerial(obj->u.obj.material); writenametexture(obj->u.obj.texture); } ULONG setupobjects(OBJECT *obj,BOOLEAN in_or_tree,BOOLEAN space_opt) { ULONG objcount; obj->rayno = 0; /* for space_optimizations */ if (space_opt && surfaces[obj->typ] != 0L) /* optim && a real object */ { obj->hitlist = newonlytyp(HITLIST); /* like grid/octree/... */ *(obj->hitlist) = emptyhitlist; } else obj->hitlist = NULL; v3subfrom(obj->bbox.min,V3SCENE_EPS); v3addto(obj->bbox.max,V3SCENE_EPS); obj->bsphere.radius_2 = f_sqrt(obj->bsphere.radius_2) + scene_eps; obj->bsphere.radius_2 *= obj->bsphere.radius_2; objcount = setupobj[obj->typ](obj,in_or_tree,space_opt); numberobj[obj->typ]++; return(objcount); } ULONG setup_primitiv(OBJECT *obj,BOOLEAN in_or_tree,BOOLEAN space_opt) { return(1L); } OBJECT *split_primitiv(OBJECT *obj,VOIDPTR bound_volume, BVTESTFUN bv_test,BOOLEAN *changed,ULONG *number_of_objects) { if (bv_test(obj,bound_volume) == 0) /* no intersection */ { *changed = TRUE; *number_of_objects = 0L; return(NULL); } *changed = FALSE; *number_of_objects = 1L; return(obj); } VOID endobjects(VOID) { endobj[global_object->typ](global_object); } VOID end_primitiv(OBJECT *obj) { /* does nothing */ } VOID exitobjects(VOID) { UINT i; for (i = UNKNOWN_OBJECT; i < LAST_OBJECT; i++) { if (numberobj[i] != 0L) { message(" %8ld %-20s : %8ld intersections\n",numberobj[i], nameobj[i],raysobj[i]); } if (exitobj[i] != exit_error) exitobj[i](); } } /*--------------------------------------------------------------------------*/ BOOLEAN raycast(RAY3 *ray,FLOAT tmin,FLOAT tmax,OBJECT *fromobj, BOOLEAN primary,BOOLEAN shadow,LIGHT *light,HITLIST *hitlist) { BOOLEAN ray_hit_obj; HITINFO *hit,*end; rays.number++; rci.ray = *ray; rci.primary = primary; rci.shadow = shadow; rci.shadow_light = light; rci.save_hitlist = 0; rci.rayno = rays.number; rci.do_crc = FALSE; *hitlist = emptyhitlist; HITOBJ(global_object,tmin,tmax,hitlist,ray_hit_obj); if (! ray_hit_obj) return(FALSE); hit = hitlist->first; if (hitlist->firstobj != fromobj) { do { end = hit; hit = end->next; } while (hit != NULL && end->t < hit_eps && end->newobj != fromobj); if (end->newobj != fromobj) /* no plausible ersatz hit found, */ return(TRUE); /* thus: garbage in, garbage out */ if (hit != NULL) { end->next = NULL; freelist(hitlist->first,end); hitlist->first = hit; } else freehitlist(hitlist); } else { if (hit->t < hit_eps) { hit = hit->next; while (hit != NULL && hit->t < hit_eps) { if (hit->newobj != fromobj) hit = hit->next; else { end = hit; hit = end->next; if (hit != NULL) { end->next = NULL; freelist(hitlist->first,end); hitlist->first = hit; break; } else freehitlist(hitlist); } } } } returnhitlist(hitlist); } { end = hit; hit = end->next; if (hit != NULL) { end->next = NULL; freelist(hitlist->first,end); hitlist-Flirt/objects.d000644 000316 000311 00000017442 06114640712 013565 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : objects.d all the types needed for objects DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef OBJECTS_D #define OBJECTS_D #include "geometr3.d" #include "bounding.d" #include "texture.d" #include "fived.d" #include "flirt.d" #include "plane.d" #include "esbuf.d" #include "light.d" #include "octree.d" typedef enum { UNKNOWN_OBJECT, CSG_OR, CSG_AND, CSG_SUB, MULTIPLE_OR, MULTIPLE_AND, /* not implemented yet */ MULTIPLE_SUB, /* not implemented yet */ NAMED_OBJECT, REPEATED_OBJECT, /* not functional */ GRID, OCTREE, CYLCUBE, FIVED_TREE, EYE_SHADOW_BUFFER, SELECT_NODE, DUMMY_NODE, CALCULATE_NODE, TRANSFORM_NODE, TEXTURE_NODE, SIMPLE_CUBE, SIMPLE_SPHERE, SIMPLE_TRANSFORM, CUBE, SPHERE, CYLINDER, CONE, PARABOLOID, PARABOLASWEEP, HYPERBOLOID, HYPERBOLASWEEP, TORUS, HYPERELLIPSOID, /* to be killed */ HYPERTORUS, /* to be killed */ PLANE_OBJECT, HEIGHTFIELD, TRIANGLE_PATCH, POLYGON_PATCH, /* not implemented yet */ EPIPED_TREE, FORMULA_OBJECT, TRANSLATIONAL_SWEEP, /* not implemented yet */ CONICAL_SWEEP, ROTATIONAL_SWEEP, /* not implemented yet */ SPHERE_SWEEP, /* not implemented yet */ COMPATIBILITY, /* switch to new objects */ LAST_OBJECT } OBJTYP; /*--------------------------------------------------------------------------- The parts of the object which are used in a union have to be defined as types in order to allow simple allocation of a union type without loosing to much memory. ---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* 'SPECIAL' OBJECTS */ /*---------------------------------------------------------------------------*/ typedef struct combinedobj { BOOLEAN in_or_tree; struct object *left; struct object *right; } CSGOBJ; typedef struct multipleobj { BOOLEAN in_or_tree; UINT number; struct object **child; } MCSGOBJ; typedef struct repeatedobj { UINT number; BYTE hiboundmask; BYTE loboundmask; VEC3 *vec; struct object *original; } REPEATEDOBJ; typedef struct gridobj { INTPNT3 dim; VEC3 el_len; /* element length */ BOOLEAN optimize; struct object *original; struct object **grid; } GRIDOBJ; typedef struct octreeobj { UINT max_level; /* Anzahl der Unterteilungsebenen */ UINT max_num_pro_node; /* Anzahl der Objekte pro Node */ BOOLEAN optimize; struct object *original; OCTREENODE *octree; } OCTREEOBJ; typedef struct cylcubeobj { UINT subdivisions; ULONG num_squares; struct object *original; struct object **cylcube; } CYLCUBEOBJ; typedef struct fivedobj { UINT max_level; /* Anzahl der Unterteilungsebenen */ UINT max_num_pro_node; /* Anzahl der Objekte pro Node */ BOOLEAN optimize; /* Optimierung */ struct object *original; /* Originaler Objektbaum */ FIVEDNODE *wurzel[6]; /* 6 Teil-Baeume */ } FIVEDOBJ; typedef struct eyebufobj { UINT eye_dim_x; UINT eye_dim_y; UINT shadow_dim_x; UINT shadow_dim_y; RAYBUFFER *eye_buf; struct object *original; } ESBUFOBJ; typedef struct compatbility { struct object *nextobj; } COMPATIBILITYOBJ; /*---------------------------------------------------------------------------*/ /* 'REAL' OBJECTS */ /*---------------------------------------------------------------------------*/ /* the following objects must!! have the entry PRIMITIVDATA in first pos */ #define PRIMITIVDATA \ MATERIAL *material; \ TEXTURE *texture typedef struct scubeobj { PRIMITIVDATA; TURNINFO turninfo; BOX3 box; } SCUBEOBJ; typedef struct ssphereobj { PRIMITIVDATA; TURNINFO turninfo; SPHERE3 sphere; } SSPHEREOBJ; typedef struct simpleobj { PRIMITIVDATA; MAT3 obj2world; MAT3 world2obj; } SIMPLEOBJ; typedef struct parobj { PRIMITIVDATA; MAT3 obj2world; MAT3 world2obj; FLOAT floatpar; } PAROBJ; typedef struct hyperellobj { PRIMITIVDATA; MAT3 obj2world; MAT3 world2obj; VEC3 order; } HYPERELLOBJ; typedef struct planeobj { PRIMITIVDATA; POINTARRAY *points; UINT number; UINT doublenum; PLANEENTRY *plane; } PLANEOBJ; typedef struct triangleobj { PRIMITIVDATA; BOOLEAN phong; BYTE dominant_axis; PNT3 point[3]; VEC3 edge[3]; VEC3 normal; VEC3 pointnormal[3]; FLOAT ndotp; } TRIANGLEOBJ; /*---------------------------------------------------------------------------*/ /* OBJECT */ /*---------------------------------------------------------------------------*/ typedef struct object { OBJTYP typ; /* what is it ? */ BYTE test_bbox; /* bounding volume definition */ BOOLEAN test_bsphere; BOX3 bbox; SPHERE3 bsphere; BOUNDLIST *bounds; ULONG rayno; /* for space optimisations: */ struct hitlist *hitlist; /* current rayno, copied hitlist */ struct methodtable *methods; /* this and bbox for new object */ union { CSGOBJ csg; MCSGOBJ mcsg; REPEATEDOBJ repeated; GRIDOBJ grid; OCTREEOBJ octree; CYLCUBEOBJ cylcube; FIVEDOBJ fived; ESBUFOBJ esbuffer; SCUBEOBJ scube; SSPHEREOBJ ssphere; SIMPLEOBJ obj; PAROBJ parobj; HYPERELLOBJ hyperell; PLANEOBJ plane; TRIANGLEOBJ triangle; COMPATIBILITYOBJ compatibility; } u; } OBJECT; typedef struct raycastinfo { RAY3 ray; /* actual ray */ ULONG rayno; /* number of actual ray */ ULONG save_hitlist; /* > 0 if in a grid/octree/... */ BOOLEAN do_crc; /* do the crc for random selects */ BOOLEAN primary; /* true for a primary (eye) ray */ BOOLEAN shadow; /* true for a shadow ray */ LIGHT *shadow_light; /* light source for shadow rays */ /*struct mat_tree *back_trafo; /* backtransfo-chain for nv */ FLOAT *attributes; /* var's for calculations */ } RAYCASTINFO; #endif st; /* > 0 if in a grid/octree/... */ BOOLEAN do_crc; /* do the crc for random selects */ BOOLEAN primary; /* true for a primary (eye) ray */ BOOLEAN shadow;Flirt/objects.f000644 000316 000311 00000015147 06114641373 013573 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : objects.f methods for each object DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version 260793 MS planefun added *****************************************************************************/ #ifndef OBJECTS_F #define OBJECTS_F #include "system.f" #include "hitlist.f" #include "objects.d" typedef UINT (*BVTESTFUN) PP((OBJECT *obj,VOIDPTR bound_volume)); /* no entry for the initfunctions, called once per module */ /* how to get paramters,... from file */ typedef OBJECT * (*READFUN) PP((VOID)); /* duplicate (in the dark) */ typedef OBJECT * (*COPYFUN) PP((OBJECT *obj,BOOLEAN recurse, MAT3 *obj2world,MAT3 *world2obj, MATERIAL *mat,TEXTURE *tex)); /* output the parameters with write...() */ typedef VOID (*WRITEFUN) PP((OBJECT *obj)); /* tight bounds pretty please */ typedef VOID (*BOUNDFUN) PP((OBJECT *obj,BOOLEAN bbox_test, BOOLEAN bsphere_test,BOOLEAN bounds_test, BOX3 *bbox, SPHERE3 *bsphere,BOUNDLIST *bounds)); /* additional setup's per object */ typedef ULONG (*SETUPFUN) PP((OBJECT *obj,BOOLEAN in_or_tree, BOOLEAN space_opt)); /* test a node against a bounding volume optionally splitting it */ typedef OBJECT * (*SPLITFUN) PP((OBJECT *obj,VOIDPTR bound_volume, BVTESTFUN bv_test,BOOLEAN *changed,ULONG *number_of_objects)); /* where am i */ typedef OBJECT * (*INSIDEFUN) PP((PNT3 *pnt, OBJECT *obj)); /* shoot a ray at a poor object */ typedef BOOLEAN (*HITFUN) PP((FLOAT min, FLOAT max,OBJECT *obj, HITLIST *hitlist)); /* wanna know the normal of a hit */ typedef VOID (*NORMALFUN) PP((HITINFO *hitinfo)); /* get the normal of pnt on the surface */ typedef VOID (*PNTNORMFUN) PP((OBJECT *obj,ULONG surface,PNT2 *point, PNT3 *world,VEC3 *normal)); /* wanna know the coords of a hit */ typedef VOID (*HITCOORDFUN) PP((HITINFO *hit,GEOMPAR needed)); /* fake the coords of a point */ typedef BOOLEAN (*PNTCOORDFUN) PP((OBJECT *obj,GEOMPAR needed)); /* end the whole stuff, once per object */ typedef VOID (*ENDFUN) PP((OBJECT *obj)); /* end the whole stuff, once per Module */ typedef VOID (*EXITFUN) PP((VOID)); Extern RAYCASTINFO rci; Extern UCHAR Const *nameobj[LAST_OBJECT]; Extern ULONG surfaces[LAST_OBJECT]; Extern ULONG raysobj[LAST_OBJECT]; Extern READFUN readobj[LAST_OBJECT]; Extern COPYFUN copyobj[LAST_OBJECT]; Extern WRITEFUN writeobj[LAST_OBJECT]; Extern BOUNDFUN boundobj[LAST_OBJECT]; Extern SETUPFUN setupobj[LAST_OBJECT]; Extern SPLITFUN splitobj[LAST_OBJECT]; Extern INSIDEFUN inside[LAST_OBJECT]; Extern HITFUN hitobj[LAST_OBJECT]; Extern NORMALFUN normalvec[LAST_OBJECT]; Extern PNTNORMFUN pntnormvec[LAST_OBJECT]; Extern HITCOORDFUN hitcoord[LAST_OBJECT]; Extern PNTCOORDFUN pntcoord[LAST_OBJECT]; Extern ENDFUN endobj[LAST_OBJECT]; Extern EXITFUN exitobj[LAST_OBJECT]; Extern OBJECT *global_object; VOID initobjects PP((VOID)); OBJECT *readobjects PP((VOID)); OBJECT *readnameobject PP((VOID)); OBJECT *copysobj PP((OBJECT *obj,BOOLEAN recurse,MAT3 *obj2world, MAT3 *world2obj,MATERIAL *mat,TEXTURE *tex)); OBJECT *copypobj PP((OBJECT *obj,BOOLEAN recurse,MAT3 *obj2world, MAT3 *world2obj,MATERIAL *mat,TEXTURE *tex)); VOID writeobjects PP((OBJECT *)); VOID writesobj PP((OBJECT *)); VOID writepobj PP((OBJECT *)); ULONG setupobjects PP((OBJECT *obj,BOOLEAN in_or_tree,BOOLEAN space_opt)); ULONG setup_primitiv PP((OBJECT *obj,BOOLEAN in_or_tree,BOOLEAN space_opt)); OBJECT *split_primitiv PP((OBJECT *obj,VOIDPTR bound_volume, BVTESTFUN bv_test,BOOLEAN *changed,ULONG *number_of_objects)); VOID endobjects PP((VOID)); VOID end_primitiv PP((OBJECT *obj)); VOID exitobjects PP((VOID)); BOOLEAN raycast PP((RAY3 *ray,FLOAT tmin,FLOAT tmax,OBJECT *fromobj, BOOLEAN primary,BOOLEAN shadow,LIGHT *light, HITLIST *hitlist)); #define HITBOUNDSONLY(obj,tmin,tmax,ray_hit_obj) \ { \ ray_hit_obj = (BOOLEAN) HIT_BOUNDS(obj,rci.ray,tmin,tmax); \ } #define HITOBJONLY(obj,tmin,tmax,hitlst,ray_hit_obj) \ { \ ray_hit_obj = hitobj[(obj)->typ](tmin,tmax,obj,hitlst); \ raysobj[(obj)->typ]++; \ } #define HITOBJ(obj,tmin,tmax,hitlst,ray_hit_obj) \ { \ ray_hit_obj = (BOOLEAN) HIT_BOUNDS(obj,rci.ray,tmin,tmax); \ if (ray_hit_obj) \ { \ ray_hit_obj = hitobj[(obj)->typ](tmin,tmax,obj,hitlst); \ raysobj[(obj)->typ]++; \ } \ } #define PRE_OBJECT(obj,hitlst) \ { \ if (rci.save_hitlist && (obj)->hitlist != NULL) \ { \ if (rci.rayno == (obj)->rayno) \ { \ copyhitlist((obj)->hitlist,hitlst,TRUE); \ returnhitlist(hitlst); \ } \ (obj)->rayno = rci.rayno; \ (obj)->hitlist->first = NULL; \ } \ } #define POST_OBJECT(obj,hitlst) \ { \ if (rci.save_hitlist && obj->hitlist != NULL) \ copyhitlist(hitlst,obj->hitlist,FALSE); \ } #endif ayno; \ (obj)->hitlist->first = NULL; \ } \ } #define POST_OBJECT(obj,hitlst) \ { \ if (rci.save_hitlist && obj->hitlist != NULL) Flirt/octree.c000644 000316 000311 00000051362 06103226526 013414 0ustar00wrzlgup000000 000000 /******************************************************************* PROJECT : flirt MODULE : octree.c octree manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 150393 rweber first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "objects.f" #include "csg.f" #include "readdata.f" #include "writdata.f" #include "scene.f" /* scene_eps */ #include "octree.f" /* Globale Varibalen */ BYTE entry_octant; UINT max_lev; UINT max_num; UINT count; OBJECT *original; Static OBJECT *readoctree(VOID) { ULONG size; OBJECT *obj; obj = newonlyvar(OBJECT,OCTREEOBJ); obj->typ = OCTREE; readconststring("maximumlevel"); obj->u.octree.max_level = (INT) readuint(); readconststring("maximumpronode"); obj->u.octree.max_num_pro_node = (INT) readuint(); /* message("maximumlevel: %d\n",obj->u.octree.max_level); message("maximumpronode: %d\n",obj->u.octree.max_num_pro_node); */ option_read_bool("optimisation", obj->u.octree.optimize,FALSE); obj->u.octree.original = readobjects(); size = (ULONG)sizeof(OCTREENODE); obj->u.octree.octree = (OCTREENODE *)newonlymem(size); return(obj); } Static OBJECT *copyoctree(OBJECT *obj,BOOLEAN recurse,MAT3 *to,MAT3 *fr, MATERIAL *mat,TEXTURE *tex) { ULONG size; OBJECT *newobj; message("copyoctree\n"); newobj = newonlyvar(OBJECT,OCTREE); /* $$$$ Warum hier anders?? */ newobj->typ = obj->typ; newobj->u.octree = obj->u.octree; size = (ULONG)sizeof(OCTREENODE); newobj->u.octree.octree = (OCTREENODE *)newonlymem(size); if (recurse) newobj->u.octree.original = copyobj[obj->u.octree.original->typ](obj->u.octree.original,TRUE, to,fr,mat,tex); else newobj->u.octree.original = obj->u.octree.original; return(newobj); } Static VOID writeoctree(OBJECT *obj) { writestring("maximumlevel"); writeuint(obj->u.octree.max_level); writestring("maximumpronode"); writeuint(obj->u.octree.max_num_pro_node); writelf(); write_string_bool("optimisation",obj->u.octree.optimize); writeobjects(obj->u.octree.original); } Static VOID boundoctree(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { boundobj[obj->u.octree.original->typ](obj->u.octree.original,bbox_test, bsphere_test,bounds_test,bbox,bsphere,bounds); obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_ALL; obj->test_bsphere = (bsphere_test) ? FALSE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; obj->bbox = obj->u.octree.original->bbox; obj->bsphere = obj->u.octree.original->bsphere; *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static UINT bbox_test(OBJECT *obj,VOIDPTR bound_volume) { PNT3 pmin,pmax; BOX3 *box; box = (BOX3 *) bound_volume; v3pmax(obj->bbox.min,box->min,pmin); v3pmin(obj->bbox.max,box->max,pmax); if (pmin.x <= pmax.x && pmin.y <= pmax.y && pmin.z <= pmax.z) { if (obj->bbox.min.x >= box->min.x && obj->bbox.min.y >= box->min.y && obj->bbox.min.z >= box->min.z && obj->bbox.max.x <= box->max.x && obj->bbox.max.y <= box->max.y && obj->bbox.max.z <= box->max.z) return(2); /* totally inside */ return(1); /* boxes intersect */ } return(0); /* no intersection */ } #ifdef NEVER /* Debugging */ Static VOID box_aus(BOX3 *bbox) { message(" bbox %f %f %f\n %f %f %f\n", bbox->min.x,bbox->min.y,bbox->min.z, bbox->max.x,bbox->max.y,bbox->max.z); } /*Static VOID p(PNT3 *p) { message(" punkt %f %f %f\n",p->x,p->y,p->z); } Static VOID i(INT i) { message(" int %d\n",i); } Static VOID f(FLOAT f) { message(" float %f\n",f); } */ Static VOID octreeaus(OCTREENODE *o, ULONG index, int level) { int i; message("----------\n"); message("index (calc) %d\n",index); /* message("level %d\n",level); */ if (o != NULL) { message("index (mem) %d\n",o->index); /* message("octreenode != null\n"); message(" childbox\n"); b = o->bbox; box_aus(&b); */ if (o->blatt==TRUE) message("blatt\n"); if (o->objects==NULL) { message("keine objekte!!\n");} else { message(" objekte\n"); /* message(" objektbox\n"); b = o->objects->bbox; box_aus(&b); */ } if ((o->children) != NULL) { message(" children !\n"); for(i=0;i<8;i++) { octreeaus(o->children[i],index*10+i+1,level+1); } } else message(" keine children\n"); } else message(" node leer\n"); } #endif Static VOID nodedivide(OCTREENODE *node,UINT level, FLOAT box_len) /* node Zeiger auf zu unterteilenden Octreenode level Ebene von Node box_len Laenge der bbox der Childnodes */ { ULONG size; INT i; BOX3 bbox; BOX3 kindbbox; PNT3 midpoint; OBJECT *obj; OCTREENODE **kind; BOOLEAN changed; ULONG num_obj; /* MAT3 *to = NULL; MAT3 *fr = NULL; MATERIAL *mat = NULL; TEXTURE *tex = NULL; */ /* Rekursion zum Octreeaufbau. Wird aufgerufen, wenn in Node mehr Objects liegen als max_num_pro_node und wenn level kleiner als max_level ist. */ /* message("nodedivide, level %d\n", level); */ node->blatt = FALSE; size = 8*(ULONG)sizeof(OCTREENODE *); /* 8 Pointer auf Octreenode */ node->children = (OCTREENODE **)newonlymem(size); bbox = node->bbox; /* box_aus(&bbox); */ midpoint.x = node->bbox.min.x + box_len; midpoint.y = node->bbox.min.y + box_len; midpoint.z = node->bbox.min.z + box_len; /* message(" midpoint %f %f %f\n",midpoint.x,midpoint.y,midpoint.z); */ /* Bereich des Childknotens ermitteln */ kind = node->children; for (i=0; i<8; i++) { kindbbox = bbox; if (i % 2) kindbbox.min.x = midpoint.x; else kindbbox.max.x = midpoint.x; if ((i>>1) % 2) kindbbox.min.y = midpoint.y; else kindbbox.max.y = midpoint.y; if (i > 3 ) kindbbox.min.z = midpoint.z; else kindbbox.max.z = midpoint.z; /* message(" i = %d\n",i); box_aus(&kindbbox); */ changed = TRUE; /* split them */ /* brauch ma des no ? if (i != 7) { obj = copyobj[node->objects->typ](node->objects,TRUE, to,fr,mat,tex); } else { obj = node->objects; } message(" bv_test: %d\n", bbox_test(obj,&kindbbox)); */ obj = splitobj[original->typ](original,(VOIDPTR) &kindbbox, bbox_test, &changed,&num_obj); /* message(" split : num_obj=%d\n",num_obj); */ if (num_obj == 0) { *kind = NULL; /* message(" level %d i %d num_obj %d \n", level,i,num_obj); */ } else /* numobj > 0 */ { *kind = newonlytyp(OCTREENODE); (*kind)->index = (node->index)*10+i+1; (*kind)->blatt = TRUE; (*kind)->bbox = kindbbox; (*kind)->objects = obj; (*kind)->children = NULL; /* message(" level %d i %d num_obj %d \n", level,i,num_obj); */ if ((num_obj > max_num) && (level < max_lev)) nodedivide(*kind,level+1,box_len/2); } /* end if */ kind++; } /* end for */ node->objects = NULL; } /* end nodedivide */ Static ULONG setupoctree(OBJECT *obj,BOOLEAN in_or_tree,BOOLEAN space_opt) /* $$$$ ist es noetig, die BBoxes jedes Nodes zu speichern ?? nur dann, wenn im eigentlichen Algorithmus benoetigt. aber Speicher ist auf jeden Fall bereitgestellt!! Ists ueberhaupt noetig, irgendwelche bboxes zu speichern???? Sicher nicht, wenn man Indices verwendet. */ { ULONG number_of_objects; OCTREENODE *root; OCTREEOBJ *octree; BOX3 bbox; VEC3 diagonal; FLOAT box_len; MAT3 *to = NULL; MAT3 *fr = NULL; MATERIAL *mat = NULL; TEXTURE *tex = NULL; if (! in_or_tree) fatal("octree not in or-tree"); /* message("setupoctree\n"); */ number_of_objects = setupobjects(obj->u.octree.original,TRUE,TRUE); /* message("numb_of_obj: %d\n",number_of_objects); */ octree = &(obj->u.octree); /* Zeiger auf Octreeobj */ root = octree->octree; /* Wurzel */ original = octree->original; bbox = obj->bbox; max_lev = octree->max_level; max_num = octree->max_num_pro_node; /* box_aus(&bbox); */ /* BoundingBox quadratisch machen */ v3sub(bbox.max,bbox.min,diagonal); box_len = maxi(diagonal.x,maxi(diagonal.y,diagonal.z)); diagonal = V3ONE; v3scale(diagonal,box_len); v3add(bbox.min,diagonal,bbox.max); root->index = 1; root->bbox = bbox; root->blatt = TRUE; root->children = NULL; root->objects = copyobj[original->typ](original,TRUE,to,fr,mat,tex); /* Aufteilung des Octrees */ if (number_of_objects > max_num) nodedivide(root,0,box_len/2); /*octreeaus(root,1,0); */ return(number_of_objects); } Static OBJECT *insideoctree(PNT3 *pnt,OBJECT *obj) { INSIDE_BOUND_TEST(obj,pnt); /* FIXME: could be improved */ return(inside[obj->u.octree.original->typ](pnt,obj->u.octree.original)); } /***************** Macros fuer 'hitoctree' ********************/ #define absolut(v,w) \ { \ w.x = abso(v.x); \ w.y = abso(v.y); \ w.z = abso(v.z); \ } #define setz(v,w) \ { \ v.x = w.x/2; \ v.y = w.y/2; \ v.z = w.z/2; \ } #define merk(v,w) \ { \ v.x = w.x; \ v.y = w.y; \ v.z = w.z; \ } #define upd(a,b,c) \ { \ verti.a -= komp; \ hori.b -= wid_dir.c; \ hori.c += wid_dir.b; \ } #define ONE_PLANE(bit,a,b,c) \ { \ if (relat & bit) break; \ relat |= bit; \ komp = child_wid_dir.a; \ verti.a = wid_dir.a; \ verti.b = hori.c; \ verti.c = -hori.b; \ hori.b += wid_dir.c; \ hori.c -= wid_dir.b; \ } #define TWO_PLANE(bit,a,b,c) \ { \ if (relat & bit) break; \ relat |= bit; \ komp = child_wid_dir.c; \ verti.a = hori.b; \ verti.b = wid_dir.c; \ verti.c = wid_dir.c; \ hori.a = wid_dir.b - wid_dir.c; \ hori.b -= wid_dir.a; \ hori.c += wid_dir.a; \ } #define THREE_PLANE \ { \ if (relat & 7) break; \ relat |= 7; \ komp = child_wid_dir.x; \ verti.x = wid_dir.x; \ verti.y = wid_dir.x; \ verti.z = wid_dir.x; \ hori.x = wid_dir.y - wid_dir.z; \ hori.y = wid_dir.z - wid_dir.x; \ hori.z = wid_dir.x - wid_dir.y; \ } #define X_PLANE ONE_PLANE(1,x,y,z) #define Y_PLANE ONE_PLANE(2,y,z,x) #define Z_PLANE ONE_PLANE(4,z,x,y) #define YZ_PLANE ONE_PLANE(6,x,y,z) #define ZX_PLANE ONE_PLANE(5,y,z,x) #define XY_PLANE ONE_PLANE(3,z,x,y) #define XYZ_PLANE THREE_PLANE Static VOID traverse( OCTREENODE *node, VEC3 *pntr_verti, FLOAT komp, VEC3 *pntr_hori, VEC3 *pntr_wid_dir, HITLIST *hitlist, FLOAT tmin, FLOAT tmax) /* Vertikal_vergleichswert */ /* Vertikalnavigator */ /* Horizontalnavigator */ /* ray_direct scaled by child width entspricht delta*m im text m ist node_wid delta ist richtungsvektor*/ { OCTREENODE *octn /*, **chil*/ ; HITLIST lochitlist; BOOLEAN ray_hit_obj; VEC3 child_wid_dir; /* Vertically propagated */ VEC3 verti,hori,wid_dir; BYTE relat = 0; /* Relativer Morton Index */ /* BYTE rel; */ /* message("traverse\n"); */ /*octreeaus(node,1,0); */ if ( node->blatt == TRUE ) /* query candidate list */ { /* message(" %d\n",node->index); message("blatt\n"); */ lochitlist = emptyhitlist; HITOBJ(node->objects,tmin,tmax,&lochitlist,ray_hit_obj); count++; if (ray_hit_obj) { /* hit? */ /* message("hit!\n"); */ if (hitlist->first != NULL) { hitlist->last->next = lochitlist.first; hitlist->last = lochitlist.last; } /* possibly eliminate a double hit ? */ else *hitlist = lochitlist; } } /* end if (ray_hit_obj */ else /* Knoten ist unterteilt, Voxel-Walking */ { /* zuerst vertikaler Schritt */ /* message("Walking\n"); */ verti = *pntr_verti; hori = *pntr_hori; wid_dir = *pntr_wid_dir; if (verti.x > komp) { upd(x,y,z); } else relat |=1; if (verti.y > komp) { upd(y,z,x); } else relat |=2; if (verti.z > komp) { upd(z,x,y); } else relat |=4; /* Halbe Werte */ komp = komp/2; setz(child_wid_dir,wid_dir); /* message("hori "); p(&hori); message("verti "); p(&verti); message("ch_w_d "); p(&child_wid_dir); message("komp "); f(komp); message("child index %d\n", relat^entry_octant); */ /* rel = relat^entry_octant; message("index %d\n",rel); chil = node->children; if (chil == NULL) { message(" chil = NULL\n");} else { message("chil = nicht NULL\n"); if (chil[rel] == NULL) { message(" chil[rel] = NULL\n");} else { message("child[rel] = nicht NULL\n"); octn = chil[rel]; } } */ octn = (node->children)[relat ^ entry_octant]; if (octn != NULL ) traverse(octn,&verti,komp,&hori,&child_wid_dir,hitlist,tmin,tmax); /* message("nach traverse vertikal\n"); */ /* dann horizontal */ while(relat != 7) { if (hori.x < 0) { if (hori.y < 0) { X_PLANE; } /* x<0 y<0 */ else { if (hori.y > 0) { Z_PLANE; } /* x<0 y>0 */ else { ZX_PLANE; } /* x<0 y=0 */ } } else /* else 1 */ { if (hori.x > 0) { if (hori.z < 0) { Y_PLANE; } /* x>0 z<0 */ else { if (hori.z > 0) { X_PLANE; } /* x>0 z>0 */ else { XY_PLANE; } /* x>0 z=0 */ } } else { if (hori.y < 0) { X_PLANE; } /* x=0 y<0 */ else { if (hori.y > 0) { YZ_PLANE; } /* x=0 y>0 */ else { XYZ_PLANE; } /* x=0 y=0 */ } } } /* end else 1 */ /* message("child index %d\n", relat^entry_octant); */ /* rel = relat^entry_octant; message("index %d\n",rel); chil = node->children; if (chil == NULL) { message(" chil = NULL\n");} else { message("chil = nicht NULL\n"); if (chil[rel] == NULL) { message(" chil[rel] = NULL\n");} else { message("child[rel] = nicht NULL\n"); octn = chil[rel]; } } */ octn = (node->children)[relat ^ entry_octant]; if (octn != NULL) traverse(octn,&verti,komp,&hori,&child_wid_dir,hitlist,tmin,tmax); /* message("nach traverse horizontal\n"); */ } /* end while */ /* ACHTUNG auf Gueltigkeit nach den Rekursionsschritten !! */ /* *pntr_verti = verti; *pntr_hori = hori; *pntr_wid_dir = wid_dir; */ } /* end else */ } /* end traverse */ /* ------------------------------------------------------------------------ */ Static BOOLEAN hitoctree(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) /* --------------------------------------------------------------------------- calculate intersection with octree --------------------------------------------------------------------------- */ { FLOAT tin,taus; ULONG facein,faceaus; FLOAT el_len, komp; PNT3 begin, exit_punkt; OCTREENODE *octree; VEC3 hori, verti; VEC3 distance_vector; VEC3 richtung; /* message("----------\n"); message("hitoctree\n"); */ PRE_OBJECT(obj,hitlist); if (obj->u.octree.optimize) rci.save_hitlist++; octree = (obj->u.octree.octree); /* Entry_octant berechnen, haengt ab von Ray_direction, Schnittpunkt der moeglichen Eintrittsflaechen des Rays sind z.B. alle Komponenten von 'ray-diretion' negativ, so ist der entry-octant = bbox.max!, der exit_punkt liegt diagonal gegenueber */ entry_octant = 0; exit_punkt = octree->bbox.max; if (rci.ray.direction.x < 0) { entry_octant += 1; exit_punkt.x = octree->bbox.min.x; } if (rci.ray.direction.y < 0) { entry_octant += 2; exit_punkt.y = octree->bbox.min.y; } if (rci.ray.direction.z < 0) { entry_octant += 4; exit_punkt.z = octree->bbox.min.z; } /* message(" ray\n"); p(&(rci.ray.origin)); p(&(rci.ray.direction)); message(" entry\n"); i(entry_octant); */ /* Ermittlung des Eintrittspunktes */ if (hitbox(&(rci.ray), &tin,&taus,&facein,&faceaus,&(octree->bbox))) { /*message(" in bbox ( if 1)\n"); */ /* Initialisierungen */ /* Anfangspunkt des Strahls im Octree */ if (insidebbox(&(rci.ray.origin),&(octree->bbox))) { begin = rci.ray.origin; } else { richtung = rci.ray.direction; v3normalize(richtung); v3addscaled(rci.ray.origin,richtung,tin,begin); } /* el_len entspricht m ( Child_voxel_width) */ el_len = octree->bbox.max.x - octree->bbox.min.x; /* distance_vector entspricht klein delta, vom begin-Punkt bis zum exit-corner */ v3sub(exit_punkt,begin,distance_vector); absolut(distance_vector,distance_vector); /* Horizontal Initialisierung */ /* Betraege der Strahlrichtungskomponenten verwenden */ /* richtung entspricht gross DELTA */ absolut(rci.ray.direction, richtung); v3cross(richtung,distance_vector,hori); /* Vertikale Initialisierung */ verti = distance_vector; /* Initialisierung Vergleichswert entspricht Sm */ komp = el_len/2; /* richtung skaliert entspricht m*DELTA im Text ( child_width_dir) */ v3scale(richtung,el_len); /* message("begin\n"); p(&begin); message("mittel\n"); p(&mittelp); message("el_len"); f(el_len); message("distance_vector"); p(&distance_vector); message("hori "); p(&hori); message("verti "); p(&verti); message("richtung "); p(&richtung); message("komp "); f(komp); */ traverse(octree,&verti,komp,&hori,&richtung,hitlist,tmin,tmax); } /* endif */ if (obj->u.octree.optimize) rci.save_hitlist--; POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } Static VOID endoctree(OBJECT *obj) { message("Die Prozedur wurde %d -mal aufgerufen\n",count); endobj[obj->u.octree.original->typ](obj->u.octree.original); } VOID initoctree(VOID) { nameobj[OCTREE] = "octree"; readobj[OCTREE] = readoctree; copyobj[OCTREE] = copyoctree; writeobj[OCTREE] = writeoctree; boundobj[OCTREE] = boundoctree; setupobj[OCTREE] = setupoctree; splitobj[OCTREE] = split_primitiv; inside[OCTREE] = insideoctree; hitobj[OCTREE] = hitoctree; endobj[OCTREE] = endoctree; } message("Die Prozedur wurde %d -mal aufgerufen\n",count); endobj[obj->u.octree.original->typ](obj->u.octree.original); } VOID initoctree(VOID) { nameobj[OCTREE] = "octree"; readobj[OCTREE] = readoctree; copyobj[OCTREE] = copyoctree; writeoFlirt/octree.d000644 000316 000311 00000001501 06103226562 013403 0ustar00wrzlgup000000 000000 /******************************************************************* PROJECT : flirt MODULE : octree.d octree definitions DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 011192 rweber first version *****************************************************************************/ #ifndef OCTREE_D #define OCTREE_D #include "geometr3.d" #include "flirt.d" #include "system.d" typedef struct octreenode { ULONG index; /* Nummer des Knotens */ BOOLEAN blatt; /* ist der Knoten ein Blatt ? */ BOX3 bbox; /* Boundingbox des Knotens */ struct octreenode **children; struct object *objects; /* Objekte innerhalb dieses Knotens */ } OCTREENODE; #endif ******************************************/ #ifndef OCTREE_D #define OCTREE_D #include "geometr3.d" #include "flirt.d" #include "system.d" typedef struct octreenode { ULONG Flirt/octree.f000644 000316 000311 00000000721 06103226620 013403 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : octree.f octree routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef OCTREE_F #define OCTREE_F #include "system.d" VOID initoctree PP((VOID)); #endif ypedef struct oµ¯ «ö¨s { ULONG Flirt/parabol.c000644 000316 000311 00000024413 06103226526 013550 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : parabol.c paraboloid manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "material.f" #include "texture.f" #include "objects.f" #include "readdata.f" #include "parabol.f" Static OBJECT *readparabol(VOID) { OBJECT *obj; obj = newonlyvar(OBJECT,SIMPLEOBJ); obj->typ = PARABOLOID; readtransform(&(obj->u.obj.obj2world),&(obj->u.obj.world2obj)); obj->u.obj.material = readnamematerial(); obj->u.obj.texture = readnametexture(); return(obj); } #define DIS 0.414213562 /* tan(22.5 * F_PI/180.0) == sqrt(2.0) - 1.0 */ #define DHF (DIS / 2.0) Static PNT3 hull_parabol[16] = { { 0.5, DHF, 0.0 }, { 1.0, DIS, 1.0 }, { DHF, 0.5, 0.0 }, { DIS, 1.0, 1.0 }, { -DHF, 0.5, 0.0 }, { -DIS, 1.0, 1.0 }, { -0.5, DHF, 0.0 }, { -1.0, DIS, 1.0 }, { -0.5, -DHF, 0.0 }, { -1.0, -DIS, 1.0 }, { -DHF, -0.5, 0.0 }, { -DIS, -1.0, 1.0 }, { DHF, -0.5, 0.0 }, { DIS, -1.0, 1.0 }, { 0.5, -DHF, 0.0 }, { 1.0, -DIS, 1.0 } }; Static VOID boundparabol(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? TRUE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; bounds4points(16,hull_parabol,&(obj->bbox),&(obj->bsphere),NULL, &(obj->u.obj.obj2world)); *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static OBJECT *insideparabol(PNT3 *pnt,OBJECT *obj) { PNT3 locpnt; INSIDE_BOUND_TEST(obj,pnt); v3pmulm(*pnt,obj->u.obj.world2obj,locpnt); if (0.0 < locpnt.z && locpnt.z < 1.0 && locpnt.x * locpnt.x + locpnt.y * locpnt.y < locpnt.z) return(obj); return(NULL); } /* ------------------------------------------------------------------------ */ Static BOOLEAN hitparabol(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) /* ------------------------------------------------------------------------ calculate intersection of ray and parabol ------------------------------------------------------------------------ */ { ULONG tminface = 0L; ULONG tmaxface = 0L; HITINFO *hit1,*hit2; FLOAT a,b,c,d,tone,ttwo; RAY3 locray; PRE_OBJECT(obj,hitlist); v3pmulm(rci.ray.origin,obj->u.obj.world2obj,locray.origin); v3vmulm(rci.ray.direction,obj->u.obj.world2obj,locray.direction); if (f_iszero(locray.direction.z)) /* ray parallel to z-planes ? */ { if (locray.origin.z <= 0.0 || locray.origin.z >= 1.0) return(FALSE); } else if (locray.direction.z > 0.0) { ttwo = (1.0 - locray.origin.z) / locray.direction.z; checkaddmax(2L,ttwo,tmaxface,tmin,tmax); } else { tone = (1.0 - locray.origin.z) / locray.direction.z; checkaddmin(2L,tone,tminface,tmin,tmax); } a = locray.direction.x * locray.direction.x + locray.direction.y * locray.direction.y; b = locray.origin.x * locray.direction.x + locray.origin.y * locray.direction.y - 0.5 * locray.direction.z; c = locray.origin.x * locray.origin.x + locray.origin.y * locray.origin.y - locray.origin.z; if (f_iszero(a)) /* linear equation ? */ { if (! f_iszero(b)) /* solvable ? */ { tone = - c / (2.0 * b); if (c > 0.0) /* does the ray enter */ { /* the paraboloid ? */ checkaddmin(1L,tone,tminface,tmin,tmax); } else { checkaddmax(1L,tone,tmaxface,tmin,tmax); } } } else { /* ---------------------- quadric equation : a t^2 + 2b t + c = 0 */ d = b * b - a * c; /* factor 2 was eliminated! */ if (d <= 0.0) /* no root ? */ return(FALSE); /* then exit */ if (b > 0.0) /* stable way to calculate */ d = - f_sqrt(d) - b; /* the roots of a quadratic */ else /* equation */ d = f_sqrt(d) - b; tone = d / a; ttwo = c / d; /* VIETA : tone * ttwo == c/a */ if (tone < ttwo) { checkaddmin(1L,tone,tminface,tmin,tmax); checkaddmax(1L,ttwo,tmaxface,tmin,tmax); } else { checkaddmin(1L,ttwo,tminface,tmin,tmax); checkaddmax(1L,tone,tmaxface,tmin,tmax); } } checkmakerayhit(tminface,tmin,locray,hit1); checkmakerayhit(tmaxface,tmax,locray,hit2); prepare2hits(obj,hit1,hit2,hitlist); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } Static VOID normparabol(HITINFO *hit) { VEC3 pnt,locnormal; if (hit->face == 1L) { pnt.x = hit->ray.origin.x + hit->t * hit->ray.direction.x; pnt.y = hit->ray.origin.y + hit->t * hit->ray.direction.y; pnt.z = hit->ray.origin.z + hit->t * hit->ray.direction.z; locnormal.x = 2.0 * pnt.x * pnt.z; locnormal.y = 2.0 * pnt.y * pnt.z; locnormal.z = - pnt.x * pnt.x - pnt.y * pnt.y; if (f_iszero(locnormal.z)) locnormal.z = -1.0; v3vmultransm(locnormal,hit->obj->u.obj.world2obj,hit->normal); } else { v3vmultransm(V3ZUNIT,hit->obj->u.obj.world2obj,hit->normal); } v3normalize(hit->normal); } Static VOID pntnormparabol(OBJECT *obj,ULONG surface,PNT2 *point, PNT3 *world,VEC3 *normal) { PNT3 locpnt; VEC3 locnormal; if (surface == 1L) { locpnt.z = point->y; if (locpnt.z < F_SMALL) { locpnt.x = 0.0; locpnt.y = 0.0; } else { locpnt.x = f_cos(point->x * F_2PI) / point->y; locpnt.y = f_sin(point->x * F_2PI) / point->y; locnormal.x = 2.0 * locpnt.x * locpnt.z; locnormal.y = 2.0 * locpnt.y * locpnt.z; locnormal.z = - locpnt.x * locpnt.x - locpnt.y * locpnt.y; if (f_iszero(locnormal.z)) locnormal.z = -1.0; } locnormal = locpnt; locnormal.z = - locnormal.z; } else { locpnt.x = f_cos(point->x * F_2PI) * point->y; locpnt.y = f_sin(point->x * F_2PI) * point->y; locpnt.z = 1.0; locnormal = V3ZUNIT; } v3vmulm(locpnt,obj->u.obj.obj2world,*world); v3vmultransm(locnormal,obj->u.obj.world2obj,*normal); v3normalize(*normal); } Static VOID hitcoordparabol(HITINFO *hit,GEOMPAR needed) { if (needed & (LOCALPNT | GEOM_2DCOORD)) { v3addscaled(hit->ray.origin,hit->ray.direction,hit->t, texinfo.localpnt); texinfo.face = hit->face; if (needed & GEOM_2DCOORD) { texinfo.pnt2[0].x = (1.0 / F_2PI) * f_atan2(texinfo.localpnt.y,texinfo.localpnt.x) + 0.5; if (texinfo.face == 1L) texinfo.pnt2[0].y = texinfo.localpnt.z; else texinfo.pnt2[0].y = f_sqrt(texinfo.localpnt.x * texinfo.localpnt.x + texinfo.localpnt.y * texinfo.localpnt.y); texinfo.num2 = 1; } } } Static BOOLEAN pntcoordparabol(OBJECT *obj,GEOMPAR needed) { FLOAT x2_y2; if (needed & (LOCALPNT | GEOM_2DCOORD)) { v3pmulm(texinfo.worldpnt,obj->u.obj.world2obj,texinfo.localpnt); if (needed & GEOM_2DCOORD) { if (texinfo.localpnt.z <= 0.0) /* below 0 */ { texinfo.face = 1L; texinfo.pnt2[0].x = 0.0; texinfo.pnt2[0].y = 0.0; } else { texinfo.pnt2[0].x = (1.0 / F_2PI) * f_atan2(texinfo.localpnt.y,texinfo.localpnt.x) + 0.5; x2_y2 = texinfo.localpnt.x * texinfo.localpnt.x + texinfo.localpnt.y * texinfo.localpnt.y; if (x2_y2 > texinfo.localpnt.z * texinfo.localpnt.z) { /* out of (half) cone ? */ texinfo.face = 1L; if (texinfo.localpnt.z >= 1.0) /* too high */ texinfo.pnt2[0].y = 1.0; else texinfo.pnt2[0].y = texinfo.localpnt.z; } else /* upper cap */ { texinfo.face = 2L; texinfo.pnt2[0].y = f_sqrt(x2_y2) / texinfo.localpnt.z; } } texinfo.num2 = 1; } } return(TRUE); } VOID initparabol(VOID) { nameobj[PARABOLOID] = "paraboloid"; surfaces[PARABOLOID] = 2L; readobj[PARABOLOID] = readparabol; copyobj[PARABOLOID] = copysobj; writeobj[PARABOLOID] = writesobj; boundobj[PARABOLOID] = boundparabol; setupobj[PARABOLOID] = setup_primitiv; splitobj[PARABOLOID] = split_primitiv; inside[PARABOLOID] = insideparabol; hitobj[PARABOLOID] = hitparabol; normalvec[PARABOLOID] = normparabol; pntnormvec[PARABOLOID] = pntnormparabol; hitcoord[PARABOLOID] = hitcoordparabol; pntcoord[PARABOLOID] = pntcoordparabol; endobj[PARABOLOID] = end_primitiv; } readparabol; copyobj[PARABOLOID] = copysobj; writeobj[PARABOLOID] = writesobj; boundobj[PARABOLOID] = boundparabol; setupobj[PARABOLOID] = setup_primitiv; splitobj[PARABOLOID] = split_primitiv; inside[PARABOLOID] = insidFlirt/parabol.f000644 000316 000311 00000000746 06103226620 013551 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : parabol.f paraboloid manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef PARABOL_F #define PARABOL_F #include "system.d" VOID initparabol PP((VOID)); #endif ö¨oh[PARABOLOID] = insidFlirt/parsweep.c000644 000316 000311 00000016245 06103226526 013762 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : parsweep.c parabola sweep manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "material.f" #include "texture.f" #include "objects.f" #include "readdata.f" #include "parsweep.f" Static OBJECT *readparsweep(VOID) { OBJECT *obj; obj = newonlyvar(OBJECT,SIMPLEOBJ); obj->typ = PARABOLASWEEP; readtransform(&(obj->u.obj.obj2world),&(obj->u.obj.world2obj)); obj->u.obj.material = readnamematerial(); obj->u.obj.texture = readnametexture(); return(obj); } Static PNT3 hull_parsweep[] = { { 0.5, 0.0, 0.0 }, { 0.5, 0.0, 1.0 }, { 1.0, 1.0, 0.0 }, { 1.0, 1.0, 1.0 }, { -1.0, 1.0, 0.0 }, { -1.0, 1.0, 1.0 }, { -0.5, 0.0, 0.0 }, { -0.5, 0.0, 1.0 }, }; Static VOID boundparsweep(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? TRUE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; bounds4points(8,hull_parsweep,&(obj->bbox),&(obj->bsphere),NULL, &(obj->u.obj.obj2world)); *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static OBJECT *insideparsweep(PNT3 *pnt,OBJECT *obj) { PNT3 locpnt; INSIDE_BOUND_TEST(obj,pnt); v3pmulm(*pnt,obj->u.obj.world2obj,locpnt); if (0.0 < locpnt.z && locpnt.z < 1.0 && 0.0 < locpnt.y && locpnt.y < 1.0 && locpnt.x * locpnt.x < locpnt.y) return(obj); return(NULL); } /* ------------------------------------------------------------------------ */ Static BOOLEAN hitparsweep(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) /* ------------------------------------------------------------------------ calculate intersection of ray and parsweep ------------------------------------------------------------------------ */ { ULONG tminface = 0L; ULONG tmaxface = 0L; HITINFO *hit1,*hit2; FLOAT a,b,c,d,tone,ttwo; RAY3 locray; PRE_OBJECT(obj,hitlist); v3pmulm(rci.ray.origin,obj->u.obj.world2obj,locray.origin); v3vmulm(rci.ray.direction,obj->u.obj.world2obj,locray.direction); if (f_iszero(locray.direction.z)) /* ray parallel to z-planes ? */ { if (locray.origin.z <= 0.0 || locray.origin.z >= 1.0) return(FALSE); } else if (locray.direction.z > 0.0) { tone = - locray.origin.z / locray.direction.z; checkaddmin(3L,tone,tminface,tmin,tmax); ttwo = (1.0 - locray.origin.z) / locray.direction.z; checkaddmax(4L,ttwo,tmaxface,tmin,tmax); } else { tone = (1.0 - locray.origin.z) / locray.direction.z; checkaddmin(4L,tone,tminface,tmin,tmax); ttwo = - locray.origin.z / locray.direction.z; checkaddmax(3L,ttwo,tmaxface,tmin,tmax); } if (f_iszero(locray.direction.y)) /* ray parallel to y-plane ? */ { if (locray.origin.y <= 0.0 || locray.origin.y >= 1.0) return(FALSE); } else if (locray.direction.y > 0.0) { ttwo = (1.0 - locray.origin.y) / locray.direction.y; checkaddmax(2L,ttwo,tmaxface,tmin,tmax); } else { tone = (1.0 - locray.origin.y) / locray.direction.y; checkaddmin(2L,tone,tminface,tmin,tmax); } a = locray.direction.x * locray.direction.x; b = locray.origin.x * locray.direction.x - 0.5 * locray.direction.y; c = locray.origin.x * locray.origin.x - locray.origin.y; if (f_iszero(a)) /* linear equation ? */ { if (! f_iszero(b)) /* solvable ? */ { tone = - c / (2.0 * b); if (c > 0.0) /* does the ray enter */ { /* the parabolasweep ? */ checkaddmin(1L,tone,tminface,tmin,tmax); } else { checkaddmax(1L,tone,tmaxface,tmin,tmax); } } } else { /* ---------------------- quadric equation : a t^2 + 2b t + c = 0 */ d = b * b - a * c; /* factor 2 was eliminated! */ if (d <= 0.0) /* no root ? */ return(FALSE); /* then exit */ if (b > 0.0) /* stable way to calculate */ d = - f_sqrt(d) - b; /* the roots of a quadratic */ else /* equation */ d = f_sqrt(d) - b; tone = d / a; ttwo = c / d; /* VIETA : tone * ttwo == c/a */ if (tone < ttwo) { checkaddmin(1L,tone,tminface,tmin,tmax); checkaddmax(1L,ttwo,tmaxface,tmin,tmax); } else { checkaddmin(1L,ttwo,tminface,tmin,tmax); checkaddmax(1L,tone,tmaxface,tmin,tmax); } } checkmakerayhit(tminface,tmin,locray,hit1); checkmakerayhit(tmaxface,tmax,locray,hit2); prepare2hits(obj,hit1,hit2,hitlist); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } Static VEC3 normal_parsweep[] = { { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0,-1.0 }, { 0.0, 0.0, 1.0 } }; Static VOID normparsweep(HITINFO *hit) { VEC3 locnormal; if (hit->face == 1L) { locnormal.x = 2.0 * (hit->ray.origin.y + hit->t * hit->ray.direction.y); locnormal.y = - hit->ray.origin.x - hit->t * hit->ray.direction.x; locnormal.z = 0; if (f_iszero(locnormal.y)) { locnormal.y = -1.0; } v3vmultransm(locnormal,hit->obj->u.obj.world2obj,hit->normal); } else { v3vmultransm(normal_parsweep[hit->face], hit->obj->u.obj.world2obj,hit->normal); } v3normalize(hit->normal); } VOID initparsweep(VOID) { nameobj[PARABOLASWEEP] = "parabolasweep"; surfaces[PARABOLASWEEP] = 4L; readobj[PARABOLASWEEP] = readparsweep; copyobj[PARABOLASWEEP] = copysobj; writeobj[PARABOLASWEEP] = writesobj; boundobj[PARABOLASWEEP] = boundparsweep; setupobj[PARABOLASWEEP] = setup_primitiv; splitobj[PARABOLASWEEP] = split_primitiv; inside[PARABOLASWEEP] = insideparsweep; hitobj[PARABOLASWEEP] = hitparsweep; normalvec[PARABOLASWEEP] = normparsweep; endobj[PARABOLASWEEP] = end_primitiv; } eobj[PARABOLASWEEP] = "parabolasweep"; surfaces[PARABOLASWEEP] = 4L; readobj[PARABOLASWEEP] = readparsweep; copyobj[PARABOLASWEEP] = copysobj; writeobj[PARABOLASWEEP] = writesobj; boundobj[PARABOLASWEEP] = boundparsweep; setupobj[PARABOLASWEEP] = setup_primitiv; splitobj[PARABOLASWEEP] = split_primitiv; inside[PARFlirt/parsweep.f000644 000316 000311 00000000756 06103226622 013762 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : parsweep.f parabola sweep manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef PARSWEEP_F #define PARSWEEP_F #include "system.d" VOID initparsweep PP((VOID)); #endif iv; inside[PARFlirt/plane.c000644 000316 000311 00000025174 06103226526 013234 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : plane.c Plane object manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "objects.f" #include "readdata.f" #include "writdata.f" #include "material.f" #include "texture.f" #include "plane.f" Static OBJECT *readplane(VOID) { UINT i,j; UINT doubleindex,singleindex; OBJECT *obj; UINT number[4]; PLANEENTRY *plane; VEC3 v1,v2; POINTARRAY *points; obj = newonlyvar(OBJECT,PLANEOBJ); obj->typ = PLANE_OBJECT; points = readnamepoints(); obj->u.plane.points = points; match_read_uint("number", obj->u.plane.number); plane = (PLANEENTRY *) newonlymem(sizeof(PLANEENTRY) * obj->u.plane.number); obj->u.plane.plane = plane; doubleindex = 0; singleindex = obj->u.plane.number - 1; for (i = 0; i < obj->u.plane.number; i++) { if (matchreadconststring("plane")) { plane = &(obj->u.plane.plane[singleindex]); singleindex--; plane->two = FALSE; for (j = 0; j < 3; j++) { number[j] = readuint() - 1; if (number[j] > points->number) number[j] = 0; } plane->point1 = points->element[number[0]]; v3sub(points->element[number[1]],plane->point1,v1); v3sub(points->element[number[2]],plane->point1,v2); v3cross(v2,v1,plane->normal); v3normalize(plane->normal); plane->ndotp1 = v3dot(plane->normal,plane->point1); for (j = 0; j < points->number; j++) { if (j != number[0] && j != number[1] && j != number[2]) { v3sub(plane->point1,points->element[j],v1); if (v3dot(v1,plane->normal) < -F_SMALL) { message("plane %d points inside, point: %d\n", i + 1,j + 1); break; } } } } else { readconststring("doubleplane"); plane = &(obj->u.plane.plane[doubleindex]); doubleindex++; plane->two = TRUE; for (j = 0; j < 4; j++) { number[j] = readuint() - 1; if (number[j] > points->number) number[j] = 0; } plane->point1 = points->element[number[0]]; plane->point2 = points->element[number[3]]; v3sub(points->element[number[1]],plane->point1,v1); v3sub(points->element[number[2]],plane->point1,v2); v3cross(v2,v1,plane->normal); v3normalize(plane->normal); plane->ndotp1 = v3dot(plane->normal,plane->point1); plane->ndotp2 = v3dot(plane->normal,plane->point2); for (j = 0; j < points->number; j++) { if (j != number[0] && j != number[1] && j != number[2]) { v3sub(plane->point1,points->element[j],v1); if (v3dot(v1,plane->normal) < -F_SMALL) { message("doubleplane %i points inside\n",i + 1); break; } } } } } obj->u.plane.doublenum = doubleindex; obj->u.plane.material = readnamematerial(); obj->u.plane.texture = readnametexture(); return(obj); } Static OBJECT *copyplane(OBJECT *obj,BOOLEAN recurse,MAT3 *to,MAT3 *fr, MATERIAL *mat,TEXTURE *tex) { UINT i; OBJECT *newobj; PLANEENTRY *newplane,*oldplane; POINTARRAY *points; newobj = newonlyvar(OBJECT,PLANEOBJ); newobj->typ = obj->typ; newobj->bbox = obj->bbox; newobj->u.plane = obj->u.plane; if (mat != NULL) newobj->u.plane.material = mat; if (tex != NULL) newobj->u.plane.texture = tex; if (to != NULL && fr != NULL) { newplane = (PLANEENTRY *) newonlymem(sizeof(PLANEENTRY) * newobj->u.plane.number); newobj->u.plane.plane = newplane; oldplane = obj->u.plane.plane; points = (POINTARRAY *) newonlytyp(POINTARRAY); newobj->u.plane.points = points; points->number = obj->u.plane.points->number; points->element = (PNT3 *) newonlymem(sizeof(PNT3) * points->number); for (i = 0; i < points->number; i++) { v3pmulm(obj->u.plane.points->element[i],*to,points->element[i]); } for (i = 0; i < newobj->u.plane.number; i++) { v3pmulm(oldplane->point1,*to,newplane->point1); v3vmultransm(oldplane->normal,*fr,newplane->normal); v3normalize(newplane->normal); newplane->ndotp1 = v3dot(newplane->normal,newplane->point1); newplane->two = oldplane->two; if (newplane->two) { v3pmulm(oldplane->point2,*to,newplane->point2); newplane->ndotp2 = v3dot(newplane->normal,newplane->point2); } newplane++; oldplane++; } } return(newobj); } Static VOID writeplane(OBJECT *obj) { /* UINT i,j,number; */ writenamepoints(obj->u.plane.points); write_string_uint("number", obj->u.plane.number); writestring("ERROR: Data not available"); /* FIXME: this is broken */ writenamematerial(obj->u.plane.material); writenametexture(obj->u.plane.texture); } Static VOID boundplane(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { obj->test_bbox = (bbox_test) ? BOUNDTEST_NONE : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? FALSE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; bounds4points(obj->u.plane.points->number,obj->u.plane.points->element, &(obj->bbox),&(obj->bsphere),NULL,NULL); *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static OBJECT *insideplane(PNT3 *pnt,OBJECT *obj) { UINT i; FLOAT ndotp; PLANEENTRY *plane; plane = obj->u.plane.plane; for (i = 0; i < obj->u.plane.number; i++) { ndotp = v3dot(plane->normal,*pnt); if (ndotp >= plane->ndotp1) return(NULL); if (plane->two && ndotp <= plane->ndotp2) return(NULL); plane++; } return(obj); } /* ------------------------------------------------------------------------ */ Static BOOLEAN hitplane(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) /* ------------------------------------------------------------------------ calculate intersection of ray and cube ------------------------------------------------------------------------ */ { UINT i; ULONG face; ULONG tminface = 0L; ULONG tmaxface = 0L; FLOAT ndotv,ndoto; FLOAT t; PLANEENTRY *plane; HITINFO *hit1,*hit2; PRE_OBJECT(obj,hitlist); plane = obj->u.plane.plane; face = 1L; for (i = 0; i < obj->u.plane.doublenum; i++) { ndotv = v3dot(plane->normal,rci.ray.direction); ndoto = v3dot(plane->normal,rci.ray.origin); if (f_iszero(ndotv)) /* ray parallel to planes ? */ { if (ndoto >= plane->ndotp1) return(FALSE); if (ndoto <= plane->ndotp2) return(FALSE); } else { if (ndotv < 0.0) { t = (plane->ndotp1 - ndoto) / ndotv; checkaddmin(face,t,tminface,tmin,tmax); t = (plane->ndotp2 - ndoto) / ndotv; checkaddmax(face + 1L,t,tmaxface,tmin,tmax); } else { t = (plane->ndotp2 - ndoto) / ndotv; checkaddmin(face + 1L,t,tminface,tmin,tmax); t = (plane->ndotp1 - ndoto) / ndotv; checkaddmax(face,t,tmaxface,tmin,tmax); } } face += 2L; plane++; } for (i = obj->u.plane.doublenum; i < obj->u.plane.number; i++) { ndotv = v3dot(plane->normal,rci.ray.direction); ndoto = v3dot(plane->normal,rci.ray.origin); if (f_iszero(ndotv)) /* ray parallel to planes ? */ { if (ndoto >= plane->ndotp1) return(FALSE); } else { if (ndotv < 0.0) { t = (plane->ndotp1 - ndoto) / ndotv; checkaddmin(face,t,tminface,tmin,tmax); } else { t = (plane->ndotp1 - ndoto) / ndotv; checkaddmax(face,t,tmaxface,tmin,tmax); } } face++; plane++; } checkmakerayhit(tminface,tmin,rci.ray,hit1); checkmakerayhit(tmaxface,tmax,rci.ray,hit2); prepare2hits(obj,hit1,hit2,hitlist); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } Static VOID normplane(HITINFO *hit) { UINT face,doublenum; doublenum = hit->obj->u.plane.doublenum; face = (UINT) (hit->face - 1); if (face < doublenum * 2) /* double plane */ { hit->normal = hit->obj->u.plane.plane[face / 2].normal; if ((face & 1) != 0) { v3negate(hit->normal); } } else hit->normal = hit->obj->u.plane.plane[face - doublenum].normal; } VOID initplane(VOID) { nameobj[PLANE_OBJECT] = "planes"; surfaces[PLANE_OBJECT] = 0L; /* FIXME: cannot be determined previously */ readobj[PLANE_OBJECT] = readplane; copyobj[PLANE_OBJECT] = copyplane; writeobj[PLANE_OBJECT] = writeplane; boundobj[PLANE_OBJECT] = boundplane; setupobj[PLANE_OBJECT] = setup_primitiv; splitobj[PLANE_OBJECT] = split_primitiv; inside[PLANE_OBJECT] = insideplane; hitobj[PLANE_OBJECT] = hitplane; normalvec[PLANE_OBJECT] = normplane; endobj[PLANE_OBJECT] = end_primitiv; } T] = "planes"; surfaces[PLANE_OBJECT] = 0L; /* FIXME: cannot be determined previously */ readobj[PLANE_OBJECT] = readplane; copyobj[PLANE_OBJECT] = copyplane; writeobj[PLANE_OBJECT] = writeplane; boundobj[PLANE_OBJECT] = boundplane; setupobj[PLANE_OBJECT] = setup_primitiv; splitobj[PLANE_OBJECT] = split_primitiv; inside[PLANE_OBJECT] = insideplane; Flirt/plane.d000644 000316 000311 00000001265 06103226562 013230 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : plane.d Plane object manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef PLANE_D #define PLANE_D #include "geometr3.d" #include "flirt.d" typedef struct planeentry { BOOLEAN two; VEC3 normal; FLOAT ndotp1; FLOAT ndotp2; PNT3 point1; PNT3 point2; } PLANEENTRY; #endif HOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef PLANE_D #define PLANE_D #include "geometr3.d" #include "flirt.d" typedef struct planeentry { BOOLEAN Flirt/plane.f000644 000316 000311 00000000740 06103226622 013224 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : plane.f Plane object manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef PLANE_F #define PLANE_F #include "system.d" VOID initplane PP((VOID)); #endif µ¯ «ö¨tX { BOOLEAN Flirt/random.c000644 000316 000311 00000022136 06103226526 013410 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : random.c Random number generators DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #if defined(__STDC__) || defined(_MSC_VER) || defined(VAX) #include #define STDLIB_H #endif #include "flirt.f" #include "numeric.f" #include "random.f" /* these numbers are taken from CACM 10/88 */ /* Park & Miller: Random Number Generators: Good Ones are Hard to Find */ /* A1/M1/Q1/R1 is the Minimum Standard Generator ! */ #define A1 16807L /* 7 ^ 5 */ #define M1 2147483647L /* 2 ^ 31 - 1 */ #define Q1 127773L /* M div A */ #define R1 2836L /* M mod A */ #define A2 48271L /* */ #define M2 2147483647L /* 2 ^ 31 - 1 */ #define Q2 44488L /* M div A */ #define R2 3399L /* M mod A */ #define A3 69621L /* */ #define M3 2147483647L /* 2 ^ 31 - 1 */ #define Q3 30845L /* M div A */ #define R3 23092L /* M mod A */ Static ULONG rand_seed = 0xD75E16A3UL; Static UINT seed_02; Static UINT seed_03; Static UINT seed_08; Static UINT seed_09; Static UINT seed_11; Static FLOAT gausstable[51] = { 0.000,0.025,0.050,0.075,0.100,0.126,0.151,0.176,0.202,0.228, 0.253,0.279,0.305,0.332,0.358,0.385,0.412,0.440,0.468,0.496, 0.524,0.553,0.583,0.613,0.643,0.674,0.706,0.739,0.772,0.806, 0.842,0.878,0.915,0.954,0.994,1.036,1.080,1.126,1.175,1.227, 1.282,1.341,1.405,1.476,1.555,1.645,1.751,1.881,2.054,2.326, 3.500 }; VOID seed_rand(ULONG seed) { rand_seed = seed; } FLOAT rand01(VOID) { Register LONG seed; LONG lo,hi; seed = rand_seed; hi = seed / Q3; lo = seed % Q3; seed = A3 * lo - R3 * hi; if (seed <= 0) seed += M3; rand_seed = seed; return((FLOAT) (seed - 1) / (FLOAT) (M3 - 2)); } FLOAT equal_02(VOID) { seed_02 = (seed_02 + 1) % 2; return((seed_02 + rand01()) / 2.0); } FLOAT equal_03(VOID) { seed_03 = (seed_03 + 1) % 3; return((seed_03 + rand01()) / 3.0); } FLOAT equal_08(VOID) { seed_08 = (seed_08 + 3) % 8; return((seed_08 + rand01()) / 8.0); } FLOAT equal_09(VOID) { seed_09 = (seed_09 + 2) % 9; return((seed_09 + rand01()) / 9.0); } FLOAT equal_11(VOID) { seed_11 = (seed_11 + 5) % 11; return((seed_11 + rand01()) / 11.0); } /* ------------------------------------------------------------------------ Berechnet normalverteilte Zufallszahlen mit Mittel my und Varianz sigma. Die Normal_verteilung wird bei dmax abgeschnitten; in diesem Fall wird eine neue Zufallszahl bestimmt! Vorgangsweise: 1) Gleichverteilte Zufallszahl berechnen 2) nach Tabelle der inversen Funktion zur Verteilungsfunktion der Normalverteilung (Definitionsbereich: [0..1]) normalverteilte Zufallszahl interpolieren ------------------------------------------------------------------------ */ FLOAT gauss(FLOAT my,FLOAT sigma,FLOAT dmax,FLOAT (*rndfun)(VOID)) { INT index; FLOAT rnd; forever { rnd = rndfun() - 0.5; if (rnd == 0.0) break; else if (rnd > 0.0) rnd *= 100; else { rnd = - rnd * 100; sigma = -sigma; } index = (INT) f_floor(rnd); if (index == 50) fatal("in gauss: rnd = %f",rnd); rnd -= index; rnd = sigma * interpol(gausstable[index],gausstable[index + 1],rnd); if (f_abs(rnd) < dmax) { my += rnd; break; } } return(my); } FLOAT gauss_02(VOID) { return(gauss(0.0,0.4246609,1.0,equal_02)); } FLOAT gauss_03(VOID) { return(gauss(0.0,0.4246609,1.0,equal_03)); } FLOAT gauss_11(VOID) { return(gauss(0.5,0.2123305,0.5,equal_11)); } VOID init_random(VOID) { seed_02 = (UINT) (rand01() * 2.0); seed_03 = (UINT) (rand01() * 3.0); seed_08 = (UINT) (rand01() * 8.0); seed_09 = (UINT) (rand01() * 9.0); seed_11 = (UINT) (rand01() * 11.0); } /******************************************************************************/ Static ULONG crctab[256] = { 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, 0x2d02ef8dUL }; ULONG crc_rand = 0x2AD9C4F7UL; VOID crc_rand_update(BYTE val) { Register ULONG crc; crc = crc_rand; crc_rand = (crc << 8) ^ crctab[(BYTE) (crc & 0x00FF) ^ val]; } DOUBLE crc_rand_val(VOID) { Register ULONG seed; LONG lo,hi; DOUBLE rando; seed = (LONG) (crc_rand & 0x7FFFFFFFL); /* max 2 ^ 31 - 1 now */ if (seed == 0) /* 0 and 2 ^ 31 - 1 */ seed = M2 - 1; /* are not allowed */ else if (seed >= M2) seed = 1; hi = seed / Q2; lo = seed % Q2; seed = A2 * lo - R2 * hi; if (seed <= 0) seed += M2; hi = seed / Q2; lo = seed % Q2; seed = A2 * lo - R2 * hi; if (seed <= 0) seed += M2; hi = seed / Q2; lo = seed % Q2; seed = A2 * lo - R2 * hi; if (seed <= 0) seed += M2; crc_rand = seed; rando = (DOUBLE) (seed - 1) / (DOUBLE) (M2 - 2); return(rando); } /* are not allowed */ else if (seed >= M2) seed = 1; hi = seed / Q2; lo = seed % Q2; seed = A2 * lo - R2 * hi; if (seed <= 0) seed += M2; hi = seed / Q2; lo = seed % Q2; seed = A2 * lo - R2 * hi; if (seed <= 0) seed += M2; hi = seed / Q2; lo = seed % Q2; seed = A2 * lo - R2 * hi; if (seed <= 0) seed += M2; crcFlirt/random.f000644 000316 000311 00000001615 06103226622 013407 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : random.f Random number generator DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef RANDOM_F #define RANDOM_F #include "system.d" VOID seed_rand PP((ULONG seed)); FLOAT rand01 PP((VOID)); FLOAT equal_02 PP((VOID)); FLOAT equal_03 PP((VOID)); FLOAT equal_08 PP((VOID)); FLOAT equal_09 PP((VOID)); FLOAT equal_11 PP((VOID)); FLOAT gauss PP((FLOAT my,FLOAT sigma,FLOAT dmax,FLOAT (*x)(VOID))); FLOAT gauss_02 PP((VOID)); FLOAT gauss_03 PP((VOID)); FLOAT gauss_11 PP((VOID)); VOID init_random PP((VOID)); Extern ULONG crc_rand; VOID crc_rand_update PP((BYTE val)); DOUBLE crc_rand_val PP((VOID)); #endif #define RANDOM_F #include "system.d" VOID seed_rand PP((ULONG seed)); FLOAT rand01 PP((VOID)); FLOAT equal_02 PP(Flirt/raycount.c000644 000316 000311 00000006463 06103226530 013774 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : raycount.c Accounting DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "raycount.f" RAYCOUNT rays = { 0L, 0L, 0L, 0L }; /* global */ UINT row; UINT column; Static ULONG startticks; Static DOUBLE samplesecs; Static DOUBLE linesecs; Static DOUBLE min_raps; Static DOUBLE max_raps; Static RAYCOUNT linerays; VOID startcount(VOID) { message("\nRAYTRACING:\n"); message(" line seconds raps"); message(" rays prim refl trans light\n"); min_raps = F_HUGE; max_raps = -F_HUGE; samplesecs = 0.0; linerays = rays; startticks = clockticks(); } VOID linecount(UINT line) { ULONG prim_rays; DOUBLE raps; linesecs = ticks2secs(startticks,clockticks()); if (linesecs < 0.001) linesecs = 0.001; linerays.number = rays.number - linerays.number; linerays.shadow = rays.shadow - linerays.shadow; linerays.reflect = rays.reflect - linerays.reflect; linerays.refract = rays.refract - linerays.refract; prim_rays = linerays.number - linerays.shadow - linerays.reflect - linerays.refract; raps = linerays.number / linesecs; if (raps > max_raps) max_raps = raps; if (raps < min_raps) min_raps = raps; message(" %5d %9.3f %9.2f %7lu %6lu %6lu %6lu %6lu\n", line,linesecs,raps,linerays.number, prim_rays,linerays.reflect,linerays.refract, linerays.shadow); samplesecs += linesecs; linerays = rays; startticks = clockticks(); } DOUBLE endcount(ULONG pixels) { ULONG prim_rays; prim_rays = rays.number - rays.reflect - rays.refract - rays.shadow; message("\nRAY STATISTICS:\n"); message(" ray type number perpixel\n"); message(" --------------------------------------\n"); message(" primary : %8ld %11.3lf\n",prim_rays, prim_rays / (DOUBLE)pixels); message(" reflection : %8ld %11.3lf\n",rays.reflect, rays.reflect / (DOUBLE)pixels); message(" transparence : %8ld %11.3lf\n",rays.refract, rays.refract / (DOUBLE)pixels); message(" light : %8ld %11.3lf\n",rays.shadow, rays.shadow / (DOUBLE)pixels); message(" --------------------------------------\n"); message(" sum of all : %9ld %11.3lf\n\n",rays.number, rays.number / (DOUBLE)pixels); message(" rays per second (min) : %11.3lf\n",min_raps); message(" rays per second (avg) : %11.3lf\n", rays.number / samplesecs); message(" rays per second (max) : %11.3lf\n",max_raps); message(" total sample time : %11.3lf\n",samplesecs); return(samplesecs); } -----------------\n"); message(" sum of all : %9ld %11.3lf\n\n",rays.number, rays.number / (DOUBLE)pixels); message(" rays per second (min) : %1Flirt/raycount.d000644 000316 000311 00000001140 06103226564 013767 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : raycount.d counting rays DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef RAYCOUNT_D #define RAYCOUNT_D #include "system.d" #include "flirt.d" typedef struct raycount { ULONG number; ULONG shadow; ULONG reflect; ULONG refract; } RAYCOUNT; #endif lirt MODULE : raycount.d counting rays DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef RAYCOUNT_D #define RAYCOUNT_D #include "system.d" #include "flirt.d" typedef struct raycount { ULONG number; ULOFlirt/raycount.f000644 000316 000311 00000001130 06103226622 013763 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : raycount.f counting rays DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef RAYCOUNT_F #define RAYCOUNT_F #include "raycount.d" Extern RAYCOUNT rays; Extern UINT row; Extern UINT column; VOID startcount PP((VOID)); VOID linecount PP((UINT line)); DOUBLE endcount PP((ULONG pixels)); #endif CT : flirt MODULE : raycount.f counting rays DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef RAYCOUNT_F #define RAYCOUNT_F #include "raycount.d" Extern RAYCOUNT rays; Extern UINT row; Extern UINT column; VOID startcount PFlirt/raytrace.c000644 000316 000311 00000043250 06114641350 013740 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : raytrace.c calculate color coming from the direction of a ray DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "color.f" #include "geometr3.f" #include "hitlist.f" #include "objects.f" #include "light.f" #include "material.f" #include "texture.f" #include "environm.f" #include "raycount.f" #include "scene.f" #include "raytrace.f" #include "random.f" #define obj2mat(o) ((o == NULL) ? global_material : o->u.obj.material) COLOR global_background; UINT raytracelevel; /* ------------------------------------------------------------------------ do_texture ------------------------------------------------------------------------ */ VOID do_texture(OBJECT *fromobj,HITINFO *hit,OBJECT *toobj, PNT3 *point,FLOAT ndotv,VEC3 *normal,SURFACE *surface) { MATPAR fromchanges,hitchanges,tochanges; GEOMPAR fromneeds,hitneeds,toneeds; MATERIAL frommat,hitmat,tomat; OBJECT *hit_obj = hit->obj; if (fromobj == NULL || fromobj->u.obj.texture == NULL) { fromchanges = MATPAR_NONE; fromneeds = GEOM_NONE; } else { fromchanges = fromobj->u.obj.texture->fromchanges; fromneeds = fromobj->u.obj.texture->fromneeds; } if (hit_obj->u.obj.texture == NULL) /* hitobj is hopefully != NULL */ { hitchanges = MATPAR_NONE; hitneeds = GEOM_NONE; } else { hitchanges = hit_obj->u.obj.texture->hitchanges; hitneeds = hit_obj->u.obj.texture->hitneeds; } if (toobj == NULL || toobj->u.obj.texture == NULL) { tochanges = MATPAR_NONE; toneeds = GEOM_NONE; } else { tochanges = toobj->u.obj.texture->tochanges; toneeds = toobj->u.obj.texture->toneeds; } if ((fromchanges | hitchanges | tochanges) == MATPAR_NONE) { material2surface(obj2mat(fromobj),obj2mat(hit_obj), obj2mat(toobj),surface); } else { if (hit_obj == fromobj) { hitchanges |= fromchanges; hitneeds |= fromneeds; fromchanges = MATPAR_NONE; fromneeds = GEOM_NONE; } if (hit_obj == toobj) { hitchanges |= tochanges; hitneeds |= toneeds; tochanges = MATPAR_NONE; toneeds = GEOM_NONE; } texinfo.num1 = 0; texinfo.num2 = 0; texinfo.num3 = 0; texinfo.worldpnt = *point; texinfo.worldnormal = *normal; texinfo.ndotv = ndotv; texinfo.material = obj2mat(fromobj); frommat = *texinfo.material; if (fromchanges != MATPAR_NONE) { pntcoord[fromobj->typ](fromobj,fromneeds); evaltex[fromobj->u.obj.texture->typ]( fromobj->u.obj.texture,fromchanges,&frommat); } texinfo.material = obj2mat(hit_obj); hitmat = *texinfo.material; if (hitchanges != MATPAR_NONE) { hitcoord[hit_obj->typ](hit,hitneeds); evaltex[hit_obj->u.obj.texture->typ]( hit_obj->u.obj.texture,hitchanges,&hitmat); } texinfo.material = obj2mat(toobj); tomat = *texinfo.material; if (tochanges != MATPAR_NONE) { pntcoord[toobj->typ](toobj,toneeds); evaltex[toobj->u.obj.texture->typ]( toobj->u.obj.texture,tochanges,&tomat); } if (fromobj == hit_obj) /* temporary patch by wRZL */ frommat = hitmat; else if (hit_obj == toobj) tomat = hitmat; material2surface(&frommat,&hitmat,&tomat,surface); } } /* ------------------------------------------------------------------------ reflectdirection ------------------------------------------------------------------------ -> ndotv dot product of normal and normalized vector from point to eye (always >= 0.0) -> ray defines the geometry of incoming ray -> normal normal of the plane on which to reflect the ray ------------------------------------------------------------------------ <- reflect normalized, reflected ray ------------------------------------------------------------------------ */ Static VOID reflectdirection(FLOAT ndotv,RAY3 *ray,VEC3 *normal,RAY3 *reflect) { ndotv = 2.0 * ndotv; v3addscaled(ray->direction,*normal,ndotv,reflect->direction); v3invdir(reflect->direction,reflect->inv_dir); } /* ------------------------------------------------------------------------ transmitdirection ------------------------------------------------------------------------ -> eta refraction index of transition -> cosphi1 dot product of normal and normalized vector from point to eye -> cosphi2 dot product of normal and normalized vector in the direction of the transission ray -> ray defines the geometry of incoming ray -> normal normal of the plane on which to reflect the ray ------------------------------------------------------------------------ <- reflect normalized, reflected ray ------------------------------------------------------------------------ This procedure does not check for total internal reflection. It must only be called if there is a refraction ray ------------------------------------------------------------------------ */ Static VOID transmitdirection(FLOAT eta,FLOAT cosphi1,FLOAT cosphi2,RAY3 *ray, VEC3 *normal,RAY3 *transmit) { /* ------------------------ we use cosphi2 for another temporary value: */ cosphi2 = eta * cosphi1 - cosphi2; v3add2scaled(ray->direction,eta,*normal,cosphi2,transmit->direction); v3invdir(transmit->direction,transmit->inv_dir); } /* ------------------------------------------------------------------------ shadowtrace ------------------------------------------------------------------------ -> ray ray from point to lightsource -> len length of this ray -> fromobj the obj where we start from ------------------------------------------------------------------------ <- attenuation ------------------------------------------------------------------------ shoots the lightray and accumulates the absorptions found in the hitlist ------------------------------------------------------------------------ */ Static VOID shadowtrace(RAY3 *ray,FLOAT len,OBJECT *fromobj,LIGHT *light, COLOR *attenuation) { HITLIST hitlist; rays.shadow++; if (raycast(ray,0.0,len,fromobj,FALSE,TRUE,light,&hitlist)) { COLOR rest; HITINFO *hit; HITINFO *nexthit; hit = hitlist.first; nexthit = hit; /* we do not want to destroy hit */ /* ------------------------ we begin by checking for opaque objects */ while (nexthit != NULL) { if (nexthit->newobj != NULL && opaquematerial(nexthit->newobj->u.obj.material)) { releasehitlists(&hitlist); colorinit(*attenuation,0.0); return; } nexthit = nexthit->next; } /* -------- now only transparent obj's are between me and the light */ absorbmaterial(obj2mat(fromobj),hit->t,attenuation); nexthit = hit->next; while (nexthit != NULL) { absorbmaterial(obj2mat(hit->newobj),nexthit->t - hit->t,&rest); colormult(*attenuation,rest,*attenuation); hit = nexthit; nexthit = nexthit->next; } absorbmaterial(obj2mat(hit->newobj),len - hit->t,&rest); colormult(*attenuation,rest,*attenuation); releasehitlists(&hitlist); } else { absorbmaterial(obj2mat(fromobj),len,attenuation); } } /* ------------------------------------------------------------------------ raytrace ------------------------------------------------------------------------ -> weight influence of current ray in overall color -> ray the ray geometry -> fromobj object we come from ------------------------------------------------------------------------ <- color color value returned by this ray ------------------------------------------------------------------------ recursive raytrace function that evaluates the color of the object hit by the given ray ------------------------------------------------------------------------ */ VOID raytrace(FLOAT weight,RAY3 *ray,OBJECT *fromobj,COLOR *color) { BOOLEAN primary; HITLIST hitlist; raytracelevel++; primary = (raytracelevel == 1) ? TRUE : FALSE; if (raycast(ray,0.0,F_HUGE,fromobj,primary,FALSE,NULL,&hitlist)) { FLOAT ndotv; /* equals cosphi1 */ FLOAT minus_ndott; /* equals cosphi2 */ FLOAT k; FLOAT inverse_index; COLOR attenuation; COLOR absorption; VEC3 normal; PNT3 point; OBJECT *toobj; HITINFO *hit; SURFACE surface; BOOLEAN opaque; hit = hitlist.first; toobj = hit->newobj; /* eventually the hitlist will be freed ! */ absorbmaterial(obj2mat(fromobj),hit->t,&absorption); weight *= colormax(absorption); /* do that early ... */ if (weight <= global_scene->min_contribution) /* ...for possible...*/ { colorinit(*color,0.0); /* we're black, jack */ releasehitlists(&hitlist); raytracelevel--; return; /* ... speedup ! */ } v3addscaled(ray->origin,ray->direction,hit->t,point); #ifdef DB_RTFACE if (hit->face == 0L) { message(" WARNING: raytrace: hit->face == 0L !\n"); message(" level: %4d, fromobj: %8lx\n",raytracelevel,fromobj); dumphitlist(&hitlist); } #endif normalvec[hit->obj->typ](hit); normal = hit->normal; /* as hitlist will be freed */ ndotv = v3dot(ray->direction,normal); /* ------------------------ ndotv has the wrong sign at the moment! */ if (ndotv > 0.0) { v3negate(normal); /* either negate normal ... */ } else ndotv = -ndotv; /* or correct sign of ndotv */ #ifdef DB_RTNULL if (fromobj == NULL && toobj == NULL) fatal("raytrace both obj's are NULL"); #endif if (global_scene->texturing) do_texture(fromobj,hit,toobj,&point,ndotv,&normal,&surface); else material2surface(obj2mat(fromobj),obj2mat(hit->obj), obj2mat(toobj),&surface); releasehitlists(&hitlist); /* now the hitinfos have been evaluated */ if (toobj == NULL) opaque = opaquematerial(global_material); else opaque = opaquematerial(toobj->u.obj.material); emissionsurface(&surface,color); /* init with emission */ block { RAY3 actray; FLOAT ndotl,ldotv; LIGHT *light; FLOAT len; COLOR specular,lightcolor; for (light = global_lights; light != NULL; light = light->next) { if (light->typ == LIGHT_AMBIENT) /* special: */ { /* has no position */ COLOR ambient; colormultk(light->color,ndotv,lightcolor); ambientsurface(&surface,&ambient); colormult(lightcolor,ambient,lightcolor); coloradd(*color,lightcolor,*color); continue; } /********************************************/ /* for all lights - ASTLEITNER / GASSNER */ /********************************************/ { UINT loop; COLOR tmp_col; UINT scan; if (!(scan = lightinit[light->typ](light) )) continue; colorinit (tmp_col, 0.0); /* Reset temp. color */ for (loop = 0; loop < scan; loop ++) { /* len is distance of point to random point on luminaire */ len = lightray[light->typ](light, &point, &actray); if (f_iszero(len)) continue; ndotl = v3dot(normal, actray.direction); /* --- check if we are on the shadow-side of the object */ if (toobj != NULL && ndotl < 0.0 && opaque) continue; ldotv = - v3dot(actray.direction, ray->direction); diffusesurface(&surface, ndotl, &attenuation); specularsurface(&surface, ldotv, ndotl, ndotv, &specular); coloradd(attenuation, specular, attenuation); actray.origin = point; /* -------------------- calculate light intensity/color */ lightintensity[light->typ](light, &actray, len, &lightcolor); colormult(lightcolor, attenuation, attenuation); k = colormax(attenuation); if (weight * k > global_scene->min_contribution) { if (global_scene->shadow_rays) { v3invdir(actray.direction, actray.inv_dir); if (ndotl > 0.0) shadowtrace(&actray, len, fromobj, light, &lightcolor); else shadowtrace(&actray, len, toobj, light,&lightcolor); colormult(attenuation, lightcolor, lightcolor); } else lightcolor = attenuation; coloradd(tmp_col, lightcolor, tmp_col); } /* if weight ...*/ } /* scan thru light-object w/ monte carlo */ /* Add temporary color to global color */ colormultk (tmp_col, 1.0 / (FLOAT) scan, tmp_col); coloradd(*color, tmp_col, *color); } /* block parsing thru lights */ /* *** end of GW - Modification *** */ } } inverse_index = invindexsurface(&surface); minus_ndott = 1.0 - inverse_index * inverse_index * (1.0 - ndotv * ndotv); /* square of minus_ndott (some illumination models */ /* need this value in reflectsurface to detect TIR) */ if (raytracelevel < global_scene->max_reflection) { reflectsurface(&surface,ndotv,minus_ndott,&attenuation); k = colormax(attenuation); /* is really ks */ if (weight * k > global_scene->min_contribution) { RAY3 reflect; COLOR rcolor; reflect.origin = point; reflectdirection(ndotv,ray,&normal,&reflect); rays.reflect++; raytrace(weight * k,&reflect,fromobj,&rcolor); colormult(attenuation,rcolor,rcolor); coloradd(*color,rcolor,*color); } } if (raytracelevel < global_scene->max_refraction && ! opaque && minus_ndott > 0.0) { /* no total internal reflection */ minus_ndott = f_sqrt(minus_ndott); /* now real minus_ndott */ refractsurface(&surface,ndotv,minus_ndott,&attenuation); k = colormax(attenuation); /* is really kt */ if (weight * k > global_scene->min_contribution) { RAY3 transmit; COLOR tcolor; transmit.origin = point; transmitdirection(inverse_index,ndotv,minus_ndott,ray, &normal,&transmit); rays.refract++; raytrace(weight * k,&transmit,toobj,&tcolor); colormult(attenuation,tcolor,tcolor); coloradd(*color,tcolor,*color); } } colormult(absorption,*color,*color); } else { absorbmaterial(obj2mat(fromobj),F_HUGE,color); if(global_enviro != NULL) { COLOR env_col; hitenvironment(ray, &env_col); colormult(*color,env_col,*color); } else colormult(*color,global_background,*color); } raytracelevel--; } ,tcolor,tcolor); coloradd(*color,tcolor,*color); } } colormult(absorption,*color,*color); } else { absorbmaterial(obj2mat(fromobj),F_HUGE,color); if(global_enviro != NULL) { COLOR env_col; hitenvironment(ray, &env_col);Flirt/raytrace.f000644 000316 000311 00000001153 06103226622 013736 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : raytrace.f calculate color coming from the direction of a ray DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef RAYTRACE_F #define RAYTRACE_F #include "objects.d" Extern COLOR global_background; Extern UINT raytracelevel; VOID raytrace PP((FLOAT weight, RAY3 *ray, OBJECT *fromobj, COLOR *color)); #endif DULE : raytrace.f calculate color coming from the direction of a ray DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef RAYTRACE_F #define RAYTRACE_F #include "objects.d" Extern COLOR global_background; ExternFlirt/readdata.c000644 000316 000311 00000034424 06114641220 013672 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : readdata.c read the datafile DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include #define STDIO_H #include #define STRING_H #ifdef VAX #include #define STDLIB_H #endif #include "flirt.f" #include "geometr3.f" #include "camera.f" #include "color.f" #include "setup.f" #include "symbols.f" #include "material.f" #include "texture.f" #include "environm.f" #include "light.f" #include "scene.f" #include "objects.f" #include "raytrace.f" #include "readdata.f" #define MAXTOKENLENGTH 40 #define isdigit(c) ((c >= '0' && c <= '9') || c == '-') #define isalpha(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) UINT linenumber = 0; UCHAR *token = NULL; Static UINT linenumberstore = 0; Static UCHAR Const *seperators = " \t"; Static UCHAR inputline[256]; Static UCHAR Const *includeprefix = NULL; Static MATERIALTYP materialtyp; Static FILE *inputfilestore = NULL; Static FILE *inputfile = NULL; VOID open_read(UCHAR Const *filename,UCHAR Const *includepath) { if (inputfile != NULL) fatal("can't read more than one file at once"); inputfile = fopen(filename,"r"); if (inputfile == NULL) fatal("can't open file '%s'",filename); includeprefix = includepath; nexttoken(); } VOID close_read(VOID) { if (inputfile != NULL) fclose(inputfile); inputfile = NULL; } VOID nexttoken(VOID) { if (token != NULL) /* next token please */ token = strtok(NULL,seperators); if (token == NULL) /* need a new line ! */ { UINT i,len; UCHAR *cmt; BOOLEAN skip = FALSE; do { if (fgets(inputline,250,inputfile) == NULL) /* EOF */ { if (inputfilestore != NULL) /* return from include file */ { fclose(inputfile); inputfile = inputfilestore; inputfilestore = NULL; /* no more there */ linenumber = linenumberstore; len = 0; /* to force the next read */ skip = FALSE; /* end of IF */ continue; } token = NULL; return; } linenumber++; cmt = strchr(inputline,'%'); /* comment in line ? */ if (cmt != NULL) *cmt = '\0'; /* delete comments */ len = (UINT)strlen(inputline); /* clean whitspace at eol */ while (len > 0 && (inputline[len - 1] == '\n' || inputline[len - 1] == '\r' || inputline[len - 1] == '\033' || inputline[len - 1] == ' ' || inputline[len - 1] == '\t')) { len--; inputline[len] = '\0'; } if (inputline[0] == '#') { if (strncmp(inputline + 1,"include",7) == 0) { UCHAR includefilename[100]; if (inputfilestore != NULL) fatal("line %d: no recursive include allowed", linenumber); inputfilestore = inputfile; linenumberstore = linenumber; if (includeprefix != NULL) strcpy(includefilename,includeprefix); else includefilename[0] = '\0'; strcat(includefilename,inputline + 9); message(" including file '%s'\n",includefilename); inputfile = fopen(includefilename,"r"); if (inputfile == NULL) fatal("line %d: can't open includefile '%s'", linenumber,includefilename); linenumber = 0; len = 0; /* to force the next read */ continue; } if (strncmp(inputline + 1,"if",2) == 0) { if (strncmp(inputline + 4,"riss",4) == 0 && materialtyp == RISSMATERIALS) skip = FALSE; else if (strncmp(inputline + 4,"standard",8) == 0 && materialtyp == STANDARDMATERIALS) skip = FALSE; else if (strncmp(inputline + 4,"simple",6) == 0 && materialtyp == SIMPLEMATERIALS) skip = FALSE; else if (strncmp(inputline + 4,"true",4) == 0) skip = FALSE; else skip = TRUE; len = 0; /* to force the next read */ continue; } if (strncmp(inputline + 1,"endif",5) == 0) { skip = FALSE; len = 0; /* to force the next read */ continue; } } if (skip) /* -> active if false */ { len = 0; /* to force the next read */ continue; } } while (len == 0); /* there are empty lines ! */ for (i = 0; i < len; i++) /* convert to lowercase */ { if (inputline[i] >= 'A' && inputline[i] <= 'Z') inputline[i] += 'a' - 'A'; } token = strtok(inputline,seperators); /* read first word */ } } BOOLEAN readbool(VOID) { BOOLEAN result = FALSE; if (token == NULL) fatal("line %d: boolean expexted",linenumber); if (*token == 't' || *token == 'y' || *token == 'j') result = TRUE; nexttoken(); return(result); } UINT readuint(VOID) { UINT result = 0; if (token == NULL || ! isdigit(*token)) fatal("line %d: int expexted",linenumber); result = strtouint(token); nexttoken(); return(result); } DOUBLE readreal(VOID) { DOUBLE result = 0.0; if (token == NULL || (*token != '-' && *token != '.' && ! isdigit(*token))) fatal("line %d: real expexted",linenumber); result = strtodouble(token); nexttoken(); return(result); } VOID readconststring(UCHAR Const *string) { if (token == NULL || strcmp(token,string) != 0) fatal("line %d: %s expected",linenumber,string); nexttoken(); } BOOLEAN matchconststring(UCHAR Const *string) { if (token == NULL || strcmp(token,string) != 0) return(FALSE); return(TRUE); } BOOLEAN matchreadconststring(UCHAR Const *string) { if (token == NULL || strcmp(token,string) != 0) return(FALSE); nexttoken(); /* consume token */ return(TRUE); } BOOLEAN nextisnumeric(VOID) { if (token != NULL && ((*token >= '0' && *token <= '9') || *token == '-' || *token == '.')) return(TRUE); return(FALSE); } BOOLEAN nextisvalidname(VOID) { UINT i; if (token == NULL || ! isalpha(*token)) return(FALSE); for (i = 1; token[i] != '\0'; i++) { if (! (isalpha(token[i]) || isdigit(token[i]) || token[i] == '_')) return(FALSE); } return(TRUE); } UINT readnameconst(CONSTTYP typ,BOOLEAN fatal_on_error) { UINT value; if (token == NULL) { if (fatal_on_error) fatal("line %d: unexpected end of file",linenumber); return(NOCONST); } value = lookup(typ,token); if (value == NOCONST) { if (fatal_on_error) fatal("line %d: unknown %s '%s'",linenumber,constname(typ),token); return(value); } nexttoken(); return(value); } VOIDPTR readnameinfo(INFOTYP typ,BOOLEAN fatal_on_error) { VOIDPTR info; if (token == NULL) { if (fatal_on_error) fatal("line %d: unexpected end of file",linenumber); return(NULL); } info = findname(typ,token); if (info == NULL) { if (fatal_on_error) fatal("line %d: unknown %s '%s'",linenumber,infoname(typ),token); return(info); } nexttoken(); return(info); } /******************************************************************************/ VOID readdata(UCHAR Const *filename,UCHAR Const *includepath, MATERIALTYP material) { BOOLEAN notready = TRUE; UCHAR lightsname[MAXTOKENLENGTH]; UCHAR objectname[MAXTOKENLENGTH]; UCHAR tokenstore[MAXTOKENLENGTH]; MATERIAL *defmat; /* GR eingefuegt */ linenumber = 0; token = NULL; linenumberstore = 0; includeprefix = NULL; inputfilestore = NULL; inputfile = NULL; materialtyp = material; message("\nREADING INPUT FILE(S):\n"); open_read(filename,includepath); message(" reading file '%s'\n",filename); readconststring("global"); global_scene = readnamescene(); global_camera = readnamecamera(); readconststring(lookupstring(CONST_DATA,DATA_LIGHTS)); strcpy(lightsname,token); nexttoken(); global_lights = NULL; readconststring(lookupstring(CONST_DATA,DATA_OBJECT)); strcpy(objectname,token); nexttoken(); global_object = NULL; global_material = readnamematerial(); if (matchreadconststring("background")) readcolor(&global_background); else colorinit(global_background,0.0); if (matchreadconststring("environment")) global_enviro = readnameenvironment(); else global_enviro = NULL; while (notready) { switch(readnameconst(CONST_DATA,FALSE)) { case DATA_SCENE: { SCENE dummyscene; SCENE *newscene; newscene = (SCENE *) clearfindname(INFO_SCENE,token); nexttoken(); if (newscene == NULL) newscene = &dummyscene; readscene(newscene); break; } case DATA_ENVIRONMENT: { ENVIRONMENT *locenv; locenv = (ENVIRONMENT *) clearfindname(INFO_ENVIRONMENT, token); nexttoken(); if(locenv != NULL) readenvironment(locenv); readconststring("end"); break; } case DATA_CAMERA: { CAMERA dummycamera; CAMERA *newcamera; newcamera = (CAMERA *) clearfindname(INFO_CAMERA,token); nexttoken(); if (newcamera == NULL) newcamera = &dummycamera; readcamera(newcamera); break; } case DATA_LIGHTS: { strcpy(tokenstore,token); nexttoken(); if (strcmp(tokenstore,lightsname) == 0) global_lights = readlights(TRUE); else #ifdef __STDC__ (VOID) ((LONG) readlights(FALSE)); /* I hate MS-DOS !! */ #else readlights(FALSE); #endif readconststring("end"); break; } case DATA_POINTS: { POINTARRAY *locpoints; strcpy(tokenstore,token); nexttoken(); locpoints = readpointarray(); savename(INFO_POINTS,tokenstore,(VOIDPTR) locpoints); break; } case DATA_ATTRIBUTE: { /*readvariables();*/ fatal("not in this version"); break; } case DATA_TEXTURE: { TEXTURE *loctexture; strcpy(tokenstore,token); nexttoken(); loctexture = readtexture(); savename(INFO_TEXTURE,tokenstore,(VOIDPTR) loctexture); readconststring("end"); break; } case DATA_OBJECT: { OBJECT *locobject; strcpy(tokenstore,token); nexttoken(); if (strcmp(tokenstore,objectname) == 0) global_object = readobjects(); else { locobject = readobjects(); savename(INFO_OBJECT,tokenstore,(VOIDPTR) locobject); } readconststring("end"); break; } case DATA_MATERIAL: { MATERIAL *mater; MATERIAL dummymaterial; mater = (MATERIAL *) clearfindname(INFO_MATERIAL,token); nexttoken(); if (mater == NULL) mater = &dummymaterial; readmaterial(mater); break; } case DATA_COLOR: break; case NOCONST: { if (token != NULL) fatal("line %d: unknown datatyp %s",linenumber,token); notready = FALSE; } } } defmat = (MATERIAL *)clearfindname(INFO_MATERIAL,"default"); if (defmat != NULL) defaultmaterial(defmat); if (global_lights == NULL) fatal("couldn't find lights '%s'",lightsname); if (global_object == NULL) fatal("couldn't find object '%s'",objectname); clearnames(); close_read(); } if (token != NULL) fatal("line %d: unknown datatyp %s",linenumber,token); notready = FALSE; } } } defmat = (MATERIAL *)clearfindname(INFO_MATERIAL,"default");Flirt/readdata.f000644 000316 000311 00000004653 06103226624 013703 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : readdata.f Input file handling DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef READDATA_F #define READDATA_F #include "objects.d" #include "symbols.d" #define match_read_bool(s,v) { readconststring(s); v = readbool(); } #define match_read_uint(s,v) { readconststring(s); v = readuint(); } #define match_read_real(s,v) { readconststring(s); v = readreal(); } #define option_read_bool(s,v,default) \ { \ if (matchreadconststring(s)) \ (v) = readbool(); \ else \ (v) = (default); \ } #define option_read_uint(s,v,default) \ { \ if (matchreadconststring(s)) \ (v) = readuint(); \ else \ (v) = (default); \ } #define option_read_real(s,v,default) \ { \ if (matchreadconststring(s)) \ (v) = readreal(); \ else \ (v) = (default); \ } Extern UINT linenumber; Extern UCHAR *token; VOID open_read PP((UCHAR Const *filename,UCHAR Const *includepath)); VOID close_read PP((VOID)); VOID nexttoken PP((VOID)); BOOLEAN readbool PP((VOID)); UINT readuint PP((VOID)); DOUBLE readreal PP((VOID)); VOID readconststring PP((UCHAR Const *text)); BOOLEAN matchconststring PP((UCHAR Const *text)); BOOLEAN matchreadconststring PP((UCHAR Const *text)); BOOLEAN nextisnumeric PP((VOID)); BOOLEAN nextisvalidname PP((VOID)); UINT readnameconst PP((CONSTTYP typ,BOOLEAN fatal_on_error)); VOIDPTR readnameinfo PP((INFOTYP typ,BOOLEAN fatal_on_error)); VOID readdata PP((UCHAR Const *filename,UCHAR Const *includepath, MATERIALTYP material)); #endif readreal PP((VOID)); VOID readconststring PP((UCHAR Const *text)); BOOLEAN matchconstFlirt/repeat.c000644 000316 000311 00000021030 06103226530 013373 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : repeat.c routines for repeat-objects DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "objects.f" #include "readdata.f" #include "writdata.f" #include "repeat.f" Static OBJECT *readrepeat(VOID) { UINT i; OBJECT *obj; obj = newonlyvar(OBJECT,REPEATEDOBJ); obj->typ = REPEATED_OBJECT; match_read_uint("number",obj->u.repeated.number); obj->u.repeated.vec = (VEC3 *) newonlymem(sizeof(VEC3) * obj->u.repeated.number); obj->u.repeated.vec[0] = V3ZERO; readconststring("vector"); readvec3(&(obj->u.repeated.vec[1])); for (i = 2; i < obj->u.repeated.number; i++) { v3multk(obj->u.repeated.vec[1],i,obj->u.repeated.vec[i]); } obj->u.repeated.original = readobjects(); return(obj); } Static OBJECT *copyrepeat(OBJECT *obj,BOOLEAN recurse,MAT3 *obj2world, MAT3 *world2obj,MATERIAL *mat,TEXTURE *tex) { UINT i; OBJECT *newobj; newobj = newonlyvar(OBJECT,REPEATEDOBJ); newobj->typ = obj->typ; newobj->u.csg.in_or_tree = obj->u.csg.in_or_tree; newobj->u.repeated.number = obj->u.repeated.number; newobj->u.repeated.vec = (VEC3 *) newonlymem(sizeof(VEC3) * obj->u.repeated.number); newobj->u.repeated.vec[0] = V3ZERO; v3vmulm(obj->u.repeated.vec[1],*obj2world,newobj->u.repeated.vec[1]); for (i = 2; i < obj->u.repeated.number; i++) { v3multk(newobj->u.repeated.vec[1],i,newobj->u.repeated.vec[i]); } if (recurse) newobj->u.repeated.original = copyobj[obj->u.repeated.original->typ](obj->u.repeated.original, TRUE,obj2world, world2obj,mat,tex); else newobj->u.repeated.original = obj->u.repeated.original; return(newobj); } Static VOID writerepeat(OBJECT *obj) { write_string_uint("number",obj->u.repeated.number); writestring("vector"); writevec3(&(obj->u.repeated.vec[1])); writeobjects(obj->u.repeated.original); } Static BYTE hiboundmask; Static BYTE loboundmask; Static VEC3 hull[8]; Static VEC3 center; Static VOID boundrepeat(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { OBJECT *original; VEC3 *vec; original = obj->u.repeated.original; boundobj[original->typ](original,bbox_test,bsphere_test,bounds_test, bbox,bsphere,bounds); obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? TRUE : FALSE; obj->bounds = (bounds_test) ? original->bounds : NULL; /* make large boundingbox */ vec = obj->u.repeated.vec + obj->u.repeated.number - 1; hiboundmask = BOUNDTEST_NONE; loboundmask = BOUNDTEST_NONE; obj->bbox = original->bbox; if (vec->x > F_SMALL) { obj->bbox.max.x += vec->x; hiboundmask |= BOUNDTEST_XMAX; loboundmask |= BOUNDTEST_XMIN; } else if (vec->x < -F_SMALL) { obj->bbox.min.x += vec->x; hiboundmask |= BOUNDTEST_XMIN; loboundmask |= BOUNDTEST_XMAX; } if (vec->y > F_SMALL) { obj->bbox.max.y += vec->y; hiboundmask |= BOUNDTEST_YMAX; loboundmask |= BOUNDTEST_YMIN; } else if (vec->y < -F_SMALL) { obj->bbox.min.y += vec->y; hiboundmask |= BOUNDTEST_YMIN; loboundmask |= BOUNDTEST_YMAX; } if (vec->z > F_SMALL) { obj->bbox.max.z += vec->z; hiboundmask |= BOUNDTEST_ZMAX; loboundmask |= BOUNDTEST_ZMIN; } else if (vec->z < -F_SMALL) { obj->bbox.min.z += vec->z; hiboundmask |= BOUNDTEST_ZMIN; loboundmask |= BOUNDTEST_ZMAX; } obj->u.repeated.hiboundmask = hiboundmask; obj->u.repeated.loboundmask = loboundmask; hull[0] = original->bbox.min; hull[1] = original->bbox.min; hull[1].x = original->bbox.max.x; hull[2] = original->bbox.min; hull[2].y = original->bbox.max.y; hull[3] = original->bbox.min; hull[3].z = original->bbox.max.z; hull[4] = original->bbox.max; hull[4].x = original->bbox.min.x; hull[5] = original->bbox.max; hull[5].y = original->bbox.min.y; hull[6] = original->bbox.max; hull[6].z = original->bbox.min.z; hull[7] = original->bbox.max; v3add(hull[0],hull[7],center); v3scale(center,0.5); bounds4points(8,hull,NULL,&(obj->bsphere),¢er,NULL); *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static ULONG setuprepeat(OBJECT *obj,BOOLEAN in_or_tree,BOOLEAN space_opt) { ULONG objcount; objcount = setupobjects(obj->u.repeated.original,in_or_tree,FALSE); return(objcount); } Static OBJECT *insiderepeat(PNT3 *pnt,OBJECT *obj) { UINT i; OBJECT *result; PNT3 locpnt; locpnt = *pnt; for (i = 0; i < obj->u.repeated.number; i++) { result = inside[obj->u.repeated.original->typ](&locpnt, obj->u.repeated.original); if (result != NULL) return(result); v3subfrom(locpnt,obj->u.repeated.vec[1]); } return(NULL); } Static OBJECT *repobj; Static BOOLEAN hitreps(UINT n,VEC3 *vec,FLOAT tmin,FLOAT tmax,HITLIST *hitlist) { if (n == 1) { BOOLEAN ray_hit_obj; VEC3 origin; origin = rci.ray.origin; v3subfrom(rci.ray.origin,*vec); HITOBJ(repobj,tmin,tmax,hitlist,ray_hit_obj); rci.ray.origin = origin; return(ray_hit_obj); } else { FLOAT tmin1,tmax1; HITLIST lefthitlist; UINT j = n/2; UINT i = n - j; /* bounding box tests at hibound(i-1) and lobound(i) */ lefthitlist = emptyhitlist; tmin1 = tmin; tmax1 = tmax; if (hitshiftbbox(&rci.ray,&tmin1,&tmax1,hiboundmask, vec + i - 1,&repobj->bbox) && hitreps(i,vec,tmin1,tmax1,&lefthitlist)) { HITLIST righthitlist; righthitlist = emptyhitlist; if (hitshiftbbox(&rci.ray,&tmin,&tmax,loboundmask, vec + i,&repobj->bbox) && hitreps(j,vec + i,tmin,tmax,&righthitlist)) return orhitlists(&lefthitlist,&righthitlist,hitlist); if (righthitlist.firstobj != NULL) replacenull(&lefthitlist,righthitlist.firstobj); *hitlist = lefthitlist; } else { if (lefthitlist.firstobj == NULL) { if (hitshiftbbox(&rci.ray,&tmin,&tmax,loboundmask, vec + i,&repobj->bbox) && hitreps(j,vec + i,tmin,tmax,hitlist)) return(TRUE); return (FALSE); } *hitlist = lefthitlist; return(FALSE); } return(TRUE); } } Static BOOLEAN hitrepeat(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) { repobj = obj->u.repeated.original; hiboundmask = obj->u.repeated.hiboundmask; loboundmask = obj->u.repeated.loboundmask; return(hitreps(obj->u.repeated.number,obj->u.repeated.vec,tmin,tmax, hitlist)); } Static VOID endrepeat(OBJECT *obj) { endobj[obj->u.repeated.original->typ](obj->u.repeated.original); } VOID initrepeat(VOID) { nameobj[REPEATED_OBJECT] = "repeat"; readobj[REPEATED_OBJECT] = readrepeat; copyobj[REPEATED_OBJECT] = copyrepeat; writeobj[REPEATED_OBJECT] = writerepeat; boundobj[REPEATED_OBJECT] = boundrepeat; setupobj[REPEATED_OBJECT] = setuprepeat; splitobj[REPEATED_OBJECT] = split_primitiv; /* FIXME: could be improved */ inside[REPEATED_OBJECT] = insiderepeat; hitobj[REPEATED_OBJECT] = hitrepeat; endobj[REPEATED_OBJECT] = endrepeat; } ; } VOID initrepeat(VOID) { nameobj[REPEATED_OBJECT] = "repeat"; readobj[REPEATED_OBJECT] = readrepeat; copyobj[REPEATED_OBJECT] = copyrepeat; writeobj[REPEATED_OBJECT] = writerepeat; boundobj[REPEATED_OBJECT] = boundrepeat; setupobj[REPEATED_OBJECT] = setuprepeat; splitobj[REPEATED_OBJECT] = split_primitiv; /* FIXME: could be improved */ inside[REPEATED_OBJECT] = insiderepeat; hitobj[REPEATED_OBJECT] = hitrepeat; endobj[REPEATED_OBJEFlirt/repeat.f000644 000316 000311 00000000756 06103226624 013416 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : repeat.f classification routines for repeated objects DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef REPEAT_F #define REPEAT_F #include "system.d" VOID initrepeat PP((VOID)); #endif dobj[REPEATED_OBJEFlirt/rgbinout.c000644 000316 000311 00000001700 06114637705 013762 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : rgbinout.c RGB-Handling DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "rgbinout.f" VOID rgbopenwrite (UCHAR Const *filename,RGBFILE *pd,INT b,INT h,DOUBLE v) { pd->f = fopen(filename,"w"); if (pd->f == NULL) { fatal("couldn't open %s",filename); return; } fprintf(pd->f,"P6\n%d %d\n255\n",b,h); } VOID rgbwrite(RGBFILE *pd,BYTE r,BYTE g,BYTE b) { fwrite(&r,1,1,pd->f); fwrite(&g,1,1,pd->f); fwrite(&b,1,1,pd->f); } VOID rgbflush(RGBFILE *pd) { fflush(pd->f); } VOID rgbclose (RGBFILE *pd) { fclose(pd->f); } ite (UCHAR Const *filename,RGBFILE *pd,INT b,INT h,DOUBLE v) Flirt/rgbinout.d000644 000316 000311 00000001043 06114637742 013764 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : rgbinout.d Header file for RGB-Handling DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef RGBINOUT_D #define RGBINOUT_D #include #include "system.d" #include "flirt.d" typedef struct { FILE *f; } RGBFILE; #endif ******************************************* PROJECT : flirt MODULE : rgbinout.d Header file for RGB-Handling DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef RGBINOUT_D #define RGBINOUT_D #include #include "system.d" #include "flirt.d" typedef struct { FIFlirt/rgbinout.f000644 000316 000311 00000001225 06114637756 013775 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : rgbinout.f Header file for RGB-Handling DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef RGBINOUT_F #define RGBINOUT_F #include "rgbinout.d" VOID rgbopenwrite PP((UCHAR Const *filename,RGBFILE *pd,INT b,INT h,DOUBLE v)); VOID rgbwrite PP((RGBFILE *pd, BYTE r, BYTE g, BYTE b)); VOID rgbflush PP((RGBFILE *pd)); VOID rgbclose PP((RGBFILE *pd)); #endif RGB-Handling DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef RGBINOUT_F #define RGBINOUT_F #include "rgbinout.d" VOID rgbopenwrite PP((UCHAR Const *filename,RGBFILE *pd,INT b,IFlirt/rissmat.c000644 000316 000311 00000051750 06103226532 013613 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : rissmat.c shading functions DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version 100491 wrzl,rft checked the darned thing (found 1 bug !) *****************************************************************************/ #include "flirt.f" #include "color.f" #include "material.f" #include "readdata.f" #include "writdata.f" #include "rissmat.f" #define IND 5.828427125 Static RISSMAT defaultrissmaterial = { TRUE, { 0.5, 0.5, 0.5 }, 1.0, 1.0, { 1.0, 1.0, 1.0 }, 0.0, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }, { IND, IND, IND }, { { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } }, }; Static VOID diffusereflection PP((COLOR *extinction,COLOR *refraction, COLOR *diffuse)); Static VOID defaultrissmat(MATERIAL *def) { def->riss = defaultrissmaterial; } Static MATERIAL *newrissmat(VOID) { MATERIAL *material = newonlyuni(MATERIAL,RISSMAT); return(material); } Static VOID readrissmat(MATERIAL *material) { UINT i; match_read_real("specular", material->riss.specular); match_read_real("refract_index", material->riss.refract_index); if (matchreadconststring("diffuse")) readcolor(&(material->riss.diffuse)); else { colorinit(material->riss.diffuse,-1.0); } readconststring("extinction"); readcolor(&(material->riss.extinction)); readconststring("absorption"); readcolor(&(material->riss.absorption)); readconststring("emission"); readcolor(&(material->riss.emission)); readconststring("refraction"); readcolor(&(material->riss.refraction)); readconststring("facets"); for (i = 0; i < FACETSAMPLES; i++) material->riss.facets.sample[i] = readreal(); } Static VOID writerissmat(MATERIAL *material) { UINT i; write_string_real("specular", material->riss.specular); write_string_real("refract_index", material->riss.refract_index); writestring("diffuse"); writecolor(&(material->riss.diffuse)); writestring("extinction"); writecolor(&(material->riss.extinction)); writestring("absorption"); writecolor(&(material->riss.absorption)); writestring("emission"); writecolor(&(material->riss.emission)); writestring("refraction"); writecolor(&(material->riss.refraction)); writestring("facets"); for (i = 0; i < FACETSAMPLES / 2; i++) writereal(material->riss.facets.sample[i]); writelf(); for (i = FACETSAMPLES / 2; i < FACETSAMPLES; i++) writereal(material->riss.facets.sample[i]); writelf(); } Static VOID setuprissmat(MATERIAL *material) { if (colormax(material->riss.absorption) > 0.0) material->riss.opaque = FALSE; else material->riss.opaque = TRUE; material->riss.refract_index /= global_material->riss.refract_index; material->riss.inverse_index = 1.0 / material->riss.refract_index; colordiv(material->riss.refraction,global_material->riss.refraction, material->riss.refraction); colordiv(COLWHITE,material->riss.refraction,material->riss.invrefract); if (colormax(material->riss.diffuse) == -1.0) { diffusereflection(&(material->riss.extinction), &(material->riss.refraction), &(material->riss.diffuse)); } } /* ------------------------------------------------------------------------ absorptionfactor ------------------------------------------------------------------------ -> object the object the ray pierces -> length ------------------------------------------------------------------------ <- absorption ------------------------------------------------------------------------ calculates the absorption of a ray when going through a material for fog and haze we may need additional parameters !!! ------------------------------------------------------------------------ */ Static VOID absorbrissmat(MATERIAL *material, FLOAT length, COLOR *absorption) { if (length >= F_HUGE) { if (material->riss.absorption.r < 1.0) absorption->r = 0.0; else absorption->r = 1.0; if (material->riss.absorption.g < 1.0) absorption->g = 0.0; else absorption->g = 1.0; if (material->riss.absorption.b < 1.0) absorption->b = 0.0; else absorption->b = 1.0; } else { colorpowk(material->riss.absorption,length,*absorption); } /* ----------------------------- at this point: simulate fog, haze, ... */ } Static BOOLEAN opaquerissmat(MATERIAL *material) { return(material->riss.opaque); } /* ------------------------------------------------------------------------ diffusereflection ------------------------------------------------------------------------ -> extinction -> refraction ------------------------------------------------------------------------ <- diffuse ------------------------------------------------------------------------ calculates diffuse reflection coefficient from extinction coefficient and refraction indices (= fresnel with normal incidence) ------------------------------------------------------------------------ */ Static VOID diffusereflection(COLOR *extinction,COLOR *refraction, COLOR *diffuse) { FLOAT ext_2; FLOAT nm1; FLOAT np1; /* g = refraction: because d == 0, c == 1 */ ext_2 = extinction->r * extinction->r; nm1 = refraction->r - 1.0; np1 = refraction->r + 1.0; diffuse->r = (ext_2 + nm1 * nm1) / (ext_2 + np1 * np1); ext_2 = extinction->g * extinction->g; nm1 = refraction->g - 1.0; np1 = refraction->g + 1.0; diffuse->g = (ext_2 + nm1 * nm1) / (ext_2 + np1 * np1); ext_2 = extinction->b * extinction->b; nm1 = refraction->b - 1.0; np1 = refraction->b + 1.0; diffuse->b = (ext_2 + nm1 * nm1) / (ext_2 + np1 * np1); } Static VOID rissmatinterpol(MATERIAL *mat1,MATERIAL *mat2, FLOAT t,MATPAR changes,MATERIAL *material) { if (changes & RISS_SPECULAR) material->riss.specular = interpol(mat1->riss.specular, mat2->riss.specular,t); if (changes & RISS_ABSORPTION) { colorinterpol(mat1->riss.absorption,mat2->riss.absorption,t, material->riss.absorption); } if (changes & RISS_EMISSION) { colorinterpol(mat1->riss.emission,mat2->riss.emission,t, material->riss.emission); } if (changes & RISS_FACETS) { UINT i; for (i = 0; i < FACETSAMPLES; i++) material->riss.facets.sample[i] = interpol( mat1->riss.facets.sample[i], mat2->riss.facets.sample[i],t); } if (changes & RISS_DIFFUSE) { colorinterpol(mat1->riss.extinction,mat2->riss.extinction,t, material->riss.extinction); colorinterpol(mat1->riss.refraction,mat2->riss.refraction,t, material->riss.refraction); diffusereflection(&(material->riss.extinction), &(material->riss.refraction), &(material->riss.diffuse)); } } /* ------------------------------------------------------------------------ materialtosurface ------------------------------------------------------------------------ -> fromobj -> hit ------------------------------------------------------------------------ <- surface ------------------------------------------------------------------------ calaculates surface information at a transition between two objects ------------------------------------------------------------------------ */ Static VOID rissmat2surf(MATERIAL *frommaterial,MATERIAL *material, MATERIAL *tomaterial,SURFACE *surface) { if (tomaterial != global_material) { surface->riss.emission = tomaterial->riss.emission; surface->riss.extinction = tomaterial->riss.extinction; if (frommaterial == global_material) { surface->riss.diffuse = tomaterial->riss.diffuse; surface->riss.refract_index = tomaterial->riss.refract_index; surface->riss.inverse_index = tomaterial->riss.inverse_index; surface->riss.refraction_2 = tomaterial->riss.refraction; surface->riss.invrefract_2 = tomaterial->riss.invrefract; } else { surface->riss.refract_index = tomaterial->riss.refract_index / frommaterial->riss.refract_index; surface->riss.inverse_index = frommaterial->riss.refract_index / tomaterial->riss.refract_index; colordiv(frommaterial->riss.refraction, tomaterial->riss.refraction, surface->riss.invrefract_2); colordiv(tomaterial->riss.refraction, frommaterial->riss.refraction, surface->riss.refraction_2); diffusereflection(&surface->riss.extinction, &surface->riss.refraction_2,&surface->riss.diffuse); } } else { colorinit(surface->riss.emission,0.0); surface->riss.extinction = frommaterial->riss.extinction; surface->riss.diffuse = frommaterial->riss.diffuse; surface->riss.refract_index = frommaterial->riss.inverse_index; surface->riss.inverse_index = frommaterial->riss.refract_index; surface->riss.refraction_2 = frommaterial->riss.invrefract; surface->riss.invrefract_2 = frommaterial->riss.refraction; } /* ------------------- refraction and invrefract aren't squared yet !!! */ surface->riss.specular = material->riss.specular; surface->riss.facets = material->riss.facets; /* ----------------------------now square refraction and invrefract !!! */ colormult(surface->riss.refraction_2,surface->riss.refraction_2, surface->riss.refraction_2); colormult(surface->riss.invrefract_2,surface->riss.invrefract_2, surface->riss.invrefract_2); } Static VOID ambientrisssurf(SURFACE *surface,COLOR *attenuation) { *attenuation = surface->riss.diffuse; } Static VOID emissionrisssurf(SURFACE *surface,COLOR *attenuation) { *attenuation = surface->riss.emission; } /* ------------------------------------------------------------------------ geometricfactor ------------------------------------------------------------------------ -> two_ndoth cosine values and derivated values of the angles -> ndotv between N and H, N and V, N and L, V and H -> ndotl -> inv_vdoth ------------------------------------------------------------------------ <- attenuation factor ------------------------------------------------------------------------ calculate geometric shadowing/masking factor (Blinn 1977) check (t < 0.0) could be removed ! ------------------------------------------------------------------------ */ Static FLOAT geometricfactor(FLOAT ndoth,FLOAT ndotv,FLOAT ndotl,FLOAT vdoth) { FLOAT t; t = 2.0 * ndoth / vdoth; #ifdef DB_GEOMETRICF if (t < 0.0) { message("WARNING: geometricfactor - t < 0: %f\n",t); return 0.0; } #endif ndotv *= t; /* another misuse for temporary vars */ ndotl *= t; return mini(1.0,mini(ndotv,ndotl)); } /* ------------------------------------------------------------------------ fresnelattenuation ------------------------------------------------------------------------ -> c -> refraction_2 ------------------------------------------------------------------------ <- attenuation ------------------------------------------------------------------------ calculate fresnel factor in dependence of wavelength ------------------------------------------------------------------------ */ Static VOID fresnelattenuation(FLOAT c,COLOR *refraction_2,COLOR *attenuation) { FLOAT d,g,gp,gm,t1,t2; d = c * c - 1.0; g = refraction_2->r + d; if (g < 0.0) attenuation->r = 1.0; else { g = f_sqrt(g); gp = g + c; gm = g - c; t1 = c * gp - 1.0; t2 = c * gm + 1.0; attenuation->r = (1.0 + t1 * t1 / (t2 * t2)) * 0.5 * gm * gm / (gp * gp); } g = refraction_2->g + d; if (g < 0.0) attenuation->g = 1.0; else { g = f_sqrt(g); gp = g + c; gm = g - c; t1 = c * gp - 1.0; t2 = c * gm + 1.0; attenuation->g = (1.0 + t1 * t1 / (t2 * t2)) * 0.5 * gm * gm / (gp * gp); } g = refraction_2->b + d; if (g < 0.0) attenuation->b = 1.0; else { g = f_sqrt(g); gp = g + c; gm = g - c; t1 = c * gp - 1.0; t2 = c * gm + 1.0; attenuation->b = (1.0 + t1 * t1 / (t2 * t2)) * 0.5 * gm * gm / (gp * gp); } } /* ------------------------------------------------------------------------ distributionfactor ------------------------------------------------------------------------ -> facets -> cosphi ------------------------------------------------------------------------ <- ------------------------------------------------------------------------ calculate distribution factor from distribution of microfacets ------------------------------------------------------------------------ */ Static FLOAT distributionfactor(FACETS *facets,FLOAT cosphi) { UINT i; FLOAT f; f = f_sqrt(1.0 - cosphi * cosphi) * (FLOAT)(FACETSAMPLES - 1); i = (UINT)f; f = f - (FLOAT) i; return interpol(facets->sample[i],facets->sample[i + 1],f); } /* ------------------------------------------------------------------------ diffuse ------------------------------------------------------------------------ -> surface -> ndotl ------------------------------------------------------------------------ <- attenuation ------------------------------------------------------------------------ calculate attenuation of diffuse light from a lightsource ------------------------------------------------------------------------ */ Static VOID diffuserisssurf(SURFACE *surface,FLOAT ndotl,COLOR *attenuation) { FLOAT diffuse_factor; diffuse_factor = (1.0 - surface->riss.specular) * ndotl; colormultk(surface->riss.diffuse,diffuse_factor,*attenuation); /* in attenuation we have now: (1 - s) * Rd * N.L */ } /* ------------------------------------------------------------------------ specular ------------------------------------------------------------------------ -> surface -> ldotv -> ndotl -> ndotv ------------------------------------------------------------------------ <- attenuation ------------------------------------------------------------------------ calculate attenuation of specular light from a lightsource ------------------------------------------------------------------------ */ Static VOID specularrisssurf(SURFACE *surface,FLOAT ldotv,FLOAT ndotl, FLOAT ndotv,COLOR *attenuation) { BOOLEAN flag; FLOAT a,b,g,d; FLOAT rshelp; FLOAT ndoth; FLOAT vdoth; FLOAT specular_factor; flag = TRUE; ndoth = 0.0; vdoth = 0.0; if (ndotl > 0.0) { a = ldotv + 1.0; b = f_sqrt(a + a); ndoth = (ndotl + ndotv) / b; vdoth = a / b; } else if (ndotl < 0.0) /* light on the backside */ { if (surface->riss.refract_index == 1.0) { if (ldotv == -1.0) { ndoth = ndotv; vdoth = 1.0; } else flag = FALSE; /* approx. TIR ??? */ } else { a = surface->riss.inverse_index; if (-ldotv >= mini(a,surface->riss.refract_index)) { b = ((a + ldotv + ldotv) * a) + 1.0; if (a > 1.0) b = f_sqrt(b); else b = - f_sqrt(b); if (b == 0.0) /* FIXME: temporary */ b = F_SMALL; ndoth = ((a * ndotv) + ndotl) / b; vdoth = (a + ldotv) / b; } else flag = FALSE; /* approx. TIR ??? */ } } else /* ndotl == 0.0 */ { colorinit(*attenuation,0.0); return; } if (flag) { g = geometricfactor(ndoth,ndotv,ndotl,vdoth); d = distributionfactor(&(surface->riss.facets),ndoth); rshelp = d * g / (ndotl * ndotv * F_PI); if (ndotl > 0.0) { fresnelattenuation(vdoth,&(surface->riss.refraction_2),attenuation); /* rshelp * attenuation = Rs(lambda) */ specular_factor = rshelp * surface->riss.specular * ndotl; } else { fresnelattenuation(vdoth,&(surface->riss.invrefract_2),attenuation); colorinv(*attenuation,*attenuation); specular_factor = rshelp * surface->riss.specular * (- ndotl); } /* in attenuation we have now: Rs(lambda) * s * N.L */ colormultk(*attenuation,specular_factor,*attenuation); } else { colorinit(*attenuation,0.0); } } Static FLOAT invindexrisssurf(SURFACE *surface) { return(surface->riss.inverse_index); } /* ------------------------------------------------------------------------ reflectattenuation ------------------------------------------------------------------------ -> surface -> ndotv ------------------------------------------------------------------------ <- attenuation ------------------------------------------------------------------------ calculate attenuation of light from reflection direction ------------------------------------------------------------------------ */ Static VOID reflectrisssurf(SURFACE *surface,FLOAT ndotv,FLOAT minusndott_2, COLOR *attenuation) { fresnelattenuation(ndotv,&(surface->riss.refraction_2),attenuation); colormultk(*attenuation,surface->riss.specular,*attenuation); } /* ------------------------------------------------------------------------ transmitattenuation ------------------------------------------------------------------------ -> surface -> minusndott ------------------------------------------------------------------------ <- attenuation ------------------------------------------------------------------------ calculate attenuation of light from transmission direction ------------------------------------------------------------------------ */ Static VOID transmitrisssurf(SURFACE *surface,FLOAT ndotv,FLOAT minusndott, COLOR *attenuation) { fresnelattenuation(minusndott,&(surface->riss.invrefract_2),attenuation); colorinv(*attenuation,*attenuation); colormultk(*attenuation,surface->riss.specular,*attenuation); } VOID initrissmat(VOID) { defaultmaterial = defaultrissmat; frommatpar = RISS_DIFFUSE; hitmatpar = RISS_SPECULAR | RISS_FACETS; tomatpar = RISS_EMISSION | RISS_DIFFUSE; newmaterial = newrissmat; readmaterial = readrissmat; writematerial = writerissmat; setupmaterial = setuprissmat; absorbmaterial = absorbrissmat; opaquematerial = opaquerissmat; materialinterpol = rissmatinterpol; material2surface = rissmat2surf; ambientsurface = ambientrisssurf; emissionsurface = emissionrisssurf; diffusesurface = diffuserisssurf; specularsurface = specularrisssurf; invindexsurface = invindexrisssurf; reflectsurface = reflectrisssurf; refractsurface = transmitrisssurf; } = readrissmat; writeFlirt/rissmat.f000644 000316 000311 00000000741 06103226624 013612 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : rissmat.f routines for riss materials DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef RISSMAT_F #define RISSMAT_F #include "system.d" VOID initrissmat PP((VOID)); #endif µ¯ «ö¨q8adrissmat; writeFlirt/sampling.c000644 000316 000311 00000036623 06103226532 013745 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : sampling.c Sampling of a picture DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "color.f" #include "geometr3.f" #include "hitlist.f" /* scene lines */ #include "objects.f" #include "camera.f" #include "raytrace.f" #include "raycount.f" #include "rgbinout.f" #include "random.f" #include "scene.f" #include "sampling.f" #define INCRAY(ray,delta) \ { \ if (global_camera->parallel) { v3addto((ray).origin,delta); } \ else { v3addto((ray).direction,delta); } \ } #define INCRAYSCALED(ray,delta,scale) \ { \ if (global_camera->parallel) { \ v3addscaled((ray).origin,delta,scale,(ray).origin); } \ else { \ v3addscaled((ray).direction,delta,scale,(ray).direction); } \ } #define BIT(i) (1 << (i)) #define TESTBIT(a,i) ((a) & BIT(i)) Static RGBFILE outputfile; /* output goes there */ Static OBJECT *fromobj = NULL; Static VOID midpointsampling PP((AXIS3 *ray,VEC3 *deltax,VEC3 *deltay)); Static VOID adaptivesampling PP((AXIS3 *ray,VEC3 *deltax,VEC3 *deltay)); Static VOID do_subdivide PP((FLOAT weight,UINT level,UINT offsetx,UINT offsety, UINT range,AXIS3 *ray,VEC3 *deltax,VEC3 *deltay, COLOR colorgrid[MAXADAPT + 1][MAXADAPT + 1],UINT *shotray)); Static VOID average_color PP((COLOR *c1,COLOR *c2,COLOR *c3,COLOR *c4, COLOR *c)); Static BOOLEAN no_difference PP((FLOAT weight,COLOR *c1,COLOR *c2,COLOR *c3, COLOR *c4)); Static VOID oversampling PP((AXIS3 *ray,VEC3 *deltax,VEC3 *deltay)); Static VOID samplepoint PP((FLOAT weight,AXIS3 *ray,COLOR *color,VEC3 *deltax, VEC3 *deltay)); Static PNT3 cornerpnt = { -1.0, -1.0, 0.0 }; Static VEC3 cornervec = { -1.0, -1.0, 1.0 }; DOUBLE sampling(UCHAR Const *outputfilename) { ULONG startticks; FLOAT factor; DOUBLE samplingsecs; VEC3 deltax,deltay; AXIS3 ray; startticks = clockticks(); v3vmulm(V3XUNIT,global_camera->cam2world,deltax); factor = 2.0 / global_scene->xpix; v3scale(deltax,factor); v3vmulm(V3YUNIT,global_camera->cam2world,deltay); factor = 2.0 / global_scene->ypix; v3scale(deltay,factor); if (global_camera->parallel) { v3pmulm(cornerpnt,global_camera->cam2world,ray.origin); v3vmulm(V3ZUNIT,global_camera->cam2world,ray.direction); } else { ray.origin = global_camera->eye; v3vmulm(cornervec,global_camera->cam2world,ray.direction); } if (global_scene->xstart != 0) { INCRAYSCALED(ray,deltax,global_scene->xstart); } if (global_scene->ystart != 0) { INCRAYSCALED(ray,deltay,global_scene->ystart); } fromobj = inside[global_object->typ](&ray.origin,global_object); samplingsecs = ticks2secs(startticks,clockticks()); rgbopenwrite(outputfilename,&outputfile,(INT) global_scene->xsize, (INT) global_scene->ysize,1.0); startcount(); switch (global_scene->sampling) { case MIDPOINT: midpointsampling(&ray,&deltax,&deltay); break; case ADAPTIVE: adaptivesampling(&ray,&deltax,&deltay); break; case OVERSAMPLING: oversampling(&ray,&deltax,&deltay); break; default: break; } samplingsecs += endcount((UINT) (global_scene->xsize * global_scene->ysize)); rgbclose(&outputfile); return(samplingsecs); } Static VOID writepixel(COLOR *color) { BYTE rb,gb,bb; FLOAT r,g,b; r = extract_r(*color); g = extract_g(*color); b = extract_b(*color); r = maxi(r,0.0); g = maxi(g,0.0); b = maxi(b,0.0); r = mini(r,1.0); g = mini(g,1.0); b = mini(b,1.0); rb = (BYTE) f_floor(r * 255.0 + 0.5); gb = (BYTE) f_floor(g * 255.0 + 0.5); bb = (BYTE) f_floor(b * 255.0 + 0.5); rgbwrite(&outputfile,rb,gb,bb); } Static VOID midpointsampling(AXIS3 *ray,VEC3 *deltax,VEC3 *deltay) { AXIS3 ray1; COLOR color; INCRAYSCALED(*ray,*deltax,0.5); /* aim at middle of pixel */ INCRAYSCALED(*ray,*deltay,0.5); for (row = 0; row < global_scene->ysize; row++) { ray1 = *ray; for (column = 0; column < global_scene->xsize; column++) { samplepoint(1.0,&ray1,&color,deltax,deltay); writepixel(&color); INCRAY(ray1,*deltax); } INCRAY(*ray,*deltay); rgbflush(&outputfile); linecount((UINT) (global_scene->ysize - row)); } } Static VOID adaptivesampling(AXIS3 *ray,VEC3 *deltax,VEC3 *deltay) { UINT i; UINT shotray[MAXADAPT + 1]; UINT mem_id = SYSTEM; BOOLEAN *shotlastmidp; /* could be a bit-array */ AXIS3 ray1,ray2; COLOR *lastline = NULL; COLOR *lastmidpoint = NULL; COLOR colorgrid[MAXADAPT + 1][MAXADAPT + 1]; /* colums are first !*/ mem_id = getallocid((sizeof(COLOR) * 2 + sizeof(BOOLEAN)) * (global_scene->xsize + 1)); lastline = (COLOR *) newmem(mem_id,sizeof(COLOR) * (global_scene->xsize + 1)); lastmidpoint = (COLOR *) newmem(mem_id,sizeof(COLOR) * global_scene->xsize); shotlastmidp = (BOOLEAN *) newmem(mem_id,sizeof(BOOLEAN) * global_scene->xsize); ray1 = *ray; column = 0; samplepoint(1.0,&ray1,&(lastline[0]),deltax,deltay); for (column = 0; column < global_scene->xsize; column++) { INCRAY(ray1,*deltax); samplepoint(1.0,&ray1,&(lastline[column + 1]),deltax,deltay); } for (column = 0; column < global_scene->xsize; column++) shotlastmidp[column] = FALSE; for (row = 0; row < global_scene->ysize; row++) { ray1 = *ray; /* shoot column 0 */ INCRAY(ray1,*deltay); samplepoint(1.0,&ray1,&(colorgrid[MAXADAPT][MAXADAPT]),deltax,deltay); colorgrid[MAXADAPT][0] = lastline[0]; shotray[MAXADAPT] = BIT(0) | BIT(MAXADAPT); lastline[0] = colorgrid[MAXADAPT][MAXADAPT]; ray1 = *ray; for (column = 0; column < global_scene->xsize; column++) { shotray[0] = shotray[MAXADAPT]; for (i = 0; i <= MAXADAPT; i++) colorgrid[0][i] = colorgrid[MAXADAPT][i]; for (i = 1; i <= MAXADAPT; i++) shotray[i] = 0; colorgrid[MAXADAPT][0] = lastline[column + 1]; if (shotlastmidp[column]) { colorgrid[MAXADAPT / 2][0] = lastmidpoint[column]; shotray[MAXADAPT / 2] |= BIT(0); } ray2 = ray1; INCRAY(ray2,*deltax); INCRAY(ray2,*deltay); samplepoint(1.0,&ray2,&(colorgrid[MAXADAPT][MAXADAPT]), deltax,deltay); shotray[MAXADAPT] = BIT(0) | BIT(MAXADAPT); do_subdivide(1.0,0,0,0,MAXADAPT,&ray1,deltax,deltay,colorgrid, shotray); lastline[column + 1] = colorgrid[MAXADAPT][MAXADAPT]; if (TESTBIT(shotray[MAXADAPT / 2],MAXADAPT) != 0) { lastmidpoint[column] = colorgrid[MAXADAPT / 2][MAXADAPT]; shotlastmidp[column] = TRUE; } else shotlastmidp[column] = FALSE; writepixel(&(colorgrid[0][0])); INCRAY(ray1,*deltax); } INCRAY(*ray,*deltay); rgbflush(&outputfile); linecount((UINT) (global_scene->ysize - row)); } freemem(mem_id,NULL); } Static VOID do_subdivide(FLOAT weight,UINT level,UINT offsetx,UINT offsety, UINT range,AXIS3 *ray,VEC3 *deltax,VEC3 *deltay, COLOR colorgrid[MAXADAPT + 1][MAXADAPT + 1],UINT *shotray) { UINT x,y; FLOAT t; AXIS3 ray1; if (level < global_scene->max_rays && range > 1 && ! no_difference(weight,&(colorgrid[offsetx][offsety]), &(colorgrid[offsetx + range][offsety]), &(colorgrid[offsetx][offsety + range]), &(colorgrid[offsetx + range][offsety + range]))) { range *= 0.5; weight *= 0.25; x = offsetx; y = offsety + range; if (TESTBIT(shotray[x],y) == 0) { ray1 = *ray; t = (FLOAT) x / MAXADAPT; INCRAYSCALED(ray1,*deltax,t); t = (FLOAT) y / MAXADAPT; INCRAYSCALED(ray1,*deltay,t); samplepoint(weight,&ray1,&(colorgrid[x][y]),deltax,deltay); shotray[x] |= BIT(y); } x = offsetx + range; y = offsety; if (TESTBIT(shotray[x],y) == 0) { ray1 = *ray; t = (FLOAT) x / MAXADAPT; INCRAYSCALED(ray1,*deltax,t); t = (FLOAT) y / MAXADAPT; INCRAYSCALED(ray1,*deltay,t); samplepoint(weight,&ray1,&(colorgrid[x][y]),deltax,deltay); shotray[x] |= BIT(y); } y = offsety + range; block /* really a new one */ { ray1 = *ray; t = (FLOAT) x / MAXADAPT; INCRAYSCALED(ray1,*deltax,t); t = (FLOAT) y / MAXADAPT; INCRAYSCALED(ray1,*deltay,t); samplepoint(weight,&ray1,&(colorgrid[x][y]),deltax,deltay); shotray[x] |= BIT(y); } y = offsety + range * 2; block /* really a new one */ { ray1 = *ray; t = (FLOAT) x / MAXADAPT; INCRAYSCALED(ray1,*deltax,t); t = (FLOAT) y / MAXADAPT; INCRAYSCALED(ray1,*deltay,t); samplepoint(weight,&ray1,&(colorgrid[x][y]),deltax,deltay); shotray[x] |= BIT(y); } x = offsetx + range * 2; y = offsety + range; block /* really a new one */ { ray1 = *ray; t = (FLOAT) x / MAXADAPT; INCRAYSCALED(ray1,*deltax,t); t = (FLOAT) y / MAXADAPT; INCRAYSCALED(ray1,*deltay,t); samplepoint(weight,&ray1,&(colorgrid[x][y]),deltax,deltay); shotray[x] |= BIT(y); } level++; do_subdivide(weight,level,offsetx,offsety,range, ray,deltax,deltay,colorgrid,shotray); do_subdivide(weight,level,offsetx + range,offsety,range, ray,deltax,deltay,colorgrid,shotray); do_subdivide(weight,level,offsetx,offsety + range,range, ray,deltax,deltay,colorgrid,shotray); do_subdivide(weight,level,offsetx + range,offsety + range,range, ray,deltax,deltay,colorgrid,shotray); level--; } average_color(&(colorgrid[offsetx][offsety]), &(colorgrid[offsetx + range][offsety]), &(colorgrid[offsetx][offsety + range]), &(colorgrid[offsetx + range][offsety + range]), &(colorgrid[offsetx][offsety])); } Static VOID average_color(COLOR *c1,COLOR *c2,COLOR *c3,COLOR *c4,COLOR *c) { coloradd(*c1,*c2,*c); coloradd(*c,*c3,*c); coloradd(*c,*c4,*c); colormultk(*c,0.25,*c); } Static BOOLEAN no_difference(FLOAT weight,COLOR *c1,COLOR *c2,COLOR *c3, COLOR *c4) { COLOR mi,ma; colormini(*c1,*c2,mi); colormini(mi,*c3,mi); colormini(mi,*c4,mi); colormaxi(*c1,*c2,ma); colormaxi(ma,*c3,ma); colormaxi(ma,*c4,ma); colorsub(ma,mi,ma); if (colormax(ma) * weight < NO_DIFFERENCE) return(TRUE); return(FALSE); } Static VOID oversampling(AXIS3 *ray,VEC3 *deltax,VEC3 *deltay) { UINT i,j; FLOAT t,jitterx,jittery; VEC3 dx,dy; AXIS3 ray1,ray2,ray3,ray4; COLOR color,sumcolor; t = 1.0 / (global_scene->max_rays + 1); dx = *deltax; v3scale(dx,t); dy = *deltay; v3scale(dy,t); t *= t; /* i need it squared ! ==> 1 / # of samples */ INCRAYSCALED(*ray,dx,0.5); /* aim at first point in pixel */ INCRAYSCALED(*ray,dy,0.5); for (row = 0; row < global_scene->ysize; row++) { ray1 = *ray; for (column = 0; column < global_scene->xsize; column++) { ray2 = ray1; colorinit(sumcolor,0.0); for (i = 0; i <= global_scene->max_rays; i++) { ray3 = ray2; for (j = 0; j <= global_scene->max_rays; j++) { ray4 = ray3; jitterx = gauss_02(); jittery = gauss_03(); INCRAYSCALED(ray4,dx,jitterx); INCRAYSCALED(ray4,dy,jittery); samplepoint(t,&ray4,&color,deltax,deltay); coloradd(sumcolor,color,sumcolor) INCRAY(ray3,dx); } INCRAY(ray3,dy); } colormultk(sumcolor,t,color); /* divide it by # of samples */ writepixel(&color); INCRAY(ray1,*deltax); } INCRAY(*ray,*deltay); rgbflush(&outputfile); linecount((UINT) (global_scene->ysize - row)); } } Static VOID samplepoint(FLOAT weight,AXIS3 *ray,COLOR *color, VEC3 *deltax,VEC3 *deltay) { FLOAT re08,re09; VEC3 diff; RAY3 locray; locray.origin = ray->origin; locray.direction = ray->direction; if (! global_camera->parallel && global_camera->depth_of_field) { do { re08 = equal_08() - 0.5; re09 = equal_09() - 0.5; } while (re08 * re08 + re09 * re09 >= 1.0); re08 *= global_camera->aperture; re09 *= global_camera->aperture; v3add2scaled(*deltax,re08,*deltay,re09,diff); v3addto(ray->origin,diff); re08 = - global_camera->focus; /* used as another temp variable */ v3addscaled(locray.direction,diff,re08,locray.direction); } r3normalize(locray); raytracelevel = 0; raytrace(1.0,&locray,fromobj,color); } equal_09() - 0.5; } while (re08 * re08 + re09 * re09 >= 1.0); re08 *= globalFlirt/sampling.d000644 000316 000311 00000001116 06103226564 013740 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : sampling.d Sampling of a picture DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef SAMPLING_D #define SAMPLING_D #include "system.d" #include "flirt.d" typedef enum { UNKNOWN_SAMPLING, MIDPOINT, ADAPTIVE, OVERSAMPLING, STOCHASTIC } SAMPLING; #endif PROJECT : flirt MODULE : sampling.d Sampling of a picture DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef SAMPLING_D #define SAMPLING_D #include "system.d" #include "flirt.d" typedef enum { UNKNOWN_SAMPLING, MIDPOINTFlirt/sampling.f000644 000316 000311 00000000766 06103226626 013753 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : sampling.f Sampling of a picture DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef SAMPLING_F #define SAMPLING_F #include "sampling.d" DOUBLE sampling PP((UCHAR Const *outputfilename)); #endif MIDPOINTFlirt/scene.c000644 000316 000311 00000007660 06103226532 013227 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : scene.c Scene description DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "readdata.f" #include "symbols.f" #include "writdata.f" #include "scene.f" FLOAT scene_eps; SCENE *global_scene; VOID readscene(SCENE *scene) { match_read_uint("xpix", scene->xpix); option_read_uint("xstart", scene->xstart,0); if (matchreadconststring("xend")) scene->xsize = readuint() + 1 - scene->xstart; else scene->xsize = scene->xpix - scene->xstart; match_read_uint("ypix", scene->ypix); option_read_uint("ystart", scene->ystart,0); if (matchreadconststring("yend")) scene->ysize = readuint() + 1 - scene->ystart; else scene->ysize = scene->ypix - scene->ystart; option_read_bool("shadow_rays", scene->shadow_rays,TRUE); option_read_bool("texturing", scene->texturing,FALSE); option_read_bool("bbox_test", scene->bbox_test,TRUE); option_read_bool("bsphere_test", scene->bsphere_test,FALSE); option_read_bool("bounds_test", scene->bounds_test,FALSE); option_read_uint("max_reflection", scene->max_reflection,0); option_read_uint("max_refraction", scene->max_refraction,0); option_read_real("min_contribution",scene->min_contribution,1.0 / 256.0); readconststring("sampling"); scene->sampling = readnameconst(CONST_SAMPLING,TRUE); switch (scene->sampling) { case MIDPOINT: break; case ADAPTIVE: case OVERSAMPLING: match_read_uint("max_level", scene->max_rays); break; case STOCHASTIC: match_read_uint("min_rays", scene->min_rays); match_read_uint("max_rays", scene->max_rays); match_read_real("d", scene->d); match_read_real("alpha", scene->alpha); break; default: break; } } SCENE *readnamescene(VOID) { SCENE *scene; readconststring(lookupstring(CONST_DATA,DATA_SCENE)); scene = (SCENE *)findname(INFO_SCENE,token); if (scene == NULL) { scene = newonlytyp(SCENE); savename(INFO_SCENE,token,(VOIDPTR) scene); } nexttoken(); return(scene); } VOID writescene(SCENE *scene) { write_string_uint("xpix", scene->xpix); write_string_uint("xstart", scene->xstart); write_string_uint("xend", scene->xsize - 1 + scene->xstart); write_string_uint("ypix", scene->ypix); write_string_uint("ystart", scene->ystart); write_string_uint("yend", scene->ysize - 1 + scene->ystart); write_string_bool("shadow_rays", scene->shadow_rays); write_string_bool("texturing", scene->texturing); write_string_uint("max_reflection", scene->max_reflection); write_string_uint("max_refraction", scene->max_refraction); write_string_real("min_contribution", scene->min_contribution); writestring("sampling"); writestring(lookupstring(CONST_SAMPLING,(UINT) scene->sampling)); writelf(); switch (scene->sampling) { case MIDPOINT: break; case ADAPTIVE: case OVERSAMPLING: write_string_uint("max_level", scene->max_rays); break; case STOCHASTIC: write_string_uint("min_rays", scene->min_rays); write_string_uint("max_rays", scene->max_rays); write_string_real("d", scene->d); write_string_real("alpha", scene->alpha); break; default: break; } } case MIDPOINT: break; case ADAPTIVE: case OVERSAMPFlirt/scene.d000644 000316 000311 00000002403 06103226564 013223 0ustar00wrzlgup000000 000000 /**************************************************************************** Project: flirt Module: scene.d Scene description DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef SCENE_D #define SCENE_D #include "sampling.d" #include "flirt.d" typedef struct { UINT xpix; /* how many pixels */ UINT ypix; /* how many pixels */ UINT xstart; /* where to start */ UINT xsize; UINT ystart; /* where to start */ UINT ysize; BOOLEAN shadow_rays; BOOLEAN texturing; BOOLEAN bbox_test; BOOLEAN bsphere_test; BOOLEAN bounds_test; UINT max_reflection; UINT max_refraction; FLOAT min_contribution; SAMPLING sampling; UINT min_rays; UINT max_rays; /* for adaptive = max_level */ FLOAT d; FLOAT alpha; } SCENE; #endif / UINT ysize; BOOLEAN shadow_rays; BOOLEAN texturing; BOOLEAN bbox_test; BOOLEAN bsphere_test; BOOLEAN bounds_test; UINT max_reflection; UINT max_reFlirt/scene.f000644 000316 000311 00000001126 06103226626 013225 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : scene.f Scene description DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef SCENE_F #define SCENE_F #include "scene.d" Extern FLOAT scene_eps; Extern SCENE *global_scene; VOID readscene PP((SCENE *scene)); SCENE *readnamescene PP((VOID)); VOID writescene PP((SCENE *scene)); #endif JECT : flirt MODULE : scene.f Scene description DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef SCENE_F #define SCENE_F #include "scene.d" Extern FLOAT scene_eps; Extern SCENE *global_scene; VOID readscene PP((SCENE *sFlirt/scube.c000644 000316 000311 00000017013 06103226532 013224 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : scube.c Cube manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "objects.f" #include "material.f" #include "texture.f" #include "readdata.f" #include "scube.f" Static OBJECT *readscube(VOID) { OBJECT *obj,node; node.typ = CUBE; readcubetrans(&(node.u.obj.obj2world),&(node.u.obj.world2obj)); node.u.obj.material = readnamematerial(); node.u.obj.texture = readnametexture(); obj = copyobj[node.typ](&node,FALSE,NULL,NULL,NULL,NULL); return(obj); } Static OBJECT *copyscube(OBJECT *obj,BOOLEAN recurse,MAT3 *obj2world, MAT3 *world2obj,MATERIAL *mat,TEXTURE *tex) { OBJECT *newobj; if ((obj2world == NULL || world2obj == NULL) && tex == NULL && obj->u.obj.texture == NULL) { newobj = newonlyvar(OBJECT,SCUBEOBJ); newobj->typ = SIMPLE_CUBE; newobj->u.scube = obj->u.scube; if (mat != NULL) newobj->u.scube.material = mat; if (tex != NULL) newobj->u.scube.texture = tex; } else { MAT3 loc_o2w,loc_w2o,matrix; TURNINFO turninfo; BOX3 box; turnbox2mat(obj->u.scube.turninfo,&(obj->u.scube.box), &loc_o2w,&loc_w2o); m3mmulm(loc_o2w,*obj2world,matrix); if (mat2turnbox(&matrix,&turninfo,&box) && tex == NULL && obj->u.obj.texture == NULL) { newobj = newonlyvar(OBJECT,SCUBEOBJ); newobj->typ = SIMPLE_CUBE; newobj->u.scube.box = box; newobj->u.scube.turninfo = turninfo; } else { newobj = newonlyvar(OBJECT,SIMPLEOBJ); newobj->typ = CUBE; newobj->u.obj.obj2world = matrix; m3mmulm(*world2obj,loc_w2o,matrix); newobj->u.obj.world2obj = matrix; } newobj->u.obj.material = obj->u.obj.material; if (mat != NULL) newobj->u.obj.material = mat; if (tex != NULL) newobj->u.obj.texture = tex; } return(newobj); } Static VOID writescube(OBJECT *obj) { MAT3 loc_o2w,loc_w2o; turnbox2mat(obj->u.scube.turninfo,&(obj->u.scube.box),&loc_o2w,&loc_w2o); writetransform(&(loc_o2w),&(loc_w2o)); writenamematerial(obj->u.obj.material); writenametexture(obj->u.obj.texture); } Static VOID boundscube(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { obj->test_bbox = (bbox_test) ? BOUNDTEST_NONE : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? FALSE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; obj->bbox.min = obj->u.scube.box.min; obj->bbox.max = obj->u.scube.box.max; boundsphere4box(&(obj->bbox),&(obj->bsphere)); *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static OBJECT *insidescube(PNT3 *pnt,OBJECT *obj) { if (obj->u.scube.box.min.x < pnt->x && pnt->x < obj->u.scube.box.max.x && obj->u.scube.box.min.y < pnt->y && pnt->y < obj->u.scube.box.max.y && obj->u.scube.box.min.z < pnt->z && pnt->z < obj->u.scube.box.max.z) return(obj); return(NULL); } /* ------------------------------------------------------------------------ */ Static BOOLEAN hitscube(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) /* ------------------------------------------------------------------------ calculate intersection of ray and cube ------------------------------------------------------------------------ */ { ULONG tminface = 0L; ULONG tmaxface = 0L; HITINFO *hit1,*hit2; FLOAT hit; PRE_OBJECT(obj,hitlist); if (rci.ray.direction.x > 0.0) { hit = (obj->u.scube.box.min.x - rci.ray.origin.x) * rci.ray.inv_dir.x; checkaddmin(1L,hit,tminface,tmin,tmax); hit = (obj->u.scube.box.max.x - rci.ray.origin.x) * rci.ray.inv_dir.x; checkaddmax(2L,hit,tmaxface,tmin,tmax); } else if (rci.ray.direction.x < 0.0) { hit = (obj->u.scube.box.max.x - rci.ray.origin.x) * rci.ray.inv_dir.x; checkaddmin(2L,hit,tminface,tmin,tmax); hit = (obj->u.scube.box.min.x - rci.ray.origin.x) * rci.ray.inv_dir.x; checkaddmax(1L,hit,tmaxface,tmin,tmax); } else /* ray parallel to x-planes ? */ { if (rci.ray.origin.x <= obj->u.scube.box.min.x || rci.ray.origin.x >= obj->u.scube.box.max.x) return(FALSE); } if (rci.ray.direction.y > 0.0) { hit = (obj->u.scube.box.min.y - rci.ray.origin.y) * rci.ray.inv_dir.y; checkaddmin(3L,hit,tminface,tmin,tmax); hit = (obj->u.scube.box.max.y - rci.ray.origin.y) * rci.ray.inv_dir.y; checkaddmax(4L,hit,tmaxface,tmin,tmax); } else if (rci.ray.direction.y < 0.0) { hit = (obj->u.scube.box.max.y - rci.ray.origin.y) * rci.ray.inv_dir.y; checkaddmin(4L,hit,tminface,tmin,tmax); hit = (obj->u.scube.box.min.y - rci.ray.origin.y) * rci.ray.inv_dir.y; checkaddmax(3L,hit,tmaxface,tmin,tmax); } else /* ray parallel to y-planes ? */ { if (rci.ray.origin.y <= obj->u.scube.box.min.y || rci.ray.origin.y >= obj->u.scube.box.max.y) return FALSE; } if (rci.ray.direction.z > 0.0) { hit = (obj->u.scube.box.min.z - rci.ray.origin.z) * rci.ray.inv_dir.z; checkaddmin(5L,hit,tminface,tmin,tmax); hit = (obj->u.scube.box.max.z - rci.ray.origin.z) * rci.ray.inv_dir.z; checkaddmax(6L,hit,tmaxface,tmin,tmax); } else if (rci.ray.direction.z < 0.0) { hit = (obj->u.scube.box.max.z - rci.ray.origin.z) * rci.ray.inv_dir.z; checkaddmin(6L,hit,tminface,tmin,tmax); hit = (obj->u.scube.box.min.z - rci.ray.origin.z) * rci.ray.inv_dir.z; checkaddmax(5L,hit,tmaxface,tmin,tmax); } else /* ray parallel to x-planes ? */ { if (rci.ray.origin.z <= obj->u.scube.box.min.z || rci.ray.origin.z >= obj->u.scube.box.max.z) return FALSE; } checkmakerayhit(tminface,tmin,rci.ray,hit1); checkmakerayhit(tmaxface,tmax,rci.ray,hit2); prepare2hits(obj,hit1,hit2,hitlist); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } Static VOID normscube(HITINFO *hit) { hit->normal = box_normal[hit->face]; } VOID initscube(VOID) { nameobj[SIMPLE_CUBE] = "simplecube"; surfaces[SIMPLE_CUBE] = 6L; readobj[SIMPLE_CUBE] = readscube; copyobj[SIMPLE_CUBE] = copyscube; writeobj[SIMPLE_CUBE] = writescube; boundobj[SIMPLE_CUBE] = boundscube; setupobj[SIMPLE_CUBE] = setup_primitiv; splitobj[SIMPLE_CUBE] = split_primitiv; inside[SIMPLE_CUBE] = insidescube; hitobj[SIMPLE_CUBE] = hitscube; normalvec[SIMPLE_CUBE] = normscube; endobj[SIMPLE_CUBE] = end_primitiv; } } VOID initscube(VOID) { nameobj[SIMPLE_CUBE] = "simplecube"; surfaces[SIMPLE_CUBE] = 6L; readobj[SIMPLE_CUBE] = readscube; copyobj[SIMPLE_CUBE] = copyscube; writeobj[SIMPLE_CUBE] = writescube; boundobj[SIMPLE_CUBE] = boundscube; setupobj[SIMPLE_CUBE] = setup_primitiv; splitobj[SIMPLE_CUBE] = split_primitiv; inside[SIMPLE_CUBE] = insidescube; hitobj[SIMPLE_CUBE] = hitscube; normalvec[SIMPLE_CUBE] = normscube; endobj[SIMPLE_CUBE] = end_primitFlirt/scube.f000644 000316 000311 00000000737 06103226626 013240 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : scube.f Simple cube manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef SCUBE_F #define SCUBE_F #include "system.d" VOID initscube PP((VOID)); #endif µ¯ «ö¨p¸E_CUBE] = end_primitFlirt/setup.c000644 000316 000311 00000003710 06103226534 013264 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : setup.h set the datastructures DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "camera.f" #include "hitlist.f" #include "objects.f" #include "material.f" #include "texture.f" #include "scene.f" #include "setup.f" DOUBLE setup(VOID) { ULONG objcount; ULONG startticks; DOUBLE setupsecs; FLOAT diagonal; BOX3 bbox; SPHERE3 bsphere; BOUNDLIST *bounds; startticks = clockticks(); setupallmaterials(); setupalltextures(); bounds = NULL; boundobj[global_object->typ](global_object,global_scene->bbox_test, global_scene->bsphere_test,global_scene->bounds_test, &bbox,&bsphere,bounds); /* bound all objects */ v3dist(bbox.min,bbox.max,diagonal); scene_eps = diagonal / SCENE_EPS_DIVISOR; hit_eps = diagonal / HIT_EPS_DIVISOR; V3SCENE_EPS.x = scene_eps; V3SCENE_EPS.y = scene_eps; V3SCENE_EPS.z = scene_eps; setupcamera(global_camera,global_scene->xpix,global_scene->ypix); objcount = setupobjects(global_object,TRUE,FALSE); /* other inits */ setupsecs = ticks2secs(startticks,clockticks()); if (setupsecs < 0.001) setupsecs = 0.001; message("\nSETUP STATISTICS:\n"); message(" pixels in x : %8d\n",global_scene->xsize); message(" pixels in y : %8d\n",global_scene->ysize); message(" number of objects : %8ld\n",objcount); message(" total setup time : %11.3lf\n",setupsecs); return(setupsecs); } jects(global_object,TRUE,FALSE); /* other inits */Flirt/setup.f000644 000316 000311 00000000712 06103226626 013270 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : setup.f setup of scene DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef SETUP_F #define SETUP_F #include "system.d" DOUBLE setup PP((VOID)); #endif cts(global_object,TRUEµ¯ «ö¨pÈ /* other inits */Flirt/smplmat.c000644 000316 000311 00000034332 06103226534 013605 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : smplmat.c shading functions for simple materials The calculations used in this module have been described in the paper 'A Realistic Lighting Model for Computer Animators' by Paul S. Strauss IEEE Computer Graphics & applications, 1990, pg.56-64 WARNING: the H-Vector in this Article has not the same definition as the H-Vector used by our raytracer: In the article: H is the reflected lightvector. In our raytracer: H is the vector which devides the angle between V and L into two halves DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "color.f" #include "material.f" #include "readdata.f" #include "writdata.f" #include "smplmat.f" #define TABLE_ENTRIES 256 #define F_CONST 1.12 #define G_CONST 1.01 #define ADJUST_CONST 0.1 #define IND 5.828427125 Static SMPLMAT defaultsmplmaterial = { TRUE, /* opaque */ 1.0, /* 1 / ri */ 3.0, /* h */ 0.0, /* smoothness */ 0.0, /* metalness */ 0.0, /* transparency */ IND, /* ri */ { 0.5, 0.5, 0.5 } /* color */ }; Static FLOAT fresnel_table[TABLE_ENTRIES + 1]; Static FLOAT geometric_table[TABLE_ENTRIES + 1]; Static VOID defaultsmplmat(MATERIAL *def) { def->smpl = defaultsmplmaterial; } Static MATERIAL *newsmplmat(VOID) { MATERIAL *material = newonlyuni(MATERIAL,SMPLMAT); return(material); } Static VOID readsmplmat(MATERIAL *material) { option_read_real("smoothness", material->smpl.smoothness,0.0); option_read_real("metalness", material->smpl.metalness,0.0); option_read_real("transparency", material->smpl.transparency,0.0); option_read_real("refract_index", material->smpl.refract_index,1.0); readconststring("color"); readcolor(&(material->smpl.color)); } Static VOID writesmplmat(MATERIAL *material) { write_string_real("smoothness", material->smpl.smoothness); write_string_real("metalness", material->smpl.metalness); write_string_real("transparency", material->smpl.transparency); write_string_real("refract_index", material->smpl.refract_index); writestring("color"); writecolor(&(material->smpl.color)); } Static VOID setupsmplmat(MATERIAL *material) { if (material->smpl.transparency > 0.0 && colormax(material->smpl.color) > 0.0) material->smpl.opaque = FALSE; else material->smpl.opaque = TRUE; material->smpl.refract_index /= global_material->smpl.refract_index; material->smpl.inverse_index = 1.0 / material->smpl.refract_index; if (material->smpl.smoothness < 1.0) material->smpl.h = 3.0 / (1.0 - material->smpl.smoothness); else material->smpl.h = F_HUGE; } Static VOID absorbsmplmat(MATERIAL *material,FLOAT length,COLOR *absorption) { if (length >= F_HUGE) { if (material->smpl.color.r < 1.0) absorption->r = 0.0; else absorption->r = 1.0; if (material->smpl.color.g < 1.0) absorption->g = 0.0; else absorption->g = 1.0; if (material->smpl.color.b < 1.0) absorption->b = 0.0; else absorption->b = 1.0; } else { colorpowk(material->smpl.color,length,*absorption); } /* ----------------------------- at this point: simulate fog, haze, ... */ } Static BOOLEAN opaquesmplmat(MATERIAL *material) { return(material->smpl.opaque); } Static VOID smplmatinterpol(MATERIAL *mat1,MATERIAL *mat2, FLOAT t,MATPAR changes,MATERIAL *material) { if (changes & SMPL_SMOOTHNESS) { material->smpl.smoothness = interpol(mat1->smpl.smoothness, mat2->smpl.smoothness,t); if (material->smpl.smoothness < 1.0) material->smpl.h = 3.0 / (1.0 - material->smpl.smoothness); else material->smpl.h = F_HUGE; } if (changes & SMPL_METALNESS) material->smpl.metalness = interpol(mat1->smpl.metalness, mat2->smpl.metalness,t); if (changes & SMPL_TRANSPARENCY) material->smpl.transparency = interpol(mat1->smpl.transparency, mat2->smpl.transparency,t); if (changes & SMPL_REFRACT_INDEX) material->smpl.refract_index = interpol(mat1->smpl.refract_index, mat2->smpl.refract_index,t); if (changes & SMPL_COLOR) { colorinterpol(mat1->smpl.color,mat2->smpl.color,t, material->smpl.color); } } Static VOID smplmat2surf(MATERIAL *frommaterial,MATERIAL *material, MATERIAL *tomaterial,SURFACE *surface) { if (tomaterial != global_material) { surface->smpl.metalness = tomaterial->smpl.metalness; surface->smpl.transparency = tomaterial->smpl.transparency; surface->smpl.color = tomaterial->smpl.color; if (frommaterial == global_material) { surface->smpl.refract_index = tomaterial->smpl.refract_index; surface->smpl.inverse_index = tomaterial->smpl.inverse_index; } else { surface->smpl.refract_index = tomaterial->smpl.refract_index / frommaterial->smpl.refract_index; surface->smpl.inverse_index = frommaterial->smpl.refract_index / tomaterial->smpl.refract_index; } } else { surface->smpl.metalness = frommaterial->smpl.metalness; surface->smpl.transparency = frommaterial->smpl.transparency; surface->smpl.color = frommaterial->smpl.color; surface->smpl.refract_index = frommaterial->smpl.inverse_index; surface->smpl.inverse_index = frommaterial->smpl.refract_index; } surface->smpl.smoothness = material->smpl.smoothness; surface->smpl.h = material->smpl.h; block { Register FLOAT s = surface->smpl.smoothness; surface->smpl.d = 1.0 - s * surface->smpl.metalness; surface->smpl.rd = (1.0 - surface->smpl.transparency) * (1.0 - s * s * s); } } Static VOID ambientsmplsurf(SURFACE *surface,COLOR *attenuation) { colormultk(surface->smpl.color,surface->smpl.rd,*attenuation); } Static VOID emissionsmplsurf(SURFACE *surface,COLOR *attenuation) { colorinit(*attenuation,0.0); } Static FLOAT geometricfactor(FLOAT cosalpha) { INT index; FLOAT factor; cosalpha = 1.0 - cosalpha; cosalpha *= cosalpha; cosalpha *= cosalpha; cosalpha *= cosalpha; cosalpha *= TABLE_ENTRIES; index = (INT) f_floor(cosalpha); if (index < 0) return(geometric_table[0]); if (index >= TABLE_ENTRIES) return(geometric_table[TABLE_ENTRIES]); cosalpha -= index; factor = interpol(geometric_table[index],geometric_table[index + 1], cosalpha); return(factor); } Static FLOAT fresnelfactor(FLOAT cosalpha) { INT index; FLOAT factor; cosalpha = 1.0 - cosalpha; cosalpha *= cosalpha; cosalpha *= cosalpha; cosalpha *= TABLE_ENTRIES; index = (INT) f_floor(cosalpha); if (index < 0) return(fresnel_table[0]); if (index >= TABLE_ENTRIES) return(fresnel_table[TABLE_ENTRIES]); cosalpha -= index; factor = interpol(fresnel_table[index],fresnel_table[index + 1],cosalpha); return(factor); } Static VOID diffusesmplsurf(SURFACE *surface,FLOAT ndotl,COLOR *attenuation) { FLOAT diffuse_factor; diffuse_factor = ndotl * surface->smpl.d * surface->smpl.rd; colormultk(surface->smpl.color,diffuse_factor,*attenuation); } Static VOID specularsmplsurf(SURFACE *surface, FLOAT ldotv, FLOAT ndotl, FLOAT ndotv, COLOR *attenuation) { BOOLEAN flag; FLOAT specular_factor; FLOAT rn; FLOAT ndoth,a,b; COLOR specular; colorinit(specular,1.0); if (surface->smpl.metalness > 0.0) { FLOAT factor; COLOR inv_diffuse; colorinv(surface->smpl.color,inv_diffuse); factor = (fresnelfactor(ndotl) - 1.0) * surface->smpl.metalness; coloraddscaled(specular,inv_diffuse,factor,specular); } specular_factor = fresnelfactor(ndotl) * geometricfactor(ndotl) * geometricfactor(ndotv); rn = 1.0 - surface->smpl.transparency - surface->smpl.rd; specular_factor = rn + (rn + ADJUST_CONST) * specular_factor; specular_factor = mini(1.0,specular_factor); flag = TRUE; ndoth = 0.0; if (ndotl > 0.0) { a = ldotv + 1.0; b = f_sqrt(a + a); ndoth = (ndotl + ndotv) / b; } else if (ndotl < 0.0) { if (surface->smpl.refract_index == 1.0) { if (ldotv == -1.0) ndoth = ndotv; else flag = FALSE; /* approx. TIR ??? */ } else { a = surface->smpl.inverse_index; if (-ldotv >= mini(a,surface->smpl.refract_index)) { b = ((a + ldotv + ldotv) * a) + 1.0; if (a > 1.0) b = f_sqrt(b); else b = - f_sqrt(b); if (b == 0.0) /* FIXME: temporary */ b = F_SMALL; ndoth = ((a * ndotv) + ndotl) / b; } else flag = FALSE; /* approx. TIR ??? */ } } else { colorinit(*attenuation,0.0); return; } if (flag) { ndoth = 2.0 * ndoth * ndoth - 1.0; if (ndoth <= 0.0) specular_factor = 0.0; else specular_factor *= f_pow(ndoth,surface->smpl.h); colormultk(specular,specular_factor,*attenuation); } else { colorinit(*attenuation,0.0); } } Static FLOAT invindexsmplsurf(SURFACE *surface) { return(surface->smpl.inverse_index); } Static VOID reflectsmplsurf(SURFACE *surface,FLOAT ndotv,FLOAT minusndott_2, COLOR *attenuation) { FLOAT specular_factor; FLOAT rn; if (minusndott_2 >= 0.0) { specular_factor = fresnelfactor(ndotv) * geometricfactor(ndotv); rn = 1.0 - surface->smpl.transparency - surface->smpl.rd; specular_factor = rn + (rn + ADJUST_CONST) * specular_factor; specular_factor = mini(1.0,specular_factor); colorinit(*attenuation,specular_factor); } else { colorinit(*attenuation,1.0); } } Static VOID transmitsmplsurf(SURFACE *surface,FLOAT ndotv,FLOAT minusndott, COLOR *attenuation) { if (surface->smpl.transparency > 0.0) { FLOAT specular_factor; FLOAT transmit_factor; FLOAT rn; specular_factor = fresnelfactor(ndotv) * geometricfactor(ndotv); rn = 1.0 - surface->smpl.transparency - surface->smpl.rd; specular_factor = rn + (rn + ADJUST_CONST) * specular_factor; specular_factor = mini(1.0,specular_factor); transmit_factor = surface->smpl.transparency * (1.0 - specular_factor) / (surface->smpl.transparency + surface->smpl.rd); colorinit(*attenuation,transmit_factor); } else { colorinit(*attenuation,0.0); } } VOID initsmplmat(VOID) { UINT i; FLOAT t,cosalpha; FLOAT factor; FLOAT f_factor,g_factor; f_factor = 1.0 / (1.0 / ((1.0 - F_CONST) * (1.0 - F_CONST)) - 1.0 / (F_CONST * F_CONST)); g_factor = 1.0 / (1.0 / ((1.0 - G_CONST) * (1.0 - G_CONST)) - 1.0 / (G_CONST * G_CONST)); for (i = 0; i <= TABLE_ENTRIES; i++) { cosalpha = (FLOAT) i / TABLE_ENTRIES; t = f_acos(1.0 - f_sqrt(f_sqrt(cosalpha))) / F_PI_HALF - F_CONST; factor = (1.0 / (t * t) - 1.0 / (F_CONST * F_CONST)) * f_factor; if (factor < F_SMALL) fresnel_table[i] = 0.0; else fresnel_table[i] = factor; t = f_acos(1.0 - f_sqrt(f_sqrt(f_sqrt(cosalpha)))) / F_PI_HALF - G_CONST; factor = (1.0 / ((1.0 - G_CONST) * (1.0 - G_CONST)) - 1.0 / (t * t)) * g_factor; if (factor < F_SMALL) geometric_table[i] = 0.0; else geometric_table[i] = factor; } defaultmaterial = defaultsmplmat; frommatpar = SMPL_METALNESS | SMPL_TRANSPARENCY | SMPL_REFRACT_INDEX | SMPL_COLOR; hitmatpar = SMPL_SMOOTHNESS; tomatpar = SMPL_METALNESS | SMPL_TRANSPARENCY | SMPL_REFRACT_INDEX | SMPL_COLOR; newmaterial = newsmplmat; readmaterial = readsmplmat; writematerial = writesmplmat; setupmaterial = setupsmplmat; absorbmaterial = absorbsmplmat; opaquematerial = opaquesmplmat; materialinterpol = smplmatinterpol; material2surface = smplmat2surf; ambientsurface = ambientsmplsurf; emissionsurface = emissionsmplsurf; diffusesurface = diffusesmplsurf; specularsurface = specularsmplsurf; invindexsurface = invindexsmplsurf; reflectsurface = reflectsmplsurf; refractsurface = transmitsmplsurf; } = readsmplmat; writematerial = writesmplmat; setupmaterial = setupsmplmat; absorbmaterial = absorbsmplmat; opaquematerial = opaquesmplmat; materialinterpol = smplmatinterpol; material2surface = smplmat2surf; ambientsurface = ambientsmplsurf; emissionsurface = emFlirt/smplmat.f000644 000316 000311 00000000743 06103226630 013604 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : smplmat.f routines for simple materials DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef SMPLMAT_F #define SMPLMAT_F #include "system.d" VOID initsmplmat PP((VOID)); #endif «ö¨qhemissionsurface = emFlirt/sphere.c000644 000316 000311 00000021700 06103226534 013411 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : sphere.c sphere manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "bounding.f" #include "hitlist.f" #include "texture.f" #include "objects.f" #include "readdata.f" #include "material.f" #include "texture.f" #include "sphere.f" Static BOOLEAN ssphere_allowed = TRUE; Static OBJECT *readsphere(VOID) { OBJECT *obj,node; node.typ = SPHERE; readspheretrans(&(node.u.obj.obj2world),&(node.u.obj.world2obj)); node.u.obj.material = readnamematerial(); node.u.obj.texture = readnametexture(); obj = copyobj[node.typ](&node,FALSE,NULL,NULL,NULL,NULL); return(obj); } Static OBJECT *copysphere(OBJECT *obj,BOOLEAN recurse,MAT3 *to,MAT3 *fr, MATERIAL *mat,TEXTURE *tex) { OBJECT *newobj; MAT3 m; TURNINFO turninfo; SPHERE3 sphere; if (to == NULL) m = obj->u.obj.obj2world; else { m3mmulm(obj->u.obj.obj2world,*to,m); } if (ssphere_allowed && mat2turnsphere(&m,&turninfo,&sphere) && tex == NULL && obj->u.obj.texture == NULL) { newobj = newonlyvar(OBJECT,SSPHEREOBJ); newobj->typ = SIMPLE_SPHERE; newobj->u.ssphere.sphere = sphere; newobj->u.ssphere.turninfo = turninfo; } else { newobj = newonlyvar(OBJECT,SIMPLEOBJ); newobj->typ = SPHERE; newobj->u.obj.obj2world = m; if (fr == NULL) m = obj->u.obj.world2obj; else { m3mmulm(*fr,obj->u.obj.world2obj,m); } newobj->u.obj.world2obj = m; } newobj->u.obj.material = obj->u.obj.material; newobj->u.obj.texture = obj->u.obj.texture; if (mat != NULL) newobj->u.obj.material = mat; if (tex != NULL) newobj->u.obj.texture = tex; return(newobj); } #define DIS 0.414213562 /* tan(22.5 * F_PI/180.0) == sqrt(2.0) - 1.0 */ Static PNT3 hull_sphere[24] = { { 1.0, DIS, DIS }, { DIS, 1.0, DIS }, { DIS, DIS, 1.0 }, { 1.0, DIS, -DIS }, { DIS, 1.0, -DIS }, { DIS, DIS, -1.0 }, { 1.0, -DIS, DIS }, { DIS, -1.0, DIS }, { DIS, -DIS, 1.0 }, { 1.0, -DIS, -DIS }, { DIS, -1.0, -DIS }, { DIS, -DIS, -1.0 }, { -1.0, DIS, DIS }, { -DIS, 1.0, DIS }, { -DIS, DIS, 1.0 }, { -1.0, DIS, -DIS }, { -DIS, 1.0, -DIS }, { -DIS, DIS, -1.0 }, { -1.0, -DIS, DIS }, { -DIS, -1.0, DIS }, { -DIS, -DIS, 1.0 }, { -1.0, -DIS, -DIS }, { -DIS, -1.0, -DIS }, { -DIS, -DIS, -1.0 } }; Static VOID plane2point(VEC3 *normal,MAT3 *obj2world,PNT3 *point) { VEC3 vec; v3vmultransm(*normal,*obj2world,vec); v3normalize(vec); v3pmulm(vec,*obj2world,*point); } Static VOID boundsphere(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { PNT3 pnt; obj->test_bbox = (bbox_test) ? BOUNDTEST_ALL : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? TRUE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; v3pmulm(V3ZERO,obj->u.obj.obj2world,obj->bsphere.center); plane2point(&V3XUNIT,&(obj->u.obj.obj2world),&pnt); obj->bbox.max.x = pnt.x; obj->bbox.min.x = 2 * obj->bsphere.center.x - pnt.x; plane2point(&V3YUNIT,&(obj->u.obj.obj2world),&pnt); obj->bbox.max.y = pnt.y; obj->bbox.min.y = 2 * obj->bsphere.center.y - pnt.y; plane2point(&V3ZUNIT,&(obj->u.obj.obj2world),&pnt); obj->bbox.max.z = pnt.z; obj->bbox.min.z = 2 * obj->bsphere.center.z - pnt.z; bounds4points(24,hull_sphere,NULL,&(obj->bsphere),&V3ZERO, &(obj->u.obj.obj2world)); *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static OBJECT *insidesphere(PNT3 *pnt,OBJECT *obj) { PNT3 locpnt; INSIDE_BOUND_TEST(obj,pnt); v3pmulm(*pnt,obj->u.obj.world2obj,locpnt); if (v3length_2(locpnt) <= 1.0) return(obj); return(NULL); } /* ------------------------------------------------------------------------ */ Static BOOLEAN hitsphere(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) /* ------------------------------------------------------------------------ calculate intersection of ray and cube ------------------------------------------------------------------------ */ { ULONG tminface = 0L; ULONG tmaxface = 0L; HITINFO *hit1,*hit2; FLOAT a,b,c,d,tone,ttwo; RAY3 locray; PRE_OBJECT(obj,hitlist); v3pmulm(rci.ray.origin,obj->u.obj.world2obj,locray.origin); v3vmulm(rci.ray.direction,obj->u.obj.world2obj,locray.direction); a = v3dot(locray.direction, locray.direction); b = v3dot(locray.origin, locray.direction); c = v3length_2(locray.origin) - 1.0; /* ------------------------- quadric equation : a t^2 + 2b t + c = 0 */ d = b * b - a * c; /* factor 2 was eliminated! */ if (d <= 0.0) /* no root ? */ return FALSE; /* then exit */ if (b > 0) /* stable way to calculate */ d = - f_sqrt(d) - b; /* the roots of a quadratic */ else /* equation */ d = f_sqrt(d) - b; tone = d / a; ttwo = c / d; /* VIETA */ if (tone < ttwo) { checkaddmin(1L,tone,tminface,tmin,tmax); checkaddmax(1L,ttwo,tmaxface,tmin,tmax); } else { checkaddmin(1L,ttwo,tminface,tmin,tmax); checkaddmax(1L,tone,tmaxface,tmin,tmax); } checkmakerayhit(tminface,tmin,locray,hit1); checkmakerayhit(tmaxface,tmax,locray,hit2); prepare2hits(obj,hit1,hit2,hitlist); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } Static VOID normsphere(HITINFO *hit) { VEC3 locnormal; v3addscaled(hit->ray.origin,hit->ray.direction,hit->t,locnormal); v3vmultransm(locnormal,hit->obj->u.obj.world2obj,hit->normal); v3normalize(hit->normal); } Static VOID pntnormsphere(OBJECT *obj,ULONG surface,PNT2 *point, PNT3 *world,VEC3 *normal) { FLOAT t; VEC3 locnormal; t = f_cos(point->y * F_PI); locnormal.x = t * f_cos(point->x * F_2PI); locnormal.y = t * f_sin(point->x * F_2PI); locnormal.z = f_sin(point->y * F_PI); v3vmulm(locnormal,obj->u.obj.obj2world,*world); v3vmultransm(locnormal,obj->u.obj.world2obj,*normal); v3normalize(*normal); } Static VOID hitcoordsphere(HITINFO *hit,GEOMPAR needed) { if (needed & (LOCALPNT | GEOM_2DCOORD)) { v3addscaled(hit->ray.origin,hit->ray.direction,hit->t, texinfo.localpnt); texinfo.face = 1L; if (needed & GEOM_2DCOORD) { texinfo.pnt2[0].x = (1.0 / F_2PI) * f_atan2(texinfo.localpnt.y,texinfo.localpnt.x) + 0.5; texinfo.pnt2[0].y = (1.0 / F_PI) * f_atan2(texinfo.localpnt.z, f_sqrt(texinfo.localpnt.x * texinfo.localpnt.x + texinfo.localpnt.y * texinfo.localpnt.y)) + 0.5; texinfo.num2 = 1; } } } Static BOOLEAN pntcoordsphere(OBJECT *obj,GEOMPAR needed) { if (needed & (LOCALPNT | GEOM_2DCOORD)) { v3pmulm(texinfo.worldpnt,obj->u.obj.world2obj,texinfo.localpnt); texinfo.face = 1L; if (needed & GEOM_2DCOORD) { texinfo.pnt2[0].x = (1.0 / F_2PI) * f_atan2(texinfo.localpnt.y,texinfo.localpnt.x) + 0.5; texinfo.pnt2[0].y = (1.0 / F_PI) * f_atan2(texinfo.localpnt.z, f_sqrt(texinfo.localpnt.x * texinfo.localpnt.x + texinfo.localpnt.y * texinfo.localpnt.y)) + 0.5; texinfo.num2 = 1; } } return(TRUE); } VOID initsphere(BOOLEAN ssphere_ok) { ssphere_allowed = ssphere_ok; nameobj[SPHERE] = "sphere"; surfaces[SPHERE] = 1L; readobj[SPHERE] = readsphere; copyobj[SPHERE] = copysphere; writeobj[SPHERE] = writesobj; boundobj[SPHERE] = boundsphere; setupobj[SPHERE] = setup_primitiv; splitobj[SPHERE] = split_primitiv; inside[SPHERE] = insidesphere; hitobj[SPHERE] = hitsphere; normalvec[SPHERE] = normsphere; pntnormvec[SPHERE] = pntnormsphere; hitcoord[SPHERE] = hitcoordsphere; pntcoord[SPHERE] = pntcoordsphere; endobj[SPHERE] = end_primitiv; } ere"; surfaces[SPHERE] = 1L; readobj[SPHERE] = readspherFlirt/sphere.f000644 000316 000311 00000000754 06103226630 013417 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : sphere.f Sphere manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #ifndef SPHERE_F #define SPHERE_F #include "system.d" VOID initsphere PP((BOOLEAN ssphere_ok)); #endif [SPHERE] = readspherFlirt/ssphere.c000644 000316 000311 00000013652 06103226534 013603 0ustar00wrzlgup000000 000000 /***************************************************************************** PROJECT : flirt MODULE : ssphere.c sphere manipulation routines DATE AUTHOR DESCRIPTION ------ ------ ------------------------------------------------------ 010391 wrzl,rft first version *****************************************************************************/ #include "flirt.f" #include "numeric.f" #include "geometr3.f" #include "hitlist.f" #include "objects.f" #include "material.f" #include "texture.f" #include "readdata.f" #include "ssphere.f" Static OBJECT *readssphere(VOID) { OBJECT *obj,node; node.typ = SPHERE; readspheretrans(&(node.u.obj.obj2world),&(node.u.obj.world2obj)); node.u.obj.material = readnamematerial(); node.u.obj.texture = readnametexture(); obj = copyobj[node.typ](&node,FALSE,NULL,NULL,NULL,NULL); return(obj); } Static OBJECT *copyssphere(OBJECT *obj,BOOLEAN recurse,MAT3 *obj2world, MAT3 *world2obj,MATERIAL *mat,TEXTURE *tex) { OBJECT *newobj; if ((obj2world == NULL || world2obj == NULL) && tex == NULL && obj->u.obj.texture == NULL) { newobj = newonlyvar(OBJECT,SSPHEREOBJ); newobj->typ = SIMPLE_SPHERE; newobj->u.ssphere = obj->u.ssphere; if (mat != NULL) newobj->u.ssphere.material = mat; if (tex != NULL) newobj->u.ssphere.texture = tex; } else { MAT3 loc_o2w,loc_w2o,matrix; TURNINFO turninfo; SPHERE3 sphere; turnsphere2mat(obj->u.ssphere.turninfo,&(obj->u.ssphere.sphere), &loc_o2w,&loc_w2o); m3mmulm(loc_o2w,*obj2world,matrix); if (mat2turnsphere(&matrix,&turninfo,&sphere) && tex == NULL && obj->u.obj.texture == NULL) { newobj = newonlyvar(OBJECT,SSPHEREOBJ); newobj->typ = SIMPLE_SPHERE; newobj->u.ssphere.sphere = sphere; newobj->u.ssphere.turninfo = turninfo; } else { newobj = newonlyvar(OBJECT,SIMPLEOBJ); newobj->typ = SPHERE; newobj->u.obj.obj2world = matrix; m3mmulm(*world2obj,loc_w2o,matrix); newobj->u.obj.world2obj = matrix; } newobj->u.obj.material = obj->u.obj.material; if (mat != NULL) newobj->u.obj.material = mat; if (tex != NULL) newobj->u.obj.texture = tex; } return(newobj); } Static VOID writessphere(OBJECT *obj) { MAT3 loc_o2w,loc_w2o; turnsphere2mat(obj->u.ssphere.turninfo,&(obj->u.ssphere.sphere), &loc_o2w,&loc_w2o); writetransform(&(loc_o2w),&(loc_w2o)); writenamematerial(obj->u.obj.material); writenametexture(obj->u.obj.texture); } Static VOID boundssphere(OBJECT *obj,BOOLEAN bbox_test,BOOLEAN bsphere_test, BOOLEAN bounds_test,BOX3 *bbox,SPHERE3 *bsphere,BOUNDLIST *bounds) { FLOAT r; obj->test_bbox = (bbox_test) ? BOUNDTEST_NONE : BOUNDTEST_NONE; obj->test_bsphere = (bsphere_test) ? FALSE : FALSE; obj->bounds = (bounds_test) ? NULL : NULL; r = f_sqrt(obj->u.ssphere.sphere.radius_2); obj->bbox.min.x = obj->u.ssphere.sphere.center.x - r; obj->bbox.min.y = obj->u.ssphere.sphere.center.y - r; obj->bbox.min.z = obj->u.ssphere.sphere.center.z - r; obj->bbox.max.x = obj->u.ssphere.sphere.center.x + r; obj->bbox.max.y = obj->u.ssphere.sphere.center.y + r; obj->bbox.max.z = obj->u.ssphere.sphere.center.z + r; obj->bsphere.center = obj->u.ssphere.sphere.center; obj->bsphere.radius_2 = obj->u.ssphere.sphere.radius_2; *bbox = obj->bbox; *bsphere = obj->bsphere; bounds = obj->bounds; } Static OBJECT *insidessphere(PNT3 *pnt,OBJECT *obj) { FLOAT dist_2; v3dist_2(obj->u.ssphere.sphere.center,*pnt,dist_2); if (dist_2 < obj->u.ssphere.sphere.radius_2) return(obj); return(NULL); } /* ------------------------------------------------------------------------ */ Static BOOLEAN hitssphere(FLOAT tmin,FLOAT tmax,OBJECT *obj,HITLIST *hitlist) /* ------------------------------------------------------------------------ calculate intersection of ray and simple sphere ------------------------------------------------------------------------ */ { ULONG tminface = 0L; ULONG tmaxface = 0L; HITINFO *hit1,*hit2; FLOAT v,t,discr; VEC3 eye2mid; PRE_OBJECT(obj,hitlist); v3sub(obj->u.ssphere.sphere.center,rci.ray.origin,eye2mid); v = v3dot(eye2mid,rci.ray.direction); discr = obj->u.ssphere.sphere.radius_2 - (v3length_2(eye2mid) - v * v); if (discr <= 0.0) return(FALSE); discr = f_sqrt(discr); t = v - discr; /* unstable !!! */ checkaddmin(1L,t,tminface,tmin,tmax); t = v + discr; checkaddmax(1L,t,tmaxface,tmin,tmax); checkmakerayhit(tminface,tmin,rci.ray,hit1); checkmakerayhit(tmaxface,tmax,rci.ray,hit2); prepare2hits(obj,hit1,hit2,hitlist); POST_OBJECT(obj,hitlist); returnhitlist(hitlist); } Static VOID normssphere(HITINFO *hit) { v3addscaled(hit->ray.origin,hit->ray.direction,hit->t,hit->normal); v3subfrom(hit->normal,hit->obj->u.ssphere.sphere.center); v3normalize(hit->normal); } VOID initssphere(VOID) { nameobj[SIMPLE_SPHERE] = "simplesphere"; surfaces[SIMPLE_SPHERE] = 1L; readobj[SI