POV-Ray : Newsgroups : povray.general : Isosurface, box with transformations Server Time
4 Nov 2024 17:32:00 EST (-0500)
  Isosurface, box with transformations (Message 1 to 5 of 5)  
From: StephenS
Subject: Isosurface, box with transformations
Date: 22 Oct 2003 08:00:01
Message: <3f967141@news.povray.org>
I would like to blob together several box shapes in an isosurface. The size
and transformations of each box will be output from Moray to help me
visualize where everything is.

The following approach seems to work so far.
Only one shape is used so far. Additional shapes will use an array, like in
sx (start x), and a loop. Shear not add yet. Bounding box not calculated.

My question:
Is there a better way to add the transformations to the individual shapes in
the isosurface.

//start code
camera {
  location  <-0.5, 2.0, -3.0>
  look_at   <0.5, 0.5,  0.0>
  right     x*image_width/image_height
}

light_source {
  0*x
  color rgb <1,1,1>
  translate <-20, 40, -20>
}

#declare sx=array[4]{0,0,0,0}; // start
#declare sy=0;
#declare sz=0;
#declare fx=1; // finish
#declare fy=1;
#declare fz=1;

#declare length_x=(fx-sx[0]);
#declare length_y=(fx-sy);
#declare length_z=(fx-sz);

#declare scx=1; // scale
#declare scy=1;
#declare scz=1;

#declare shxy=0; // shear
#declare shxz=0;
#declare shyx=0;
#declare shyz=0;
#declare shzx=0;
#declare shzy=0;

#declare rx=20; // rotate
#declare ry=0;
#declare rz=0;

#declare tx=0; // translate
#declare ty=0;
#declare tz=0;

#declare f_box = function (x,y,z) {
           max(
             (abs(x-length_x/2+sx[0])-abs(length_x/2)),
             (abs(y-length_y/2+sy)-abs(length_y/2)),
             (abs(z-length_z/2+sz)-abs(length_z/2))
           )
         };

#declare f_scale          = function (x,y,z) {f_box(x/scx,y/scy,z/scz)};
#declare f_rotate_x       = function (x,y,z) {f_scale   (x
,z*sin(radians(rx)) + y*cos(radians(rx)) ,z*cos(radians(rx)) -
y*sin(radians(rx)))};
#declare f_rotate_y       = function (x,y,z)
{f_rotate_x(x*cos(radians(ry)) - z*sin(radians(ry)) ,y ,x*sin(radians(ry)) +
z*cos(radians(ry)))};
#declare f_rotate_z       = function (x,y,z) {f_rotate_y(x*cos(radians(rz))
+ y*sin(radians(rz)) ,-x*sin(radians(rz)) + y*cos(radians(rz)),z)};
#declare f_translate      = function (x,y,z) {f_rotate_z(x-tx,y-ty,z-tz)};
#declare f_isosurface_box = function (x,y,z) {f_translate(x,y,z)};

isosurface {
  function { f_isosurface_box(x,y,z) }
  contained_by { box { -5, 5 } }
  texture { pigment {color red 1} finish{ambient 0.2} }
}
// end code

Stephen


Post a reply to this message

From: Christopher James Huff
Subject: Re: Isosurface, box with transformations
Date: 23 Oct 2003 20:14:53
Message: <cjameshuff-A21381.20124523102003@netplex.aussie.org>
In article <3f967141@news.povray.org>,
 "StephenS" <ssh### [at] echelonca> wrote:

> Is there a better way to add the transformations to the individual shapes in
> the isosurface.

Well, there's a better way of representing the transformations in the 
first place. Declare a transform function with the inverse of the 
transforms:

#declare TransFn =
function {
    transform {
        ...your transforms...
        invert
    }
}

