Home My Page Projects Code Snippets Project Openings 3D graphics for Standard ML
Summary Activity SCM

SCM Repository

[sml3d] Diff of /trunk/sml3d/src/particles/compiler/translate.sml
ViewVC logotype

Diff of /trunk/sml3d/src/particles/compiler/translate.sml

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 974, Tue Aug 31 23:03:51 2010 UTC revision 1107, Wed Apr 6 22:46:51 2011 UTC
# Line 8  Line 8 
8    
9  structure Translate : sig  structure Translate : sig
10    
11      val compile : Particles.particle_group -> PSysIR.program      val compile : Particles.program -> PSysIR.program
12    
13    end = struct    end = struct
14    
# Line 20  Line 20 
20    
21      fun printErr s = TextIO.output(TextIO.stdErr, s ^ "\n")      fun printErr s = TextIO.output(TextIO.stdErr, s ^ "\n")
22    
23    (*
24      datatype particle_state = PS of {      datatype particle_state = PS of {
25          pos : IR.var,           (* vec3 *)          pos : IR.var,           (* vec3 *)
26          vel : IR.var,           (* vec3 *)          vel : IR.var,           (* vec3 *)
27          size : IR.var,          (* float *)          size : IR.var,          (* float *)
28          ttl : IR.var,           (* float *)          ttl : IR.var,           (* float *)
29          color : IR.var,         (* vec3 (NOTE: should be vector4) *)          color : IR.var,         (* vec3 (NOTE: should be vector4) *)
30          pos2 : IR.var,          (* vec3 *)        user : IR.var list
         dummy : IR.var  
31        }        }
32    *)
33        type particle_state = IR.var list
34    
35    (* special PSV global variables *)    (* special PSV global variables *)
36      val epsilon = PSV.constf(0.00001)      val epsilon = PSV.constf(0.00001)
# Line 36  Line 38 
38    (* constants *)    (* constants *)
39      val pi = 3.14159265358979      val pi = 3.14159265358979
40    
41    (* dummy placeholder *)      fun constructUserDefs([]) = []
42      fun dummy (state, k) =        | constructUserDefs(IR.V{id, ...} :: users) =
43            IR.mkPRIM(            (IR.USER_DEF id) :: constructUserDefs(users)
             IR.newLocal(  
               "temp",  
               IR.T_BOOL,  
               (IR.COPY, [IR.newConst("c", IR.C_BOOL false)])  
             ),  
             IR.COPY,  
             [IR.newConst("c", IR.C_BOOL false)],  
             k state  
           )  
44    
45        fun userVarsFromState(PS{user, ...}) = user
46        fun userVarsFromEmit(P.EMIT{...}) = []
47    
48      fun retState s = let      fun retState s = let
49        val PS{pos, vel, size, ttl, color, pos2, dummy} = s        val PS{pos, vel, size, ttl, color, user} = s
50       in       in
51        IR.mkRETURN (        IR.mkRETURN (
52          [pos, vel, size, ttl, color, pos2, dummy],          [pos, vel, size, ttl, color] @ user,
53          [IR.POS, IR.VEL, IR.SZ, IR.TTL, IR.COLOR, IR.POS2, IR.DUMMY]          [IR.POS, IR.VEL, IR.SZ, IR.TTL, IR.COLOR] @ constructUserDefs(user)
54        )        )
55       end       end
56    
57    (* translation environment *)    (* translation environment *)
58      datatype env = TE of (IR.block list ref * IR.var PSV.Map.map)      datatype env = TE of (IR.block list ref * IR.var PSV.Map.map * IR.var PSV.SVMap.map)
59    
60      fun psvToIRVar (TE(_, env), x as PSV.V{name, id, ...}) = (case PSV.Map.find(env, x)      fun psvToIRVar (TE(_, env, _), x as PSV.V{name, id, ...}) = (case PSV.Map.find(env, x)
61             of SOME x' => x'             of SOME x' => x'
62              | NONE => raise Fail (String.concat["unknown variable ", name, " with ID ", Int.toString id])              | NONE => raise Fail (String.concat["unknown variable ", name, " with ID ", Int.toString id])
63            (* end case *))            (* end case *))
64    
65      fun insert (TE(blks, env), x, x') = TE(blks, PSV.Map.insert (env, x, x'))      fun insertVar (TE(blks, varEnv, svarEnv), x, x') = TE(blks, PSV.Map.insert (varenv, x, x'), svarEnv)
66        fun insertSVar (TE(blks, varEnv, svarEnv), x, x') = TE(blks, varenv, PSV.Map.insert (svarEnv, x, x'))
67    
68    (* create a block that implements the given continuation *)    (* create a block that implements the given continuation *)
     fun newBlock (TE(blks, _), k : particle_state -> IR.stmt) = let  
           val pos = IR.newParam ("ps_pos", IR.T_VEC)  
           val vel = IR.newParam ("ps_vel", IR.T_VEC)  
           val size = IR.newParam ("ps_size", IR.T_FLOAT)  
           val ttl = IR.newParam ("ps_ttl", IR.T_FLOAT)  
           val color = IR.newParam ("ps_color", IR.T_VEC)  
           val dummy = IR.newParam ("ps_dummy", IR.T_FLOAT)  
           val pos2 = IR.newParam ("ps_pos2", IR.T_VEC)  
           val state = PS{pos=pos, vel=vel, size=size, ttl=ttl, color=color, pos2=pos2, dummy=dummy}  
           val blk = IR.newBlock ([pos, vel, size, ttl, color, pos2, dummy], k state)  
           in  
             blks := blk :: !blks;  
             blk  
           end  
69    
70          fun newBlockWithArgs (TE(blks, _), args, k : particle_state -> IR.stmt) = let      fun createUserVarCopies( [ ], _ ) = [ ]
71            val pos = IR.newParam ("ps_pos", IR.T_VEC)        | createUserVarCopies( IR.V{varType, ...} :: vars, i) =
72            val vel = IR.newParam ("ps_vel", IR.T_VEC)        IR.newParam ("ps_user" ^ (Int.toString i), varType) :: (createUserVarCopies(vars, i+1))
73            val size = IR.newParam ("ps_size", IR.T_FLOAT)  
74            val ttl = IR.newParam ("ps_ttl", IR.T_FLOAT)      fun newBlockWithArgs (TE(blks, _, _), state , args, k : particle_state -> IR.stmt) = let
75            val color = IR.newParam ("ps_color", IR.T_VEC)             val blk = IR.newBlock (state @ args, k state)
           val dummy = IR.newParam ("ps_dummy", IR.T_FLOAT)  
           val pos2 = IR.newParam ("ps_pos2", IR.T_VEC)  
           val state = PS{pos=pos, vel=vel, size=size, ttl=ttl, color=color, pos2=pos2, dummy = dummy}  
           val blk = IR.newBlock ([pos, vel, size, ttl, color, pos2, dummy] @ args, k state)  
