/* ----------------------------------------------------------------------------- This source file is part of OpenSpace3D For the latest info, see http://www.openspace3d.com Copyright (c) 2012 I-maginer This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA, or go to http://www.gnu.org/copyleft/lesser.txt ----------------------------------------------------------------------------- */ struct PWarper = [ WARP_srcX : [F F F F], WARP_srcY : [F F F F], WARP_dstX : [F F F F], WARP_dstY : [F F F F], WARP_srcMat : [F F F F F F F F F F F F F F F F], WARP_dstMat : [F F F F F F F F F F F F F F F F], WARP_warpMat : [F F F F F F F F F F F F F F F F], WARP_bDirty : I, WARP_iMode : I ]mkWarper;; fun SetWarperSource(warperstr, x0, y0, x1, y1, x2, y2, x3, y3)= set warperstr.WARP_srcX = [x0 x1 x2 x3]; set warperstr.WARP_srcY = [y0 y1 y2 y3]; set warperstr.WARP_bDirty = 1; 0;; fun SetWarperDestination(warperstr, x0, y0, x1, y1, x2, y2, x3, y3)= set warperstr.WARP_dstX = [x0 x1 x2 x3]; set warperstr.WARP_dstY = [y0 y1 y2 y3]; set warperstr.WARP_bDirty = 1; 0;; fun MulWarperMats(warperstr)= let warperstr.WARP_srcMat -> [m0 m1 m2 m3 m4 m5 m6 m7 m8 m9 m10 m11 m12 m13 m14 m15] in let warperstr.WARP_dstMat -> [d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15] in let m0 *. d0 +. m1 *. d4 +. m2 *. d8 +. m3 *. d12 -> q0 in let m0 *. d1 +. m1 *. d5 +. m2 *. d9 +. m3 *. d13 -> q1 in let m0 *. d2 +. m1 *. d6 +. m2 *. d10 +. m3 *. d14 -> q2 in let m0 *. d3 +. m1 *. d7 +. m2 *. d11 +. m3 *. d15 -> q3 in let m4 *. d0 +. m5 *. d4 +. m6 *. d8 +. m7 *. d12 -> q4 in let m4 *. d1 +. m5 *. d5 +. m6 *. d9 +. m7 *. d13 -> q5 in let m4 *. d2 +. m5 *. d6 +. m6 *. d10 +. m7 *. d14 -> q6 in let m4 *. d3 +. m5 *. d7 +. m6 *. d11 +. m7 *. d15 -> q7 in let m8 *. d0 +. m9 *. d4 +. m10 *. d8 +. m11 *. d12 -> q8 in let m8 *. d1 +. m9 *. d5 +. m10 *. d9 +. m11 *. d13 -> q9 in let m8 *. d2 +. m9 *. d6 +. m10 *. d10 +. m11 *. d14 -> q10 in let m8 *. d3 +. m9 *. d7 +. m10 *. d11 +. m11 *. d15 -> q11 in let m12 *. d0 +. m13 *. d4 +. m14 *. d8 +. m15 *. d12 -> q12 in let m12 *. d1 +. m13 *. d5 +. m14 *. d9 +. m15 *. d13 -> q13 in let m12 *. d2 +. m13 *. d6 +. m14 *. d10 +. m15 *. d14 -> q14 in let m12 *. d3 +. m13 *. d7 +. m14 *. d11 +. m15 *. d15 -> q15 in set warperstr.WARP_warpMat = [q0 q1 q2 q3 q4 q5 q6 q7 q8 q9 q10 q11 q12 q13 q14 q15]; 0;; fun ComputeWarperSquareToQuad(srcX, srcY)= let srcX -> [x0 x1 x2 x3] in let srcY -> [y0 y1 y2 y3] in let x1 -. x2 -> dx1 in let y1 -. y2 -> dy1 in let x3 -. x2 -> dx2 in let y3 -. y2 -> dy2 in let x0 -. x1 +. x2 -. x3 -> sx in let y0 -. y1 +. y2 -. y3 -> sy in let if (dx1 *. dy2 -. dx2 *. dy1) == 0.0 then 1.0 else (dx1 *. dy2 -. dx2 *. dy1) -> d1 in let (sx *. dy2 -. dx2 *. sy) /. d1 -> g in let (dx1 *. sy -. sx *. dy1) /. d1 -> h in let x1 -. x0 +. g *. x1 -> a in let x3 -. x0 +. h *. x3 -> b in let x0 -> c in let y1 -. y0 +. g *. y1 -> d in let y3 -. y0 +. h *. y3 -> e in let y0 -> f in [a d 0.0 g b e 0.0 h 0.0 0.0 1.0 0.0 c f 0.0 1.0];; fun ComputeWarperQuadToSquare(srcX, srcY)= let ComputeWarperSquareToQuad srcX srcY -> [a d _ g b e _ h _ _ _ _ c f _ _] in // invert through adjoint let e -. f *. h -> mA in let c *. h -. b -> mB in let b *. f -. c *. e -> mC in let f *. g -. d -> mD in let a -. c *. g -> mE in let c *. d -. a *. f -> mF in let d *. h -. e *. g -> mG in let b *. g -. a *. h -> mH in let a *. e -. b *. d -> mI in let if (a *. mA +. b *. mD +. c *. mG) == 0.0 then 1.0 else (a *. mA +. b *. mD +. c *. mG) -> d1 in let 1.0 /. d1 -> idet in [(mA *. idet) (mD *. idet) 0.0 (mG *. idet) (mB *. idet) (mE *. idet) 0.0 (mH *. idet) 0.0 0.0 1.0 0.0 (mC *. idet) (mF *. idet) 0.0 (mI *. idet)];; fun ComputeWarper(warperstr)= set warperstr.WARP_srcMat = ComputeWarperQuadToSquare warperstr.WARP_srcX warperstr.WARP_srcY; set warperstr.WARP_dstMat = ComputeWarperSquareToQuad warperstr.WARP_dstX warperstr.WARP_dstY; MulWarperMats(warperstr); set warperstr.WARP_bDirty = 0; 0;; fun SetWarperIdentity(warperstr)= SetWarperDestination warperstr 0.0 0.0 1.0 0.0 0.0 1.0 1.0 1.0; SetWarperSource warperstr 0.0 0.0 1.0 0.0 0.0 1.0 1.0 1.0; ComputeWarper warperstr; 0;; fun Warp(warperstr, p)= if (!warperstr.WARP_bDirty) then nil else ComputeWarper warperstr; let p -> [srcX srcY srcZ] in let warperstr.WARP_warpMat -> [m0 m1 m2 m3 m4 m5 m6 m7 m8 m9 m10 m11 m12 m13 m14 m15] in let (srcX *. m0 +. srcY *. m4 +. srcZ *. m8 +. 1.0 *. m12) -> d0 in let (srcX *. m1 +. srcY *. m5 +. srcZ *. m9 +. 1.0 *. m13) -> d1 in let (srcX *. m2 +. srcY *. m6 +. srcZ *. m10 +. 1.0 *. m14) -> d2 in let (srcX *. m3 +. srcY *. m7 +. srcZ *. m11 +. 1.0 *. m15) -> d3 in let if (d3 == 0.0) then 1.0 else d3 -> d3 in [(d0 /. d3) (d1 /. d3) (d2 /. d3)];; fun deleteOb(inst)= 0;; fun cbGetValue(inst, from, action, param, reply, warperstr)= let if warperstr.WARP_iMode == 0 then V3DgetViewSize (V3DgetSessionView c3dXsession) else _GETscreenSize -> [vw vh] in let hd strextr param -> lp in let atof (hd lp) -> px in let atof (hd tl lp) -> py in let atof (hd tl tl lp) -> pz in let if px == nil then 0.0 else (px /. (itof (max 1 vw))) -> px in let if py == nil then 0.0 else (py /. (itof (max 1 vh))) -> py in let 0.0 -> pz in let Warp warperstr [px py pz] -> [dx dy dz] in let [(dx *. (itof vw)) (dy *. (itof vh))] -> [dx dy] in ( SendPluginEvent inst "Out" strcatn (ftoa dx)::" "::(ftoa dy)::nil nil; ); 0;; fun cbSetCorner(inst, from, action, param, reply, pp)= let pp -> [idx warperstr] in let if warperstr.WARP_iMode == 0 then V3DgetViewSize (V3DgetSessionView c3dXsession) else _GETscreenSize -> [vw vh] in let hd strextr param -> lp in let atof (hd lp) -> px in let atof (hd tl lp) -> py in let atof (hd tl tl lp) -> pz in let if px == nil then 0.0 else (px /. (itof (max 1 vw))) -> px in let if py == nil then 0.0 else (py /. (itof (max 1 vh))) -> py in let if pz == nil then 0.0 else pz -> pz in let warperstr.WARP_srcX -> [dx0 dx1 dx2 dx3] in let warperstr.WARP_srcY -> [dy0 dy1 dy2 dy3] in ( if (idx == 0) then ( set warperstr.WARP_srcX = [px dx1 dx2 dx3]; set warperstr.WARP_srcY = [py dy1 dy2 dy3]; ) else if (idx == 1) then ( set warperstr.WARP_srcX = [dx0 px dx2 dx3]; set warperstr.WARP_srcY = [dy0 py dy2 dy3]; ) else if (idx == 2) then ( set warperstr.WARP_srcX = [dx0 dx1 px dx3]; set warperstr.WARP_srcY = [dy0 dy1 py dy3]; ) else if (idx == 3) then ( set warperstr.WARP_srcX = [dx0 dx1 dx2 px]; set warperstr.WARP_srcY = [dy0 dy1 dy2 py]; ) else nil; set warperstr.WARP_bDirty = 1; ); 0;; fun newOb(inst)= let atoi (getPluginInstanceParam inst "mode") -> mode in let if mode == nil then 0 else mode -> mode in let mkWarper[nil nil nil nil nil nil nil 1 mode] -> warperstr in ( SetWarperIdentity warperstr; PluginRegisterAction inst "Set top left corner" mkfun6 @cbSetCorner [0 warperstr]; PluginRegisterAction inst "Set top right corner" mkfun6 @cbSetCorner [1 warperstr]; PluginRegisterAction inst "Set bottom left corner" mkfun6 @cbSetCorner [2 warperstr]; PluginRegisterAction inst "Set bottom right corner" mkfun6 @cbSetCorner [3 warperstr]; PluginRegisterAction inst "In" mkfun6 @cbGetValue warperstr; ); setPluginInstanceCbDel inst @deleteOb; 0;; fun IniPlug(file)= PlugRegister @newOb nil; setPluginEditor @dynamicedit; 0;;