luser.droog wrote:
> tlvp wrote:
>
>> On Thu, 13 Sep 2012 19:07:37 -0700 (PDT), luser- -droog wrote:
>>
>>> ... I've got to go
>>> newsserver shopping again ...
>>
>>
http://aioe.org/ ...
news.eternal-september.org ...
freenews.netfront.net
>>
>> There are others, too. HTH. Cheers, -- tlvp
>
> Awesome! thnx. And eternal-september has its own calendrical system!
>
> So I did some further reorganizing and added normal-visibility and
> simplified the model->object transform. Even without lighting and color,
> I think it looks pretty cool now.
>
> 625(1)04:49 PM:ps 1> cat
3d5.ps
Back to the drawing board, I realized that nothing really changes along
the "z" axis of a cylinder. So there's really no need to iterate over it.
So I tried one big face per theta but then there's no known "inside"
point to seed the clip. So I tried two faces per theta with vertices like
6 on a domino. Then I realized that I could avoid clipping against one
of the cylinders by simply setting the outer z coords on the face by
solving for z using x or y of one of the cylinders, the x or y already
calculated for the face. After further playing, I realized I could take
both and use the max for the upper z and min for the lower z. Thus the
faces of the cylinder being drawn are bounded by the other two.
No need to clip. But I leave it here anyway so you all can see how
heinous doing vector clipping is (assuming a demonstration of this fact
is at all necessary to anyone).
But while most of the shape is simple and beautiful, there are distracting
artifacts at the 4-face joins that look like little swastikas a higher
resolutions. And that just sucks. Maybe I should ask for help with that
on SO... (???)
Anyway, I snagged a simpler light calculation from Casselman than the
one from Rogers, and set the hue to the x/y angle of v1 of the face,
const .5 saturation. And wow! If you can overlook (or remove! ?)
the swastikas, this is quite pretty to look at. Maybe a dark background
would help...
522(1)11:30 PM:ps 0> cat
3d5.ps
%!
%Steinmertz, take 5: NEEDFORSPEED
% O(N) generator makes caching largely irrelevant!
% Bounded faces makes clipping unnecessary
% (which wasn't quite working somehow)
% Improved visibility now shows the Front of the object!
% TODO: eliminate those ugly swastika artifacts
(
mat.ps)run
%/forall { pstack()= forall } bind def
%/if { pstack()= if } bind def
/min { 2 copy gt { exch } if pop } def
/max { 2 copy lt { exch } if pop } def
%The vertical chopping cylinder
/cylyz <<
/inside { % x y z . bool
dup mul exch dup mul add R^2 le
exch pop } bind
/doparams {
/D edge 1 get edge 0 get { sub } vop
[ 1 index mag dup dup ] { div } vop def
/a D 1 get dup mul D 2 get dup mul add def
/b 2 edge 0 get 1 get D 1 get mul mul
2 edge 0 get 2 get D 2 get mul mul add def
/c edge 0 get 1 get dup mul
edge 0 get 2 get dup mul add 1 sub def
/t [ b dup mul 4 a c mul mul sub dup 0 lt { neg } if
sqrt 2 a mul div dup neg
b neg 2 a mul div add exch
b neg 2 a mul div add ] def }
>> def
%The horizontal chopping cylinder
/cylxz <<
/inside { % x y z . bool
exch pop
dup mul exch dup mul add R^2 le } bind
/doparams {
/D edge 1 get edge 0 get { sub } vop
%[ 1 index mag dup dup ] { div } vop
def
/a D 0 get dup mul D 2 get dup mul add def
/b 2 edge 0 get 0 get D 0 get mul mul
2 edge 0 get 2 get D 2 get mul mul add def
/c edge 0 get 0 get dup mul
edge 0 get 2 get dup mul add 1 sub def
/t [ b dup mul 4 a c mul mul sub dup 0 lt { neg } if
sqrt 2 a mul div dup neg
b neg 2 a mul div add exch
b neg 2 a mul div add ] def }
>> def
%cd:chopping-cylinder
/clipface { /i exch def
/v1 face 0 get def
/v2 face 1 get def
/v3 face 2 get def
/v4 face 3 get def
[ [v1 v2] [v4 v3] [v1 v2] [v4 v3] [v1 v2] [v2 v1] [v3 v4] ]
i 2 getinterval { /edge exch def
edge 1 get aload pop inside not {
doparams
t aload pop
2 copy 0 lt exch 0 lt xor { dup 0 ge { exch } if pop }{
2 copy lt { exch } if pop
} ifelse
dup 1 gt { pop 1.01 } if
[ exch dup dup ] D { mul } vop
edge 0 get { add } vop
edge 1 get copy pop
} if
} forall
true
} def
%Check that the vertices of a face
%are inside a specified chopping cylinder
/checkface { % [ v1 v2 v3 v4 ] dict
begin
{ aload pop inside } forall
%pop true false false true
%4 copy eq 3 1 roll eq eq { % all-eq
% pop pop pop
%}{ % uneq in>=1 out>=1
true { %don't clip
pop pop pop pop true
}{
{ %if v4true
pop pop pop
3 clipface
}{ %else
{ %if v3true
pop pop
2 clipface
}{ %else
{ %if v2true
pop
1 clipface
}{ %else
{ %if v1true
0 clipface
}{ %else none true
false
} ifelse
} ifelse
} ifelse
} ifelse % i(v_i inside)
} ifelse
%} ifelse
end } bind def
%Write the vertex array [v1 v2 v3 v4]
%to outfile with embedded drawing command
/writeface {
out ([) writestring
[ v1 v2 v3 v4 ]{ % forall vertices
out ([) writestring
{ % forall coords of vertex
out exch outbuf cvs writestring
out ( ) writestring
} forall
out ( ) writestring
out (]) writestring
} forall
out (] drawface\n) writestring
out flushfile
} def
/fudge 1.03 def
%Generate the faces of the Forward cylinder
%and eliminate faces outside the chopping cylinders
/steinmertz-gen {
/N exch def
/R exch def
/R^2 R dup mul def
/h exch def
/dz 1 N div def
/dt 360 dz mul def
/hdz h dz mul def
0 dt 360 { /t exch def
%0 dt 180 { /u exch def
/v1 [
R t cos mul %u cos mul
R t sin mul %u cos mul
0
%R^2 2 index dup mul sub sqrt neg
%R^2 2 index dup mul sub sqrt neg max
] def
/v2 [ %v1 aload pop neg
R t cos mul
R t sin mul
R^2 2 index dup mul sub sqrt
R^2 2 index dup mul sub sqrt min
] def
/t t dt fudge mul add def
/v3 [
R t cos mul
R t sin mul
R^2 2 index dup mul sub sqrt
R^2 2 index dup mul sub sqrt min
] def
/v4 [ %v3 aload pop neg
R t cos mul
R t sin mul
0
] def
/face [ v1 v2 v3 v4 ] def
face cylyz checkface { doface } if
/v1 [
R t cos mul %u cos mul
R t sin mul %u cos mul
0
%R^2 2 index dup mul sub sqrt neg
%R^2 2 index dup mul sub sqrt neg max
] def
/v2 [ %v1 aload pop neg
R t cos mul
R t sin mul
R^2 2 index dup mul sub sqrt neg
R^2 2 index dup mul sub sqrt neg max
] def
/t t dt fudge mul sub def
/v3 [
R t cos mul
R t sin mul
R^2 2 index dup mul sub sqrt neg
R^2 2 index dup mul sub sqrt neg max
%R^2 2 index dup mul sub sqrt neg max
] def
/v4 [ %v3 aload pop neg
R t cos mul
R t sin mul
0
] def
/face [ v1 v2 v3 v4 ] def
face cylyz checkface { doface } if
%} for
} for
} def
%Action performed by steinmertz-gen
%on each face that survives the chopping
/doface {
usecache? {
writeface
}{
face drawface
} ifelse
} def
%This controls the parameters of the
%wireframe approximation of the cylinder
/genfaces {
% Generate the faces
%h R N
4 2 300 steinmertz-gen
} def
%Default modeling transform
/I3 3 ident def
/MO I3 def % model->object
/model {} def
/OW I3 def % object->world
/fill? true def
/wire? false def
colorface
fill? { gsave fill grestore } if
wire? { gsave wirecolor stroke grestore } if
/flushpage where { pop flushpage } if
newpath
exit } loop
end } dup 0 2 dict put bind def
/E [ 3 3 10 ] def %eye point
/crackE { % set pointers into E
/ex E 0 1 getinterval cvx def
/ey E 1 1 getinterval cvx def
/ez E 2 1 getinterval cvx def
} def crackE
/E^ E dup [ exch mag neg dup dup ] { div } vop def %eye center vec
%Check visibility from the eye
/visible { % [ v1 v2 v3 v4 ] . bool
dup 0 get 1 index 1 get 2 index 3 get % [] v1 v2 v4
2 index { sub } vop % [] v1 v2 v14
3 1 roll exch { sub } vop % [] v14 v12
cross /normal exch def %normal ==
%/normal [ normal mag dup dup ] { div } vop def
dup 0 get E { sub } vop % [] ve1
/ev exch def %ev ==
ev normal dot %dup =
0 lt % [] bool
exch pop
} def
/light [ -5 10 20 ] def
/colorface {
%normal light dot 1 add 3 div setgray
face 0 get aload pop pop exch atan 360 div
.5
normal light dot 1 add 3 div sethsbcolor
} def
/proj { DICT begin /z exch def /y exch def /x exch def
1 ez z sub div
x ez mul z ex mul sub
1 index mul
y ez mul z ey mul sub
3 2 roll mul
end } dup 0 10 dict put bind def
/setuppage {
300 400 translate
1 90 dup dup scale div 2 div setlinewidth
} def
/usecache? false def
usecache? { % Generate Data File to cache the faces
/data (stein.fac) def
{
/in data (r) file def
} stopped {
pop pop pop%clear
/out data (w) file def
/outbuf 128 string def
genfaces
flush out closefile
/out null def
/in data (r) file def
} if
/reopen { in closefile /in data (r) file def } def
/drawshape { in cvx exec reopen } def
}{ % Generate fresh data for each shape
/drawshape { genfaces } def
} ifelse
/up 90 rotx def
/left 90 roty def
/ang 0 def
{
/OW ang roty def
/ang ang 10 add def
setuppage
/model {} def % x y z -> x y z
%/MO I3 def
drawshape
/model { neg exch } def % x y z -> x -z y
%/MO up def
drawshape
/model { neg 3 1 roll exch } def % x y z -> -z y x
%/MO left def
drawshape
pstack flush
showpage
} loop