76            in            in
77              blks := blk :: !blks;              blks := blk :: !blks;
78              blk              blk
79            end            end
80    
81      fun goto (PS{pos, vel, size, ttl, color, pos2, dummy}, blk) =          fun newBlock (env, state, k) = newBlockWithArgs(env, state, [], k)
           IR.mkGOTO(blk, [pos, vel, size, ttl, color, pos2, dummy])  
82    
83          fun gotoWithArgs(PS{pos, vel, size, ttl, color, pos2, dummy}, args, blk) =      fun gotoWithArgs(state, args, blk) = IR.mkGOTO(blk, state @ args)
84            IR.mkGOTO(blk, [pos, vel, size, ttl, color, pos2, dummy] @ args)      fun goto (state, blk) = gotoWithArgs(state, [], blk)
85    
86      fun letPRIM (x, ty, p, args, body) = let      fun letPRIM (x, ty, p, args, body) = let
87            val x' = IR.newLocal(x, ty, (p, args))            val x' = IR.newLocal(x, ty, (p, args))
# Line 112  Line 89 
89              IR.mkPRIM(x', p, args, body x')              IR.mkPRIM(x', p, args, body x')
90            end            end
91    
   (* prim bound to state variable (S_LOCAL for now) *)  
     fun letSPRIM(x, ty, p, args, body) = let  
           val x' = IR.new(x, IR.S_LOCAL(ref (p, args)), ty)  
           in  
             IR.mkPRIM(x', p, args, body x')  
           end  
   
