## initially generated by c2l# implement Collide; include "draw.m"; draw: Draw; Display, Image: import draw; Collide: module{ init: fn(nil: ref Draw->Context, argl: list of string);}; include "sys.m"; sys: Sys;include "tk.m"; tk: Tk; Toplevel: import tk;include "tkclient.m"; tkclient: Tkclient;include "math.m"; maths: Math;include "rand.m"; rand: Rand;include "daytime.m"; daytime: Daytime;include "bufio.m";include "arg.m"; arg: Arg;include "math/polyhedra.m"; polyhedra: Polyhedra; init(ctxt: ref Draw->Context, argl: list of string){ sys = load Sys Sys->PATH; draw = load Draw Draw->PATH; tk = load Tk Tk->PATH; tkclient = load Tkclient Tkclient->PATH; maths = load Math Math->PATH; rand = load Rand Rand->PATH; arg = load Arg Arg->PATH; daytime = load Daytime Daytime->PATH; main(ctxt, argl);} π: con Math->Pi;∞: con real (1<<30);ε: con 0.001;√2: con 1.4142135623730950488016887242096980785696718753769486732; M1: con 1.0;M2: con 1.0;E: con 1.0; # coefficient of restitution/elasticity COLLIDE, REFLECT: con 1<<iota; MAXX, MAXY: con 512; RDisp: ref Draw->Image;black, white, red: ref Draw->Image;display: ref Draw->Display;toplev: ref Toplevel; Vector: adt{ x: real; y: real; z: real;}; Line: adt{ a: Vector; d: Vector; # normalized}; Plane: adt{ id: int; n: Vector; # normalized d: real; min: Vector; max: Vector; far: Vector; v: array of Vector;}; Object: adt{ id: int; poly: ref Polyhedra->Polyhedron; # if any c: ref Draw->Image; # colour cb: ref Draw->Image; # border colour l: ref Line; # initial point and direction p: Vector; # current position rp: Vector; # position after reflection cp: Vector; # any collision point rt: real; # time to reflection ct: real; # time to collision plane: ref Plane; # reflecting off pmask: int; # plane mask obj: cyclic ref Object; # colliding with v: real; # speed ω: real; # speed of rotation roll: real; # roll pitch: real; # pitch yaw: real; # yaw todo: int; # work to do}; planes: list of ref Plane; V0: con Vector(real 0, real 0, real 0);VZ: con Vector(0.0, 0.0, 1.0); far: Vector; DOCIRCLE: con 1;POLY, FILLPOLY, CIRCLE, FILLCIRCLE, ELLIPSE, FILLELLIPSE: con iota; ## final object is centred on (0, 0, -objd)# viewer is at origin looking along (0 0 -1)# maxx, maxy: int; SCRW: con 320; # screen widthSCRH: con 240; # screen height frac := 0.5; # % of screen for cubefront := 0.5; # % of cube in front of screenhpar := 0.0; # horizontal parallaxfov := -1.0; # field of view : 0 for parallel projection, -1 for unspecifiedobjd := 500.0; # eye to middle of cubecubd := 100.0; # half side of cubeicubd: real; # half side of inner cubeicubd2: real; # square of aboveeyed := 32.0; # half eye to eyetrkd := 5.0; # side/diameter of objecttrkd2: real; # square of aboverpy := 0;roll := 0.0; # zpitch := 0.0; # yyaw := 0.0; # x scrd, objD, scrD: real; # screen distanceleft := 0; # left or right eyesx, sy, sz: real; # screen scale factors sf: real; # perspective scale factor fbpar: real; # -1 for front of cube, 1 for backvf := 1.0; # current velocity factor cmin, cmax: Vector; # cube extents # special transformation matrix without roll, pitch, yaw # this is needed so that spheres can be drawn as circles mod0 := array[4] of array of real; stereo := 0; # stereopsis SPHERE, ELLIPSOID, CUBE, POLYHEDRON: con iota;surr := CUBE; # surround poly := 0; # show polyhedraflat: int; # objects in one planeprojx: int; # strange projection # ellipse parametersef: Vector = (1.0, 0.8, 1.0);e2: Vector; # objectsnobjs: int;objs: array of ref Object;me: ref Object; # circle drawingNC: con 72;cost, sint: array of real; # polyhedrapolys: ref Polyhedra->Polyhedron;npolys: int;polyh: ref Polyhedra->Polyhedron; rgba(r: int, g: int, b: int, α: int): ref Image{ c := draw->setalpha((r<<24)|(g<<16)|(b<<8), α); return display.newimage(((0, 0), (1, 1)), display.image.chans, 1, c);} random(a: int, b: int): int{ return a+rand->rand(b-a+1);} urand(): real{ M: con 1000; return real random(0, M)/real M;} randomr(a: real, b: real): real{ return a+urand()*(b-a);} randomc(): ref Image{ r, g, b: int; do{ r = random(0, 255); g = random(0, 255); b = random(0, 255); }while(r+g+b < 384); return rgba(r, g, b, 255);} randomv(a: real, b: real): Vector{ x := randomr(a, b); y := randomr(a, b); if(flat) return (x, y, (a+b)/2.0); return (x, y, randomr(a, b));} randomd(): Vector{ M: con 1000.0; v := randomv(-M, M); while(vlen(v) == 0.0) v = randomv(-M, M); return vnorm(v);} randomp(min: real, max: real): Vector{ case(surr){ SPHERE => return vmul(randomd(), max*maths->sqrt(urand())); ELLIPSOID => return vmul(randomd(), max*vmin(ef)*maths->sqrt(urand())); CUBE => return randomv(min, max); * => v := randomv(min, max); while(outside3(v, cmin, cmax)) v = randomv(min, max); return v; }} det(a: real, b: real, c: real, d: real): real{ return a*d-b*c;} simeq(a: real, b: real, c: real, d: real, e: real, f: real): (real, real){ de := det(a, b, c, d); return (det(e, b, f, d)/de, det(a, e, c, f)/de);} cksimeq(a: real, b: real, c: real, d: real, e: real, f: real): (int, real, real){ ade := de := det(a, b, c, d); if(ade < 0.0) ade = -ade; if(ade < ε) return (0, 0.0, 0.0); return (1, det(e, b, f, d)/de, det(a, e, c, f)/de);} ostring(o: ref Object): string{ return lstring(o.l) + "+" + vstring(o.p) + "+" + string o.v;} pstring(p: ref Plane): string{ return vstring(p.n) + "=" + string p.d;} lstring(l: ref Line): string{ return vstring(l.a) + "->" + vstring(l.d);} vstring(v: Vector): string{ return "(" + string v.x + " " + string v.y + " " + string v.z + ")";} vpt(x: real, y: real, z: real): Vector{ p: Vector; p.x = x; p.y = y; p.z = z; return p;} vdot(v1: Vector, v2: Vector): real{ return v1.x*v2.x+v1.y*v2.y+v1.z*v2.z;} vcross(v1: Vector, v2: Vector): Vector{ v: Vector; 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; return v;} vadd(v1: Vector, v2: Vector): Vector{ v: Vector; v.x = v1.x+v2.x; v.y = v1.y+v2.y; v.z = v1.z+v2.z; return v;} vsub(v1: Vector, v2: Vector): Vector{ v: Vector; v.x = v1.x-v2.x; v.y = v1.y-v2.y; v.z = v1.z-v2.z; return v;} vmul(v1: Vector, s: real): Vector{ v: Vector; v.x = s*v1.x; v.y = s*v1.y; v.z = s*v1.z; return v;} vdiv(v1: Vector, s: real): Vector{ v: Vector; v.x = v1.x/s; v.y = v1.y/s; v.z = v1.z/s; return v;} vlen(v: Vector): real{ return maths->sqrt(vdot(v, v));} vlen2(v: Vector): (real, real){ d2 := vdot(v, v); d := maths->sqrt(d2); return (d, d2);} vnorm(v: Vector): Vector{ d := maths->sqrt(vdot(v, v)); if(d == 0.0) return v; return vmul(v, real 1/d);} vnorm2(v: Vector): (real, Vector){ d := maths->sqrt(vdot(v, v)); if(d == 0.0) return (0.0, VZ); return (d, vmul(v, real 1/d));} clip(x: real, d: real): real{ if(x < -d) x = -d; if(x > d) x = d; return x;} vclip(v: Vector, d: real): Vector{ c: Vector; c.x = clip(v.x, d); c.y = clip(v.y, d); c.z = clip(v.z, d); return c;} vout(v1: Vector, v2: Vector): int{ v := vsub(v2, v1); return v.x < 0.0 || v.y < 0.0 || v.z < 0.0;} vmin(v: Vector): real{ m := v.x; if(v.y < m) m = v.y; if(v.z < m) m = v.z; return m;} vvmul(v1: Vector, v2: Vector): Vector{ v: Vector; v.x = v1.x*v2.x; v.y = v1.y*v2.y; v.z = v1.z*v2.z; return v;} vvdiv(v1: Vector, v2: Vector): Vector{ v: Vector; v.x = v1.x/v2.x; v.y = v1.y/v2.y; v.z = v1.z/v2.z; return v;} vmuldiv(v1: Vector, v2: Vector, v3: Vector): real{ return vdot(vvdiv(v1, v3), v2);} newp(id: int, a: real, b: real, c: real, d: real, m: real, v: array of Vector){ p := ref Plane; p.id = id; p.n = (a, b, c); p.d = d; m += ε; p.min = (-m, -m, -m); p.max = (+m, +m, +m); p.v = v; if(v != nil){ p.min = (∞, ∞, ∞); p.max = (-∞, -∞, -∞); for(i := 0; i < len v; i++){ vtx := v[i]; if(vtx.x < p.min.x) p.min.x = vtx.x; if(vtx.y < p.min.y) p.min.y = vtx.y; if(vtx.z < p.min.z) p.min.z = vtx.z; if(vtx.x > p.max.x) p.max.x = vtx.x; if(vtx.y > p.max.y) p.max.y = vtx.y; if(vtx.z > p.max.z) p.max.z = vtx.z; } (x, y, z) := p.far = vmul(p.max, 2.0); if(a != 0.0) p.far.x = (d-b*y-c*z)/a; else if(b != 0.0) p.far.y = (d-c*z-a*x)/b; else if(c != 0.0) p.far.z = (d-a*x-b*y)/c; else fatal("null plane"); } planes = p :: planes;} pinit(){ case(surr){ SPHERE or ELLIPSOID => newp(0, 0.0, 0.0, 1.0, ∞, ∞, nil); CUBE => newp(0, 1.0, 0.0, 0.0, -icubd, icubd, nil); newp(1, 1.0, 0.0, 0.0, +icubd, icubd, nil); newp(2, 0.0, 1.0, 0.0, -icubd, icubd, nil); newp(3, 0.0, 1.0, 0.0, +icubd, icubd, nil); newp(4, 0.0, 0.0, 1.0, -icubd, icubd, nil); newp(5, 0.0, 0.0, 1.0, +icubd, icubd, nil);Lines 1–500 of 2180. Load more
# # initially generated by c2l # implement Collide; include "draw.m"; draw: Draw; Display, Image: import draw; Collide: module { init: fn(nil: ref Draw->Context, argl: list of string); }; include "sys.m"; sys: Sys; include "tk.m"; tk: Tk; Toplevel: import tk; include "tkclient.m"; tkclient: Tkclient; include "math.m"; maths: Math; include "rand.m"; rand: Rand; include "daytime.m"; daytime: Daytime; include "bufio.m"; include "arg.m"; arg: Arg; include "math/polyhedra.m"; polyhedra: Polyhedra; init(ctxt: ref Draw->Context, argl: list of string) { sys = load Sys Sys->PATH; draw = load Draw Draw->PATH; tk = load Tk Tk->PATH; tkclient = load Tkclient Tkclient->PATH; maths = load Math Math->PATH; rand = load Rand Rand->PATH; arg = load Arg Arg->PATH; daytime = load Daytime Daytime->PATH; main(ctxt, argl); } π: con Math->Pi; ∞: con real (1<<30); ε: con 0.001; √2: con 1.4142135623730950488016887242096980785696718753769486732; M1: con 1.0; M2: con 1.0; E: con 1.0; # coefficient of restitution/elasticity COLLIDE, REFLECT: con 1<<iota; MAXX, MAXY: con 512; RDisp: ref Draw->Image; black, white, red: ref Draw->Image; display: ref Draw->Display; toplev: ref Toplevel; Vector: adt{ x: real; y: real; z: real; }; Line: adt{ a: Vector; d: Vector; # normalized }; Plane: adt{ id: int; n: Vector; # normalized d: real; min: Vector; max: Vector; far: Vector; v: array of Vector; }; Object: adt{ id: int; poly: ref Polyhedra->Polyhedron; # if any c: ref Draw->Image; # colour cb: ref Draw->Image; # border colour l: ref Line; # initial point and direction p: Vector; # current position rp: Vector; # position after reflection cp: Vector; # any collision point rt: real; # time to reflection ct: real; # time to collision plane: ref Plane; # reflecting off pmask: int; # plane mask obj: cyclic ref Object; # colliding with v: real; # speed ω: real; # speed of rotation roll: real; # roll pitch: real; # pitch yaw: real; # yaw todo: int; # work to do }; planes: list of ref Plane; V0: con Vector(real 0, real 0, real 0); VZ: con Vector(0.0, 0.0, 1.0); far: Vector; DOCIRCLE: con 1; POLY, FILLPOLY, CIRCLE, FILLCIRCLE, ELLIPSE, FILLELLIPSE: con iota; # # final object is centred on (0, 0, -objd) # viewer is at origin looking along (0 0 -1) # maxx, maxy: int; SCRW: con 320; # screen width SCRH: con 240; # screen height frac := 0.5; # % of screen for cube front := 0.5; # % of cube in front of screen hpar := 0.0; # horizontal parallax fov := -1.0; # field of view : 0 for parallel projection, -1 for unspecified objd := 500.0; # eye to middle of cube cubd := 100.0; # half side of cube icubd: real; # half side of inner cube icubd2: real; # square of above eyed := 32.0; # half eye to eye trkd := 5.0; # side/diameter of object trkd2: real; # square of above rpy := 0; roll := 0.0; # z pitch := 0.0; # y yaw := 0.0; # x scrd, objD, scrD: real; # screen distance left := 0; # left or right eye sx, sy, sz: real; # screen scale factors sf: real; # perspective scale factor fbpar: real; # -1 for front of cube, 1 for back vf := 1.0; # current velocity factor cmin, cmax: Vector; # cube extents # special transformation matrix without roll, pitch, yaw # this is needed so that spheres can be drawn as circles mod0 := array[4] of array of real; stereo := 0; # stereopsis SPHERE, ELLIPSOID, CUBE, POLYHEDRON: con iota; surr := CUBE; # surround poly := 0; # show polyhedra flat: int; # objects in one plane projx: int; # strange projection # ellipse parameters ef: Vector = (1.0, 0.8, 1.0); e2: Vector; # objects nobjs: int; objs: array of ref Object; me: ref Object; # circle drawing NC: con 72; cost, sint: array of real; # polyhedra polys: ref Polyhedra->Polyhedron; npolys: int; polyh: ref Polyhedra->Polyhedron; rgba(r: int, g: int, b: int, α: int): ref Image { c := draw->setalpha((r<<24)|(g<<16)|(b<<8), α); return display.newimage(((0, 0), (1, 1)), display.image.chans, 1, c); } random(a: int, b: int): int { return a+rand->rand(b-a+1); } urand(): real { M: con 1000; return real random(0, M)/real M; } randomr(a: real, b: real): real { return a+urand()*(b-a); } randomc(): ref Image { r, g, b: int; do{ r = random(0, 255); g = random(0, 255); b = random(0, 255); }while(r+g+b < 384); return rgba(r, g, b, 255); } randomv(a: real, b: real): Vector { x := randomr(a, b); y := randomr(a, b); if(flat) return (x, y, (a+b)/2.0); return (x, y, randomr(a, b)); } randomd(): Vector { M: con 1000.0; v := randomv(-M, M); while(vlen(v) == 0.0) v = randomv(-M, M); return vnorm(v); } randomp(min: real, max: real): Vector { case(surr){ SPHERE => return vmul(randomd(), max*maths->sqrt(urand())); ELLIPSOID => return vmul(randomd(), max*vmin(ef)*maths->sqrt(urand())); CUBE => return randomv(min, max); * => v := randomv(min, max); while(outside3(v, cmin, cmax)) v = randomv(min, max); return v; } } det(a: real, b: real, c: real, d: real): real { return a*d-b*c; } simeq(a: real, b: real, c: real, d: real, e: real, f: real): (real, real) { de := det(a, b, c, d); return (det(e, b, f, d)/de, det(a, e, c, f)/de); } cksimeq(a: real, b: real, c: real, d: real, e: real, f: real): (int, real, real) { ade := de := det(a, b, c, d); if(ade < 0.0) ade = -ade; if(ade < ε) return (0, 0.0, 0.0); return (1, det(e, b, f, d)/de, det(a, e, c, f)/de); } ostring(o: ref Object): string { return lstring(o.l) + "+" + vstring(o.p) + "+" + string o.v; } pstring(p: ref Plane): string { return vstring(p.n) + "=" + string p.d; } lstring(l: ref Line): string { return vstring(l.a) + "->" + vstring(l.d); } vstring(v: Vector): string { return "(" + string v.x + " " + string v.y + " " + string v.z + ")"; } vpt(x: real, y: real, z: real): Vector { p: Vector; p.x = x; p.y = y; p.z = z; return p; } vdot(v1: Vector, v2: Vector): real { return v1.x*v2.x+v1.y*v2.y+v1.z*v2.z; } vcross(v1: Vector, v2: Vector): Vector { v: Vector; 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; return v; } vadd(v1: Vector, v2: Vector): Vector { v: Vector; v.x = v1.x+v2.x; v.y = v1.y+v2.y; v.z = v1.z+v2.z; return v; } vsub(v1: Vector, v2: Vector): Vector { v: Vector; v.x = v1.x-v2.x; v.y = v1.y-v2.y; v.z = v1.z-v2.z; return v; } vmul(v1: Vector, s: real): Vector { v: Vector; v.x = s*v1.x; v.y = s*v1.y; v.z = s*v1.z; return v; } vdiv(v1: Vector, s: real): Vector { v: Vector; v.x = v1.x/s; v.y = v1.y/s; v.z = v1.z/s; return v; } vlen(v: Vector): real { return maths->sqrt(vdot(v, v)); } vlen2(v: Vector): (real, real) { d2 := vdot(v, v); d := maths->sqrt(d2); return (d, d2); } vnorm(v: Vector): Vector { d := maths->sqrt(vdot(v, v)); if(d == 0.0) return v; return vmul(v, real 1/d); } vnorm2(v: Vector): (real, Vector) { d := maths->sqrt(vdot(v, v)); if(d == 0.0) return (0.0, VZ); return (d, vmul(v, real 1/d)); } clip(x: real, d: real): real { if(x < -d) x = -d; if(x > d) x = d; return x; } vclip(v: Vector, d: real): Vector { c: Vector; c.x = clip(v.x, d); c.y = clip(v.y, d); c.z = clip(v.z, d); return c; } vout(v1: Vector, v2: Vector): int { v := vsub(v2, v1); return v.x < 0.0 || v.y < 0.0 || v.z < 0.0; } vmin(v: Vector): real { m := v.x; if(v.y < m) m = v.y; if(v.z < m) m = v.z; return m; } vvmul(v1: Vector, v2: Vector): Vector { v: Vector; v.x = v1.x*v2.x; v.y = v1.y*v2.y; v.z = v1.z*v2.z; return v; } vvdiv(v1: Vector, v2: Vector): Vector { v: Vector; v.x = v1.x/v2.x; v.y = v1.y/v2.y; v.z = v1.z/v2.z; return v; } vmuldiv(v1: Vector, v2: Vector, v3: Vector): real { return vdot(vvdiv(v1, v3), v2); } newp(id: int, a: real, b: real, c: real, d: real, m: real, v: array of Vector) { p := ref Plane; p.id = id; p.n = (a, b, c); p.d = d; m += ε; p.min = (-m, -m, -m); p.max = (+m, +m, +m); p.v = v; if(v != nil){ p.min = (∞, ∞, ∞); p.max = (-∞, -∞, -∞); for(i := 0; i < len v; i++){ vtx := v[i]; if(vtx.x < p.min.x) p.min.x = vtx.x; if(vtx.y < p.min.y) p.min.y = vtx.y; if(vtx.z < p.min.z) p.min.z = vtx.z; if(vtx.x > p.max.x) p.max.x = vtx.x; if(vtx.y > p.max.y) p.max.y = vtx.y; if(vtx.z > p.max.z) p.max.z = vtx.z; } (x, y, z) := p.far = vmul(p.max, 2.0); if(a != 0.0) p.far.x = (d-b*y-c*z)/a; else if(b != 0.0) p.far.y = (d-c*z-a*x)/b; else if(c != 0.0) p.far.z = (d-a*x-b*y)/c; else fatal("null plane"); } planes = p :: planes; } pinit() { case(surr){ SPHERE or ELLIPSOID => newp(0, 0.0, 0.0, 1.0, ∞, ∞, nil); CUBE => newp(0, 1.0, 0.0, 0.0, -icubd, icubd, nil); newp(1, 1.0, 0.0, 0.0, +icubd, icubd, nil); newp(2, 0.0, 1.0, 0.0, -icubd, icubd, nil); newp(3, 0.0, 1.0, 0.0, +icubd, icubd, nil); newp(4, 0.0, 0.0, 1.0, -icubd, icubd, nil); newp(5, 0.0, 0.0, 1.0, +icubd, icubd, nil);