isosurface {
    function {
        f_isosurface_box(
            TransFn(x, y, z).x,
            TransFn(x, y, z).y,
            TransFn(x, y, z).z
        )
    }
    ...

Of course, this is less efficient than it could be, since you can't 
declare variables or handle vectors, but it's certainly easier to handle 
and more efficient at handling lots of transformations. You could write 
macros to create separate functions for the x, y, and z coordinates 
which might be more efficient...

#macro XTransFn(Trans)
    #local TransFn = function {transform {Trans}}
    #local C0 = TransFn(0, 0, 0);
    #local CX = TransFn(1, 0, 0) - C0;
    #local CY = TransFn(0, 1, 0) - C0;
    #local CZ = TransFn(0, 0, 1) - C0;
    function {x*CX.x + y*CY.x + z*CZ.x + C0.x}
#end

And similarly for y and z...a smarter macro could remove zero terms to 
speed calculation. This macro would be used like this:

#declare f_RotateX = XTransFn(transform {rotate ...})

-- 
Christopher James Huff <cja### [at] earthlinknet>
http://home.earthlink.net/~cjameshuff/
POV-Ray TAG: chr### [at] tagpovrayorg
http://tag.povray.org/


Post a reply to this message

From: StephenS
Subject: Re: Isosurface, box with transformations
Date: 24 Oct 2003 18:40:00
Message: <3f99aa40$1@news.povray.org>
...
> Well, there's a better way of representing the transformations in the
> first place. Declare a transform function with the inverse of the
> transforms:
>
> #declare TransFn =
> function {
>     transform {
>         ...your transforms...
>         invert
>     }
> }
>
> isosurface {
>     function {
>         f_isosurface_box(
>             TransFn(x, y, z).x,
>             TransFn(x, y, z).y,
>             TransFn(x, y, z).z
>         )
>     }
>     ...
>
> Of course, this is less efficient than it could be, since you can't
> declare variables or handle vectors, but it's certainly easier to handle
> and more efficient at handling lots of transformations. You could write
> macros to create separate functions for the x, y, and z coordinates
> which might be more efficient...
>
> #macro XTransFn(Trans)
>     #local TransFn = function {transform {Trans}}
>     #local C0 = TransFn(0, 0, 0);
>     #local CX = TransFn(1, 0, 0) - C0;
>     #local CY = TransFn(0, 1, 0) - C0;
>     #local CZ = TransFn(0, 0, 1) - C0;
>     function {x*CX.x + y*CY.x + z*CZ.x + C0.x}
> #end
>
> And similarly for y and z...a smarter macro could remove zero terms to
> speed calculation. This macro would be used like this:
>
> #declare f_RotateX = XTransFn(transform {rotate ...})
>
...
Thanks for your reply. I don't completly understand all that you sugested,
but it gives me a few things to look into. Will have to play with the code
for awhile :-)

Stephen


Post a reply to this message

From: Christopher James Huff
Subject: Re: Isosurface, box with transformations
Date: 24 Oct 2003 22:37:12
Message: <cjameshuff-686248.22350524102003@netplex.aussie.org>
In article <3f99aa40$1@news.povray.org>,
 "StephenS" <ssh### [at] echelonca> wrote:

> Thanks for your reply. I don't completly understand all that you sugested,
> but it gives me a few things to look into. Will have to play with the code
> for awhile :-)

Here's a short explanation of the macro:

#macro TransFn(Comp, Trans)
    #local TmpTransFn = function {transform {Trans}}
    #local C0 = TmpTransFn(0, 0, 0);
    #local CX = TmpTransFn(1, 0, 0) - C0;
    #local CY = TmpTransFn(0, 1, 0) - C0;
    #local CZ = TmpTransFn(0, 0, 1) - C0;
    #switch(Comp)
        #case(0)
            #local X = CX.x;
            #local Y = CY.x;
            #local Z = CZ.x;
            #local T = C0.x;
        #break
        #case(1)
            #local X = CX.y;
            #local Y = CY.y;
            #local Z = CZ.y;
            #local T = C0.y;
        #break
        #case(2)
            #local X = CX.z;
            #local Y = CY.z;
            #local Z = CZ.z;
            #local T = C0.z;
        #break
    #end
    function {x*X + y*Y + z*Z + T}
#end

POV-Ray transformations are stored in 3x4 matrices, basically 3x3 
matrices with translation columns tacked on. Points are transformed by 
the matrix like this:

xOut = m11*x + m12*y + m13*z + m14
yOut = m21*x + m22*y + m23*z + m24
yOut = m31*x + m32*y + m33*z + m34

Transforming < 0, 0, 0> gives the translation column alone. Transforming 
< 1, 0, 0>, < 0, 1, 0>, and < 0, 0, 1> and subtracting the translation 
give the first three columns. Then a function is created with the matrix 
elements of the desired row.

Unfortunately, I've tested it, and this is actually slower than 
evaluating the transform function directly. The test took 28 seconds 
with the transform function, and 32 with the functions produced with 
this macro (7 seconds with no transformations). Removing multiplications 
by 1 and zero terms, I ended up with transformation functions that 
produced an isosurface that rendered in 23 seconds, but this will only 
happen in certain limited cases, so it really isn't worth the effort to 
implement this optimization. Here's a considerably simpler macro which 
is also easier to use:

#macro TransformFn(Func, Trans)
    #ifdef(f_Trans)
        #undef f_Trans
    #end
    #local f_Trans = function {transform {Trans}}
    #local Res = function {Func(f_Trans(x, y, z).x, f_Trans(x, y, z).y, 
f_Trans(x, y, z).z)}
    Res(x, y, z)
#end