92    (* Not sure if this should be made into a primitive or not, but    (* Not sure if this should be made into a primitive or not, but
93     * basically this creates the XOR'd value of var1 and var2 and     * basically this creates the XOR'd value of var1 and var2 and
94     * stores it in result.     * stores it in result.
# Line 129  Line 99 
99            letPRIM("testNAND", IR.T_BOOL, IR.NOT, [testAND], fn testNAND =>            letPRIM("testNAND", IR.T_BOOL, IR.NOT, [testAND], fn testNAND =>
100            letPRIM(result, IR.T_BOOL, IR.AND, [testOR, testNAND], stmt))))            letPRIM(result, IR.T_BOOL, IR.AND, [testOR, testNAND], stmt))))
101    
102        fun genFloatVar (fltVar, env, domain : Float.float P.domain, dist, stmt : IR.var -> IR.stmt) = let
103          fun genRandVal(var, stmt : IR.var -> IR.stmt) = (case dist
104            of P.DIST_UNIFORM =>
105              letPRIM(var, IR.T_FLOAT, IR.RAND, [], stmt)
106    
107             (* The PDF here is f(x) = 2x when 0 < x <= 1, so the CDF is going
108              * to be the integral of f from 0 -> y => y^2. Hence, whenever we
109              * generate a random number, in order to get the random value according
110              * to this probability distribution, we just square it.
111              *)
112             | P.DIST_INC_LIN =>
113              letPRIM("randVal", IR.T_FLOAT, IR.RAND, [], fn randVal =>
114              letPRIM(var, IR.T_FLOAT, IR.MULT, [randVal, randVal], stmt))
115    
116             (* The PDF here is f(x) = -2x + 2 when 0 <= x < 1, so the CDF is going
117              * to be the integral of f from 0 -> y => -(y^2) + 2y. Hence, whenever we
118              * generate a random number, in order to get the random value according
119              * to this probability distribution, we just square it.
120              *)
121             | P.DIST_DEC_LIN =>
122              letPRIM("randVal", IR.T_FLOAT, IR.RAND, [], fn randVal =>
123              letPRIM("randSq", IR.T_FLOAT, IR.MULT, [randVal, randVal], fn randSq =>
124              letPRIM("termOne", IR.T_FLOAT, IR.MULT, [randSq, IR.newConst("negOne", IR.C_FLOAT ~1.0)], fn termOne =>
125              letPRIM("termTwo", IR.T_FLOAT, IR.MULT, [randVal, IR.newConst("negOne", IR.C_FLOAT 2.0)], fn termTwo =>
126              letPRIM(var, IR.T_FLOAT, IR.ADD, [termOne, termTwo], stmt)
127              ))))
128    
129             | _ => raise Fail "Unable to create random float for specified distribution."
130           (* end case *))
131         in
132         (case domain
133          of P.D_POINT(pt) =>
134             (* Our options here are pretty limited... *)
135             letPRIM (fltVar, IR.T_FLOAT, IR.COPY, [psvToIRVar(env, pt)], stmt)
136    
137           | P.D_BOX{max, min} =>
138             genRandVal("randf", fn rand =>
139             letPRIM("boxDiff", IR.T_FLOAT, IR.SUB, [psvToIRVar(env, max), psvToIRVar(env, max)], fn diff =>
140             letPRIM("scale", IR.T_FLOAT, IR.MULT, [diff, rand], fn scale =>
141             letPRIM( fltVar, IR.T_FLOAT, IR.ADD, [psvToIRVar(env, max), scale], stmt )
142             )))
143           | _ => raise Fail "Cannot generate float in specified domain."
144         (* end case *))
145        end
146    
147    (* Generates a random vector within the given domain and puts it in vecVar *)    (* Generates a random vector within the given domain and puts it in vecVar *)
148      fun genVecVar (vecVar, env, domain, stmt : IR.var -> IR.stmt) = (case domain      fun genVecVar (vecVar, env, domain : Vec3f.vec3 P.domain, stmt : IR.var -> IR.stmt) = (case domain
149             of P.D_POINT(pt) =>             of P.D_POINT(pt) =>
150               (* Our options here are pretty limited... *)               (* Our options here are pretty limited... *)
151                  letPRIM (vecVar, IR.T_VEC, IR.COPY, [psvToIRVar(env, pt)], stmt)                  letPRIM (vecVar, IR.T_VEC, IR.COPY, [psvToIRVar(env, pt)], stmt)
# Line 250  Line 265 
265                      letPRIM(vecVar, IR.T_VEC, IR.ADD_VEC, [ptInDisc, scaledNormVec], stmt)))))))))                      letPRIM(vecVar, IR.T_VEC, IR.ADD_VEC, [ptInDisc, scaledNormVec], stmt)))))))))
266                  end                  end
267    
268                    | P.D_SPHERE{center, irad, orad} =>
269    
270              (* generate two random angles... *)
271              letPRIM("r1", IR.T_FLOAT, IR.RAND, [], fn randForAngOne =>
272              letPRIM("t1", IR.T_FLOAT, IR.MULT, [randForAngOne, IR.newConst("fullCit", IR.C_FLOAT (2.0 * pi))], fn randAngOne =>
273              letPRIM("r2", IR.T_FLOAT, IR.RAND, [], fn randForAngTwo =>
274              letPRIM("t2", IR.T_FLOAT, IR.MULT, [randForAngTwo, IR.newConst("fullCit", IR.C_FLOAT (2.0 * pi))], fn randAngTwo =>
275    
276              (* Generate vector in the sphere ... *)
277              (* If my math is correct this should be
278               * <(cos t1)(cos t2), (sin t1)(cos t2), sin t2>
279               * This is different from wikipedia's article on spherical coordinates
280               * because of a phase shift, but for the generation of random numbers,
281               * it's irrelevant.
282               *)
283              letPRIM("cost1", IR.T_FLOAT, IR.COS, [randAngOne], fn cost1 =>
284              letPRIM("cost2", IR.T_FLOAT, IR.COS, [randAngTwo], fn cost2 =>
285              letPRIM("sint1", IR.T_FLOAT, IR.SIN, [randAngOne], fn sint1 =>
286              letPRIM("sint2", IR.T_FLOAT, IR.SIN, [randAngTwo], fn sint2 =>
287    
288              letPRIM("xVal", IR.T_FLOAT, IR.MULT, [cost1, cost2], fn xVal =>
289              letPRIM("yVal", IR.T_FLOAT, IR.MULT, [sint1, cost2], fn yVal =>
290              (* zval is just sint2 *)
291    
292              letPRIM("xVec", IR.T_VEC, IR.SCALE, [xVal, IR.newConst("xDir", IR.C_VEC {x=1.0, y=0.0, z=0.0})], fn xVec =>
293              letPRIM("yVec", IR.T_VEC, IR.SCALE, [yVal, IR.newConst("yDir", IR.C_VEC {x=0.0, y=1.0, z=0.0})], fn yVec =>
294              letPRIM("zVec", IR.T_VEC, IR.SCALE, [sint2, IR.newConst("zDir", IR.C_VEC {x=0.0, y=0.0, z=1.0})], fn zVec =>
295    
296              letPRIM("addedVecs", IR.T_VEC, IR.ADD_VEC, [xVec, yVec], fn addedVecs =>
297              letPRIM("notNormVec", IR.T_VEC, IR.ADD_VEC, [addedVecs, zVec], fn nnVec =>
298              letPRIM("vec", IR.T_VEC, IR.NORM, [nnVec], fn vec =>
299    
300              (* Generate a random radius... *)
301                      letPRIM("ratio", IR.T_FLOAT, IR.DIV, [psvToIRVar(env, irad), psvToIRVar(env, orad)], fn ratio =>
302                      letPRIM("invRatio", IR.T_FLOAT, IR.SUB, [IR.newConst("one", IR.C_FLOAT 1.0), ratio], fn invRatio =>
303                      letPRIM("randVar", IR.T_FLOAT, IR.RAND, [], fn rand =>
304                      letPRIM("randScale", IR.T_FLOAT, IR.MULT, [rand, invRatio], fn randScale =>
305                      letPRIM("randVal", IR.T_FLOAT, IR.ADD, [randScale, ratio], fn randVal =>
306                      letPRIM("randValSq", IR.T_FLOAT, IR.MULT, [randVal, randVal], fn randValSq =>
307                      letPRIM("radDiff", IR.T_FLOAT, IR.SUB, [psvToIRVar(env, orad), psvToIRVar(env, irad)], fn radDiff =>
308                      letPRIM("randRadVal", IR.T_FLOAT, IR.MULT, [radDiff, randValSq], fn randRadVal =>
309                      letPRIM("rad", IR.T_FLOAT, IR.ADD, [psvToIRVar(env, irad), randRadVal], fn rad =>
310    
311                      (* Normalize the vector and scale it by the radius. *)
312                      letPRIM("scaledVec", IR.T_VEC, IR.SCALE, [rad, vec], fn sVec =>
313                      letPRIM(vecVar, IR.T_VEC, IR.ADD_VEC, [sVec, psvToIRVar(env, center)], stmt)
314                      ))))))))))
315                      ))))))))))))
316                      ))))
317    
318              | _ => raise Fail "Cannot generate point in specified domain."              | _ => raise Fail "Cannot generate point in specified domain."
319            (* end case *))            (* end case *))
320            (*            (*
# Line 259  Line 324 
324        | generate (Dblob{c, stddev}) = Vec3f.unpack c        | generate (Dblob{c, stddev}) = Vec3f.unpack c
325            *)            *)
326    
   
