|
![](/i/fill.gif) |
/*
Hi Steve!
--:--
Mirroring is very easy: make an union of the objects comprising the
first half of the stack, put this into the scene, then put its
mirror image into the scene:
#declare HalfStack = union {
// create the objects of the first half of the stack as shown
// in my previous post (stacked vertically, i.e. in y-direction).
}
// put the HalfStack into the scene
object { HalfStack }
// grab the HalfStack (its y-range is 0 .. Position.y), mirror it in
// the xz-plane by inverting y (now the y-range is -Position.y .. 0),
// then translate by (2*Position.y)*y (this is the same as
// 2*Position*y) which gives an y-range of Position.y .. 2*Position.y,
// i.e. the mirrored copy now is on top of the first HalfStack.
object { HalfStack scale <1, -1, 1> translate 2*Position*y }
--:--
A different method would be to build the stack from the middle to both
ends by appending in the loop each object at both ends, i.e. after
object { Object translate -MinY*y+Position }
insert
object { Object translate -MinY*y+Position scale <1, -1, 1> }
Because now the double stack is partially below the checkered plane,
the plane{...}-statement must be replaced by
plane { y, -Position.y pigment { checker scale 10 } }
and we need a new camera (greater distance; adjusted to the larger object):
camera {
location <1, 3, -2>*(Position.y-Start.y)
look_at 0
translate -Position+0.55*2*Position
angle 30
}
(The lower end now is (Start-Position), this replaces Start; then I've
simplified this new expression a bit.)
Of course the code would be more easily readable when Start were renamed
to Midpoint ...
--:--
Individual control of the stacked objects is possible by filling an array
with their individual scales/textures/lengths/... like
#declare ScaleArray = array[Number] { 1, 2, 3, 3, 3, 2, 1 }
#declare PigmentArray = array[Number] { P1, P1, P2, P2, P2, P1, P2 }
then using it in the loop:
#declare Object = cylinder { 0, y, 1
scale ScaleArray[Count]
pigment { PigmentArray[Count] }
finish { FinishArray[Count] }
}
(assuming P1, P2, FinishArray are declared before this, and Number=6).
--:--
The multiplication by y in the translate modifier of the camera statement
is nonsense (in my previous post; corrected here): this multiplication
clears the x- and z-coordinate. There is no need to do that, but in this
special case it doesn't hurt, these coordinates are zero anyway.
--:--
Here comes a new example, illustrating a different and very flexible
approach -- again this whole mail is a POV-Ray-scene, I suggest to set
the following options and RUN!
// +SP8 +EP8 +W320 +H240 -F +D +A0.1
*/
// stacked cylinders, flexible control of scale
#declare Number = 40;
#declare Start = <0, 0, 0>; // arbitrary starting point
#declare Position = Start; // initialize position for object
#declare Scale = 18; // initialize scale factor for object
// loop for Counter = 0, 1, ..., Number-1
#declare Count = 0;
#while (Count<Number)
// auxiliary variable, ranging from 0 to 1
#declare C_N = Count/(Number-1);
// determine the scaling factor; in this example:
// begin with 1 (see above)
// in the first quarter (C_N<0.25): decrease by 1
// next quarter (C_N<0.50): stay constant
// third quarter (C_N<0.75): decrease by 0.5
// rest: scale by 0.4
// Using Count instead of C_N also is possible, but when Number
// changes, all #case values have to be adjusted accordingly.
// (Adjusting the initial value for Scale and the Scale-changes
// are also required; this could be automated, but is omitted here.)
// My usage of the #switch statement is a bit unusual -- most
// people would use #range-clauses. But I like it this way!
#switch (true)
#case (C_N<.25) #declare Scale = Scale-1; #break
#case (C_N<.50) /* don't change Scale */ #break
#case (C_N<.75) #declare Scale = Scale-0.5; #break
#else #declare Scale = 1;
#end//switch
// it's not necessary to check for the lower bound (i.e. to use
// #case (C_N>=.50 & C_N<0.75) instead of #case (C_N<0.75)
// because the lower values are caught in the #case(s) above.
//
// +----------------------------------------------------------------+
// ! Attention: C_N<0.5 means "first half of the NUMBER of objects !
// ! in the stack", NOT "first half of FINAL HEIGHT of stack"! !
// +----------------------------------------------------------------+
// more #switch directives could determine/change other parameters:
// Object, pigment, finish, rotation, ...
// make next object to be stacked; may depend on Count
#declare Object = cylinder { 0, y, 1
// scale the object by Scale;
// also try scale <10, Scale, 10> and scale <Scale,10,Scale>
scale Scale // calculated above
// alternating colors; also try mod(Count,5)/4 etc.
pigment { color rgb <1, mod(Count,2), 0.3> } // easy, isn't it?
finish { ambient .4 diffuse .6 }
}
// find smallest and largest y of this object and its y-size
#declare MinY = min_extent(Object).y;
#declare MaxY = max_extent(Object).y;
#declare SizeY= MaxY-MinY;
// put object into scene with it's bottom at Position
// (first translate the bottom to origin, from there to Position)
object { Object translate -MinY*y + Position }
//object { Object scale <1, -1, 1> translate +MinY*y - Position }
// update the Position for the next object
#declare Position = Position + SizeY*y;
// loop
#declare Count = Count+1;
#end//while Count
// we all love this, even without reflecting sphere ...
plane { y, 0 pigment { checker scale 10 } }
// light
light_source { <-2, 3, -1>*1000, rgb 1 }
// camera, translated to look at 55% of the height of the stack of objects
camera {
location <1, 3, -2>*(Position.y-Start.y)/2
look_at 0
translate Start+0.55*(Position-Start)
angle 30
}
// END
Post a reply to this message
|
![](/i/fill.gif) |