#local Trans = transform {scale < 1, 3, 1> translate -y*1 inverse}
isosurface {
    function {1 - TransformFn(f_r, Trans)}

-- 
Christopher James Huff <cja### [at] earthlinknet>
http://home.earthlink.net/~cjameshuff/
POV-Ray TAG: chr### [at] tagpovrayorg
http://tag.povray.org/


Post a reply to this message

From: StephenS
Subject: Re: Isosurface, box with transformations
Date: 3 Nov 2003 00:28:35
Message: <3fa5e783@news.povray.org>
Christopher James Huff wrote
...
> Here's a considerably simpler macro which
> is also easier to use:
...
This is much closer to what I was hoping for when I started :-)

I now have the following code.
-box declared with start/finish points and/or scale/translate.
-additional shapes can be added. Shapes that can be easily represented with
a wireframe interest me the most.
-scale and shear have been kept separate for ease of reading.
-bounded_by not calculated from objects used, user inputs values.

// start code
camera {
  location  <-0.5, 2.0, -3.0>
  look_at   <0.5, 0.5,  0.0>
  right     x*image_width/image_height
}

light_source {
  0*x
  color rgb <1.5,1.5,1.5>
  translate <-15, 30, -20>
}

light_source {
  0*x
  color rgb <.5,.5,.5>
  translate <0, -30, -20>
}

light_source {
  0*x
  color rgb <.5,.5,.5>
  translate <20, -5, -20>
}

// possible output from external program
#declare sx=array[4]{0,0,.2,0}; // start
#declare sy=array[4]{0,0,0,0};
#declare sz=array[4]{0,0,0,0};
#declare fx=array[4]{1,.1,1,1}; // finish
#declare fy=array[4]{1,1,1,1};
#declare fz=array[4]{1,1,1,1};

#declare scx=array[4]{1,1,1,1}; // scale
#declare scy=array[4]{1,1,1,1};
#declare scz=array[4]{1,1,1,1};

#declare shxy=array[4]{0,0,0,-.2}; // shear
#declare shxz=array[4]{0,0,0,0};
#declare shyx=array[4]{0,0,0,0};
#declare shyz=array[4]{0,0,0,0};
#declare shzx=array[4]{0,0,0,0};
#declare shzy=array[4]{0,0,0,0};

#declare rx=array[4]{0,0,0,0}; // rotate
#declare ry=array[4]{0,0,0,0};
#declare rz=array[4]{0,-10,0,0};

#declare tx=array[4]{0,.5,-.2,-.6}; // translate
#declare ty=array[4]{0,.5,0,.6};
#declare tz=array[4]{0,-.5,.5,.5};

#declare ob=array[4]{1,1,2,1}

#local Blob_threshold=.000001;
#local maxnum=4; // change from 1 - 4

// Pov code to make blobbed isosurface object
#macro m_object(num)
#switch(ob[num])
  #case(1) // box
  function {
    max(
      (abs(x-(fx[num]-sx[num])/2-sx[num])-abs(fx[num]-sx[num])/2),
      (abs(y-(fy[num]-sy[num])/2-sy[num])-abs(fy[num]-sy[num])/2),
      (abs(z-(fz[num]-sz[num])/2-sz[num])-abs(fz[num]-sz[num])/2)
    )
  }
  #break
  #case(2) // sphere
  function {
    pow(x,2) + pow(y,2) + pow(z,2) - pow(sx[num],2)
  }
  #break
#end // switch
#end // macro

#macro TransformFn(Func, Trans)
  #ifdef(f_Trans)
     #undef f_Trans
  #end
  #local f_Trans = function {transform {Trans}}
  #local Res = function {Func(f_Trans(x, y, z).x,
                              f_Trans(x, y, z).y,
                              f_Trans(x, y, z).z)}
  Res(x, y, z)
#end

isosurface {
  #local num=0;
  function {
    (1+Blob_threshold)
    #while (num<maxnum)
      #local Trans =
      transform {
        scale     < scx [num], scy [num], scz [num]>
        matrix    < 1        , shyx[num], shzx[num], // shear
                    shxy[num], 1        , shzy[num],
                    shxz[num], shyz[num], 1        ,
                    0        , 0        , 0        >
        rotate    < rx  [num], ry  [num], rz  [num]>
        translate < tx  [num], ty  [num], tz  [num]>
        inverse};
      -pow(Blob_threshold,TransformFn(m_object(num), Trans))
      #declare num=num+1;
    #end // while
  }
  contained_by { box { -1.6, 1.6 } }
  max_gradient (14.1)
  texture { pigment {color red 1} finish{ambient 0.2} }
}
// end code

My question:
Is there a better way to organize my isosurface and macros?

Stephen


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.