327    (* This function takes an IR boolean, its environment, a particle state, domain,    (* This function takes an IR boolean, its environment, a particle state, domain,
328     * and continuation.     * and continuation.
329     *     *
# Line 307  Line 371 
371               *)               *)
372                | P.D_DISC{pt, normal, orad, irad} =>                | P.D_DISC{pt, normal, orad, irad} =>
373                    letPRIM("posToPt", IR.T_VEC, IR.SUB_VEC, [pos, psvToIRVar(env, pt)], fn posToPt =>                    letPRIM("posToPt", IR.T_VEC, IR.SUB_VEC, [pos, psvToIRVar(env, pt)], fn posToPt =>
                   letPRIM("posToPtLen", IR.T_FLOAT, IR.LEN, [posToPt], fn posToPtLen =>  
374                    letPRIM("dot", IR.T_FLOAT, IR.DOT, [posToPt, psvToIRVar(env, normal)], fn dotProd =>                    letPRIM("dot", IR.T_FLOAT, IR.DOT, [posToPt, psvToIRVar(env, normal)], fn dotProd =>
375                    letPRIM("inDisc", IR.T_BOOL, IR.GT, [IR.newConst("small", IR.C_FLOAT 0.01), dotProd], fn inDisc =>                    letPRIM("inDisc", IR.T_BOOL, IR.GT, [IR.newConst("small", IR.C_FLOAT 0.01), dotProd], fn inDisc =>
376                    letPRIM("inOrad", IR.T_BOOL, IR.GT, [psvToIRVar(env, orad), posToPtLen], fn inOrad =>  
377                    letPRIM("inIrad", IR.T_BOOL, IR.GT, [posToPtLen, psvToIRVar(env, irad)], fn inIrad =>                    letPRIM("parPosToP", IR.T_VEC, IR.SCALE, [dotProd, psvToIRVar(env, normal)], fn posToPtParallelToNormal =>
378                      letPRIM("perpPosToP", IR.T_VEC, IR.SUB_VEC, [posToPt, posToPtParallelToNormal], fn posToPtPerpToNormal =>
379                      letPRIM("inDiscLen", IR.T_FLOAT, IR.LEN, [posToPtPerpToNormal], fn posToPtLen =>
380    
381                      letPRIM("inOradGt", IR.T_BOOL, IR.GT, [psvToIRVar(env, orad), posToPtLen], fn inOradGt =>
382                      letPRIM("inOradEq", IR.T_BOOL, IR.EQUALS, [psvToIRVar(env, orad), posToPtLen], fn inOradEq =>
383                      letPRIM("inOrad", IR.T_BOOL, IR.OR, [inOradGt, inOradEq], fn inOrad =>
384    
385                      letPRIM("inIradGt", IR.T_BOOL, IR.GT, [posToPtLen, psvToIRVar(env, irad)], fn inIradGt =>
386                      letPRIM("inIradEq", IR.T_BOOL, IR.EQUALS, [posToPtLen, psvToIRVar(env, irad)], fn inIradEq =>
387                      letPRIM("inIrad", IR.T_BOOL, IR.OR, [inIradGt, inIradEq], fn inIrad =>
388    
389                    letPRIM("inBothRad", IR.T_BOOL, IR.AND, [inIrad, inOrad], fn inBothRad =>                    letPRIM("inBothRad", IR.T_BOOL, IR.AND, [inIrad, inOrad], fn inBothRad =>
390                    letPRIM(boolVar, IR.T_BOOL, IR.AND, [inDisc, inBothRad], stmt))))))))  
391                      letPRIM(boolVar, IR.T_BOOL, IR.AND, [inDisc, inBothRad], stmt))))))))))))))
392    
393              (* Simply see whether or not the distance from the center is within the              (* Simply see whether or not the distance from the center is within the
394               * specified bounds.               * specified bounds.
# Line 324  Line 399 
399                    letPRIM("inOrad", IR.T_BOOL, IR.GT, [psvToIRVar(env, orad), posToCLen], fn inOrad =>                    letPRIM("inOrad", IR.T_BOOL, IR.GT, [psvToIRVar(env, orad), posToCLen], fn inOrad =>
400                    letPRIM("inIrad", IR.T_BOOL, IR.GT, [posToCLen, psvToIRVar(env, irad)], fn inIrad =>                    letPRIM("inIrad", IR.T_BOOL, IR.GT, [posToCLen, psvToIRVar(env, irad)], fn inIrad =>
401                    letPRIM(boolVar, IR.T_BOOL, IR.AND, [inIrad, inOrad], stmt)))))                    letPRIM(boolVar, IR.T_BOOL, IR.AND, [inIrad, inOrad], stmt)))))
402    
403                      | P.D_CYLINDER {pt1, pt2, irad, orad} =>
404    
405                      (* !FIXME! Right now, we see whether or not the point is within the two planes defined
406                       * by the endpoints of the cylinder, and then testing to see whether or not the smallest
407                       * distance to the line segment falls within the radii. It might be faster to find the
408                       * closest point to the line defined by the endpoints and then see whether or not the point
409                       * is within the segment.
410                       *)
411    
412                      (* Is it in one plane *)
413                      letPRIM("plane1Norm", IR.T_VEC, IR.SUB_VEC, [psvToIRVar(env, pt2), psvToIRVar(env, pt1)], fn plane1Norm =>
414                      letPRIM("posToPt1", IR.T_VEC, IR.SUB_VEC, [pos, psvToIRVar(env, pt1)], fn posToPt1 =>
415                      letPRIM("dot1", IR.T_FLOAT, IR.DOT, [posToPt1, plane1Norm], fn dot1Prod =>
416                      letPRIM("inPlane1", IR.T_BOOL, IR.GT, [dot1Prod, IR.newConst("zero", IR.C_FLOAT 0.0)], fn inPlane1=>
417    
418                      (* Is it in another plane *)
419                      letPRIM("plane2Norm", IR.T_VEC, IR.SUB_VEC, [psvToIRVar(env, pt1), psvToIRVar(env, pt2)], fn plane2Norm =>
420                      letPRIM("posToPt2", IR.T_VEC, IR.SUB_VEC, [pos, psvToIRVar(env, pt2)], fn posToPt2 =>
421                      letPRIM("dot2", IR.T_FLOAT, IR.DOT, [posToPt2, plane2Norm], fn dot2Prod =>
422                      letPRIM("inPlane2", IR.T_BOOL, IR.GT, [dot2Prod, IR.newConst("zero", IR.C_FLOAT 0.0)], fn inPlane2=>
423    
424                      (* Is it in both planes? *)
425                      letPRIM("inPlanes", IR.T_BOOL, IR.AND, [inPlane1, inPlane2], fn inPlanes =>
426    
427                      (* Find distance from segment *)
428                      letPRIM("a", IR.T_VEC, IR.SUB_VEC, [psvToIRVar(env, pt2), psvToIRVar(env, pt1)], fn a =>
429                      letPRIM("b", IR.T_VEC, IR.SUB_VEC, [psvToIRVar(env, pt1), pos], fn b =>
430                      letPRIM("alen", IR.T_FLOAT, IR.LEN, [a], fn alen =>
431                      letPRIM("axb", IR.T_VEC, IR.CROSS, [a, b], fn axb =>
432                      letPRIM("axblen", IR.T_FLOAT, IR.LEN, [axb], fn axblen =>
433                      letPRIM("dist", IR.T_FLOAT, IR.DIV, [axblen, alen], fn dist =>
434    
435                      (* Is distance in both radii? *)
436                      letPRIM("inOradGt", IR.T_BOOL, IR.GT, [psvToIRVar(env, orad), dist], fn inOradGt =>
437                      letPRIM("inOradEq", IR.T_BOOL, IR.EQUALS, [psvToIRVar(env, orad), dist], fn inOradEq =>
438                      letPRIM("inOrad", IR.T_BOOL, IR.OR, [inOradGt, inOradEq], fn inOrad =>
439    
440                      letPRIM("inIradGt", IR.T_BOOL, IR.GT, [dist, psvToIRVar(env, irad)], fn inIradGt =>
441                      letPRIM("inIradEq", IR.T_BOOL, IR.EQUALS, [dist, psvToIRVar(env, irad)], fn inIradEq =>
442                      letPRIM("inIrad", IR.T_BOOL, IR.OR, [inIradGt, inIradEq], fn inIrad =>
443    
444                      letPRIM("inBothRad", IR.T_BOOL, IR.AND, [inIrad, inOrad], fn inBothRad =>
445    
446                      (* It's in the cylinder (tube) if it's within both radii and in both planes... *)
447                      letPRIM(boolVar, IR.T_BOOL, IR.AND, [inPlanes, inBothRad], stmt)
448                      ))))))))))))))))))))))
449  (*  (*
450                | P.D_TRIANGLE {pt1: vec3f var, pt2: vec3f var, pt3: vec3f var}                | P.D_TRIANGLE {pt1: vec3f var, pt2: vec3f var, pt3: vec3f var}
451                | P.D_PLANE {pt: vec3f var, normal: vec3f var}                | P.D_PLANE {pt: vec3f var, normal: vec3f var}
452                | P.D_RECT {pt: vec3f var, htvec: vec3f var, wdvec: vec3f var}                | P.D_RECT {pt: vec3f var, htvec: vec3f var, wdvec: vec3f var}
453                | P.D_BOX {min: vec3f var, max: vec3f var}                | P.D_BOX {min: vec3f var, max: vec3f var}
454                | P.D_SPHERE {center: vec3f var, irad: vec3f var, orad: vec3f var}                | P.D_SPHERE {center: vec3f var, irad: vec3f var, orad: vec3f var}
               | P.D_CYLINDER {pt1: vec3f var, pt2: vec3f var, irad: float var, orad: float var}  
455                | P.D_CONE {pt1: vec3f var, pt2: vec3f var, irad: float var, orad: float var}                | P.D_CONE {pt1: vec3f var, pt2: vec3f var, irad: float var, orad: float var}
456                | P.D_BLOB {center: vec3f var, stddev: float var}                | P.D_BLOB {center: vec3f var, stddev: float var}
457                | P.D_DISC {pt: vec3f var, normal: vec3f var, irad: float var, orad: float var}                | P.D_DISC {pt: vec3f var, normal: vec3f var, irad: float var, orad: float var}
# Line 341  Line 462 
462    
463    
464    (* generate code to produce a random particle state from a domain *)    (* generate code to produce a random particle state from a domain *)
465      fun newParticle (posDomain, velDomain, colDomain, env, k : particle_state -> IR.stmt) =      fun newParticle (posDomain, (szDom : Float.float P.domain, szDist), velDomain, colDomain, env, k : particle_state -> IR.stmt) =
466              (* genVecVar (vecVar, env, domain, stmt) *)              (* genVecVar (vecVar, env, domain, stmt) *)
467              genVecVar("ps_pos", env, posDomain, fn newPos =>              genVecVar("ps_pos", env, posDomain, fn newPos =>
468              genVecVar("ps_vel", env, velDomain, fn newVel =>              genVecVar("ps_vel", env, velDomain, fn newVel =>
469              genVecVar("ps_col", env, colDomain, fn newCol =>              genVecVar("ps_col", env, colDomain, fn newCol =>
470              letSPRIM ("ps_size", IR.T_FLOAT, IR.RAND, [], fn newSize =>              genFloatVar("ps_size", env, szDom, szDist, fn newSize =>
471              letSPRIM ("ps_ttl", IR.T_FLOAT, IR.COPY, [IR.newConst("fbool", IR.C_FLOAT 10000.0)], fn newIsDead =>              letPRIM ("ps_ttl", IR.T_FLOAT, IR.COPY, [IR.newConst("fbool", IR.C_FLOAT 10000.0)], fn newIsDead =>
472                k(PS{pos = newPos,                k(PS{pos = newPos,
473                     vel = newVel,                     vel = newVel,
474                     size = newSize,                     size = newSize,
475                     ttl = newIsDead,                     ttl = newIsDead,
476                     color = newCol,                     color = newCol,
477                     pos2 = IR.newConst("ps_pos2", IR.C_VEC {x=0.0, y=0.0, z=0.0}),                     user = []})
                    dummy = IR.newConst("ps_dummy", IR.C_FLOAT 0.01)})  
478              )))))              )))))
479    
480      (* Find the normal at the given position of the particle for the specified      (* Find the normal at the given position of the particle for the specified
# Line 363  Line 483 
483       *)       *)
484      fun normAtPoint(retNorm, d, env, state, k : IR.var -> particle_state -> IR.stmt) = let      fun normAtPoint(retNorm, d, env, state, k : IR.var -> particle_state -> IR.stmt) = let
485        val newNorm = IR.newParam("n", IR.T_VEC)        val newNorm = IR.newParam("n", IR.T_VEC)
486        val nextBlk = newBlockWithArgs(env, [newNorm], k(newNorm))        val nextBlk = newBlockWithArgs(env, userVarsFromState(state), [newNorm], k(newNorm))
487        val PS{pos, ...} = state        val PS{pos, ...} = state
488       in       in
489        (case d        (case d
# Line 398  Line 518 
518    
519          fun trEmitter(emit, env, state, k : particle_state -> IR.stmt) = let          fun trEmitter(emit, env, state, k : particle_state -> IR.stmt) = let
520    
521            val PS{ttl, ...} = state            val P.EMIT{freq, sv_gens} = emit
522            val P.EMIT{maxNum, posDomain, velDomain, colDomain, ...} = emit            val blk = newBlock (env, user, k)
           val blk = newBlock (env, k)  
523           in           in
524            letPRIM("isDead", IR.T_BOOL, IR.GT, [IR.newConst("small", IR.C_FLOAT 0.1), ttl], fn isDead =>            letPRIM("isDead", IR.T_BOOL, IR.GT, [IR.newConst("small", IR.C_FLOAT 0.1), ttl], fn isDead =>
525        IR.mkIF(isDead,        IR.mkIF(isDead,
526         (* then *)         (* then *)
527         letPRIM("t1", IR.T_FLOAT, IR.ITOF, [psvToIRVar (env, maxNum)], fn t1 =>         genFloatVar("t1", env, rDom, rDist, fn t1 =>
528         letPRIM("t2", IR.T_FLOAT, IR.ITOF, [psvToIRVar (env, PSV.numDead)], fn t2 =>         letPRIM("t2", IR.T_FLOAT, IR.ITOF, [psvToIRVar (env, PSV.numDead)], fn t2 =>
529         letPRIM("prob", IR.T_FLOAT, IR.DIV, [t1, t2], fn prob =>         letPRIM("prob", IR.T_FLOAT, IR.DIV, [t1, t2], fn prob =>
530         letPRIM("r", IR.T_FLOAT, IR.RAND, [], fn r =>         letPRIM("r", IR.T_FLOAT, IR.RAND, [], fn r =>
531         letPRIM("t3", IR.T_BOOL, IR.GT, [prob, r], fn t3 =>         letPRIM("t3", IR.T_BOOL, IR.GT, [prob, r], fn t3 =>
532         IR.mkIF(t3,         IR.mkIF(t3,
533          (* then *)          (* then *)
534          newParticle (posDomain, velDomain, colDomain, env,          newParticle (posDomain, szDomain, velDomain, colDomain, env,
535           fn state' => retState state'),           fn state' => retState state'),
536          (* else *)          (* else *)
537          IR.DISCARD)))))),          IR.DISCARD)))))),
# Line 432  Line 551 
551           end           end
552    
553      fun trAct (action, env, state, k : particle_state -> IR.stmt) = let      fun trAct (action, env, state, k : particle_state -> IR.stmt) = let
554            val PS{pos, vel, size, ttl, color, pos2, dummy} = state            val PS{pos, vel, size, ttl, color, user} = state
555            in            in
556              case action              case action
557               of P.BOUNCE{friction, resilience, cutoff, d} => let               of P.BOUNCE{friction, resilience, cutoff, d} => let
558                    val blk = newBlock (env, k)                    val blk = newBlock (env, user, k)
559                    val negOne = IR.newConst("negOne", IR.C_FLOAT ~1.0)                    val negOne = IR.newConst("negOne", IR.C_FLOAT ~1.0)
560                    in                    in
561                      letPRIM("vs", IR.T_VEC, IR.SCALE, [psvToIRVar(env, PSV.timeStep), vel], fn velScale =>                      letPRIM("vs", IR.T_VEC, IR.SCALE, [psvToIRVar(env, PSV.timeStep), vel], fn velScale =>
562                      letPRIM("np", IR.T_VEC, IR.ADD_VEC, [pos, velScale], fn nextPos =>                      letPRIM("np", IR.T_VEC, IR.ADD_VEC, [pos, velScale], fn nextPos =>
563                      mkWithinVar("wnp", env, pos, d, fn withinNextPos =>                      mkWithinVar("wcp", env, pos, d, fn withinCurPos =>
564                      IR.mkIF(withinNextPos,                      mkWithinVar("wnp", env, nextPos, d, fn withinNextPos =>
565                        letPRIM("nwcp", IR.T_BOOL, IR.NOT, [withinCurPos], fn notWithinCurPos =>
566                        letPRIM("sb", IR.T_BOOL, IR.AND, [notWithinCurPos, withinNextPos], fn shouldBounce =>
567                        IR.mkIF(shouldBounce,
568                        (*then*)                        (*then*)
569                          normAtPoint("n", d, env, state, fn normAtD => fn state' => let                          normAtPoint("n", d, env, state, fn normAtD => fn state' => let
570                 val PS{pos=nextPos, vel=nextVel, size=nextSize, ttl=nextIsDead, color=nextColor, pos2=nextPos2, dummy=nextDummy} = state'                 val PS{pos=nextPos, vel=nextVel, size=nextSize, ttl=nextIsDead, color=nextColor, user=nextUser} = state'
571                            in                            in
572                             letPRIM("negVel", IR.T_VEC, IR.SCALE, [negOne, nextVel], fn negVel =>                             letPRIM("negVel", IR.T_VEC, IR.SCALE, [negOne, nextVel], fn negVel =>
573                             letPRIM("dnv", IR.T_FLOAT, IR.DOT, [negVel, normAtD], fn dotNegVel =>                             letPRIM("dnv", IR.T_FLOAT, IR.DOT, [negVel, normAtD], fn dotNegVel =>
# Line 464  Line 586 
586                               letPRIM("f", IR.T_FLOAT, IR.MULT, [negOne, frictInv], fn modFrict =>                               letPRIM("f", IR.T_FLOAT, IR.MULT, [negOne, frictInv], fn modFrict =>
587                               letPRIM("fTang", IR.T_VEC, IR.SCALE, [modFrict, tang], fn frictTang =>                               letPRIM("fTang", IR.T_VEC, IR.SCALE, [modFrict, tang], fn frictTang =>
588                               letPRIM("newVel", IR.T_VEC, IR.ADD_VEC, [frictTang, resNorm], fn newVel =>                               letPRIM("newVel", IR.T_VEC, IR.ADD_VEC, [frictTang, resNorm], fn newVel =>
589                                goto(PS{pos=nextPos, vel=newVel, size=nextSize, ttl=nextIsDead, color=nextColor, pos2=nextPos2, dummy=nextDummy}, blk)                                goto(PS{pos=nextPos, vel=newVel, size=nextSize, ttl=nextIsDead, color=nextColor, user=nextUser}, blk)
590                              )))),                              )))),
591                               (*else*)                               (*else*)
592                               letPRIM("fTang", IR.T_VEC, IR.SCALE, [negOne, tang], fn frictTang =>                               letPRIM("fTang", IR.T_VEC, IR.SCALE, [negOne, tang], fn frictTang =>
593                               letPRIM("ps_vel", IR.T_VEC, IR.ADD_VEC, [frictTang, resNorm], fn newVel =>                               letPRIM("ps_vel", IR.T_VEC, IR.ADD_VEC, [frictTang, resNorm], fn newVel =>
594                                goto(PS{pos=nextPos, vel=newVel, size=nextSize, ttl=nextIsDead, color=nextColor, pos2=nextPos2, dummy=nextDummy}, blk)                                goto(PS{pos=nextPos, vel=newVel, size=nextSize, ttl=nextIsDead, color=nextColor, user=nextUser}, blk)
595                               ))                               ))
596                           )))))))))                           )))))))))
597                           end                           end
598                        ),                        ),
599                        (*else*)                        (*else*)
600                        goto(state, blk)))))                        goto(state, blk))))))))
601                    end                    end
602    
603                | P.ACCEL dir =>                | P.ACCEL dir =>
604                      letPRIM("scaledVec", IR.T_VEC, IR.SCALE, [psvToIRVar(env, PSV.timeStep), psvToIRVar(env, dir)], fn theScale =>                      letPRIM("scaledVec", IR.T_VEC, IR.SCALE, [psvToIRVar(env, PSV.timeStep), psvToIRVar(env, dir)], fn theScale =>
605                      letPRIM("ps_vel", IR.T_VEC, IR.ADD_VEC, [theScale, vel], fn newVel =>                      letPRIM("ps_vel", IR.T_VEC, IR.ADD_VEC, [theScale, vel], fn newVel =>
606                        k(PS{pos = pos, vel = newVel, size = size, ttl = ttl, color = color, pos2=pos2, dummy=dummy})))                        k(PS{pos = pos, vel = newVel, size = size, ttl = ttl, color = color, user = user})))
607    
608                | P.MOVE =>                | P.MOVE =>
609                  letPRIM("scaledVec", IR.T_VEC, IR.SCALE, [psvToIRVar(env, PSV.timeStep), vel], fn theScale =>                  letPRIM("scaledVec", IR.T_VEC, IR.SCALE, [psvToIRVar(env, PSV.timeStep), vel], fn theScale =>
610                      letPRIM("ps_pos", IR.T_VEC, IR.ADD_VEC, [theScale, pos], fn newPos =>                      letPRIM("ps_pos", IR.T_VEC, IR.ADD_VEC, [theScale, pos], fn newPos =>
611                        k(PS{pos = newPos, vel = vel, size = size, ttl = ttl, color = color, pos2=pos2, dummy=dummy})))                        k(PS{pos = newPos, vel = vel, size = size, ttl = ttl, color = color, user = user})))
612                (*  
613                | P.SINK({d, kill_inside}) =>                | P.ORBITPOINT {center, mag, maxRad} => let
614                      mkWithinVar("isWithin", env, state, d, fn withinVal =>                    val blk = newBlock (env, user, k)
615                      mkXOR ("shouldNotKill", withinVal, psvToIRVar(env, kill_inside),                   in
616                        fn shouldNotKill =>                    letPRIM("toCenter", IR.T_VEC, IR.SUB_VEC, [psvToIRVar(env, center), pos], fn toCenter =>
617                      letPRIM("shouldKill", IR.T_BOOL, IR.NOT, [shouldNotKill], fn shouldKill =>                    letPRIM("dist", IR.T_FLOAT, IR.LEN, [toCenter], fn dist =>
618                      letPRIM("isReallyDead", IR.T_BOOL, IR.OR, [shouldKill, ttl], fn isReallyDead =>                    letPRIM("radInDist", IR.T_BOOL, IR.GT, [dist, psvToIRVar(env, maxRad)], fn radInDist =>
619                      k(PS{pos = pos, vel = vel, size = size, ttl = isReallyDead, color = color})                    IR.mkIF(radInDist,
620                          ))))                      (* then *)
621                *)                      goto(state, blk),
622                        (* else *)
623                    letPRIM("magRatio", IR.T_FLOAT, IR.DIV, [dist, psvToIRVar(env, maxRad)], fn magRatio =>
624                    letPRIM("oneMinMR", IR.T_FLOAT, IR.SUB, [IR.newConst("one", IR.C_FLOAT 1.0), magRatio], fn oneMinMR =>
625                    letPRIM("gravityMag", IR.T_FLOAT, IR.MULT, [oneMinMR, psvToIRVar(env, mag)], fn gravityMag =>
626                    letPRIM("totalMag", IR.T_FLOAT, IR.MULT, [gravityMag, psvToIRVar(env, PSV.timeStep)], fn totMag =>
627                    letPRIM("acc", IR.T_VEC, IR.SCALE, [totMag, toCenter], fn acc =>
628                    letPRIM("ps_vel", IR.T_VEC, IR.ADD_VEC, [vel, acc], fn newVel =>
629                    goto(PS{pos = pos, vel = newVel, size = size, ttl = ttl, color = color, user=user}, blk)
630                      ))))))))))
631                     end
632    
633    
634                | P.ORBITLINESEG {endp1, endp2, maxRad, mag} => let                | P.ORBITLINESEG {endp1, endp2, maxRad, mag} => let
635                    val blk = newBlock (env, k)                    val blk = newBlock (env, user, k)
636                  in                  in
637                  letPRIM("subVec", IR.T_VEC, IR.SUB_VEC, [psvToIRVar(env, endp2), psvToIRVar(env, endp1)], fn subVec =>                  letPRIM("subVec", IR.T_VEC, IR.SUB_VEC, [psvToIRVar(env, endp2), psvToIRVar(env, endp1)], fn subVec =>
638                  letPRIM("vecToEndP", IR.T_VEC, IR.SUB_VEC, [pos, psvToIRVar(env, endp1)], fn vecToEndP =>                  letPRIM("vecToEndP", IR.T_VEC, IR.SUB_VEC, [pos, psvToIRVar(env, endp1)], fn vecToEndP =>
# Line 522  Line 655 
655                    letPRIM("accVec", IR.T_VEC, IR.SUB_VEC, [closestP, pos], fn accVec =>                    letPRIM("accVec", IR.T_VEC, IR.SUB_VEC, [closestP, pos], fn accVec =>
656                    letPRIM("acc", IR.T_VEC, IR.SCALE, [totMag, accVec], fn acc =>                    letPRIM("acc", IR.T_VEC, IR.SCALE, [totMag, accVec], fn acc =>
657                    letPRIM("ps_vel", IR.T_VEC, IR.ADD_VEC, [vel, acc], fn newVel =>                    letPRIM("ps_vel", IR.T_VEC, IR.ADD_VEC, [vel, acc], fn newVel =>
658                    goto(PS{pos = pos, vel = newVel, size = size, ttl = ttl, color = color, pos2=pos2, dummy=dummy}, blk)                    goto(PS{pos = pos, vel = newVel, size = size, ttl = ttl, color = color, user=user}, blk)
659                    )))))))                    )))))))
660                  )))))))))))                  )))))))))))
661                  end                  end
# Line 535  Line 668 
668            end            end
669    
670      fun compile (P.PG{      fun compile (P.PG{
671         emit as P.EMIT{maxNum, vars=emitVars, ...},         emit as P.EMIT{freq, sv_gens}, act, render,
672         act as P.PSAE{action=root_act, vars=actionVars},         vars, state_vars, render_vars
        render  
673      }) = let      }) = let
674            val blks = ref[]            val blks = ref[]
675            val env = let            val env = let
676                (* add special globals to free vars *)                (* add special globals to free vars *)
677                  val vars = PSV.Set.union(emitVars, PSV.Set.addList(actionVars, [maxNum, PSV.numDead, PSV.timeStep, epsilon]))          val pgm_vars = PSV.Set.union(PSV.Set.singleton epsilon, vars)
678                  fun ins (x as PSV.V{name, ty, binding, id, ...}, map) = let          fun insv (x as PSV.V{name, ty, binding, id, ...}, map) = let
679                        val x' = (case (ty, !binding)                        val x' = (case (ty, !binding)
680                               of (PSV.T_BOOL,  PSV.UNDEF) => IR.newGlobal(x, IR.T_BOOL)                               of (PSV.T_BOOL,  PSV.UNDEF) => IR.newGlobal(x, IR.T_BOOL)
681                                | (PSV.T_BOOL,  PSV.BOOL boolVal) => IR.newConst(name, IR.C_BOOL(boolVal))                                | (PSV.T_BOOL,  PSV.BOOL boolVal) => IR.newConst(name, IR.C_BOOL(boolVal))
# Line 557  Line 689 
689                              (* end case *))                              (* end case *))
690                        in                        in
691                          PSV.Map.insert (map, x, x')                          PSV.Map.insert (map, x, x')
692                        end                     end (* ins *)
693    
694                     fun convertToIR PSV.SV{name, ty, id, ...} = IR.newParam(name, IR.psvTyToIRTy ty)
695                     fun inssv (x, map) = PSV.SVMap.insert(map, x, convertToIR x)
696                  in                  in
697                    TE(blks, PSV.Set.foldl ins PSV.Map.empty vars)                    TE(
698                  end                     blks,
699                       PSV.Set.foldl insv PSV.Map.empty pgm_vars,
700                       PSV.SVSet.foldl inssv PSV.SVMap.empty state_vars
701                      )
702                    end (* env *)
703    
704        fun evalActs f [] state = f [] state        fun evalActs f [] state = f [] state
705              | evalActs f (psa :: psal) state = (case psa              | evalActs f (psa :: psal) state = (case psa
# Line 570  Line 709 
709                    | act :: rest => trAct(act, env, state, evalActs f (P.SEQ(rest) :: psal))                    | act :: rest => trAct(act, env, state, evalActs f (P.SEQ(rest) :: psal))
710                  (* end case *))                  (* end case *))
711                 | P.PRED(pred as P.PR{thenstmt=t, elsestmt=e, ...}) => let                 | P.PRED(pred as P.PR{thenstmt=t, elsestmt=e, ...}) => let
712                     val cblk = newBlock(env, evalActs f psal)                  val cblk = newBlock(env, userVarsFromState(state), evalActs f psal)
713                     fun trPredActs [] state' = goto(state', cblk)                     fun trPredActs [] state' = goto(state', cblk)
714                       | trPredActs _ _ = raise Fail "Should never reach here."                       | trPredActs _ _ = raise Fail "Should never reach here."
715                    in                    in
# Line 579  Line 718 
718                (* end case *))                (* end case *))
719    
720            (* At the highest level, we want to return when we reach the end of the action list *)            (* At the highest level, we want to return when we reach the end of the action list *)
721            fun trActs [] state = let            fun trActs [] state = retState state
                 val PS{pos, vel, size, ttl, color, pos2, dummy} = state  
                 in  
                   IR.mkRETURN (  
                     [ pos, vel, size, ttl, color, pos2, dummy ],  
                     [IR.POS, IR.VEL, IR.SZ, IR.TTL, IR.COLOR, IR.POS2, IR.DUMMY]  
                   )  
                 end (* trActs *)  
722              | trActs _ _ = raise Fail "Should never reach here"              | trActs _ _ = raise Fail "Should never reach here"
723    
724            (* The entry block is the first block of the program, or in other words, the emitter. *)            (* The entry block is the first block of the program, or in other words, the emitter. *)
725            val entryBlock = newBlock (            val entryBlock = newBlock (
726              env,              env,
727                List.map convertToIR state_vars,
728              fn pstate => trEmitter(              fn pstate => trEmitter(
729                emit,                emit,
730                env,                env,
# Line 611  Line 744 
744    
745            val outPgm = PSysIR.PGM {            val outPgm = PSysIR.PGM {
746              globals = PSV.Map.filter isGlobal (extractVarMap env),              globals = PSV.Map.filter isGlobal (extractVarMap env),
747                persistents = [],
748                uveOptimized = false,
749          emitter = entryBlock,          emitter = entryBlock,
750              physics = List.nth(!blks, 1),              physics = List.nth(!blks, 1),
751              render = render              render = render
# Line 620  Line 755 
755    
756            in            in
757              (* IR.outputPgm(TextIO.stdErr, outPgm); *)              (* IR.outputPgm(TextIO.stdErr, outPgm); *)
758              if Checker.checkIR(optimized) then  
759               printErr "Compilation succeeded." (* Note: it only succeeds if we can optimize, too *)              (* Note: it only succeeds if we can optimize, too *)
760              else          if Checker.checkIR(optimized) then printErr "Compilation succeeded." else ();
761               ();  
762              optimized              optimized
763            end (* compile *)            end (* compile *)
764    

Legend:
Removed from v.974  
changed lines
  Added in v.1107

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0