为了回应comp.lang.postscript中的challenge,我正在尝试将3D圆柱体渲染成投影矩形块。但即使在我评论出线条图之后,我仍然会看到线框,因为这些贴片没有碰到冲洗。
通过在z(-2 ... 2,步骤4 / N)和θ(0 ... 360,步骤360 / N)上的双循环,沿z轴对圆柱体建模。矩形的四个点是:
然后我们将模型 - >世界旋转应用于所有四个点。然后我们采用向量v1-> v4和v1-> v2并进行交叉积以获得补丁的法向量。采用带有眼睛矢量的点积来检查贴片是否在形状的“这一侧”;如果没有,跳过绘图并前进到下一个补丁(从循环底部掉下来)。然后我们对每个点应用透视投影,并使用常规postscript 2D moveto和lineto绘制四边形。最后一次计算法线向量,设置灰度,然后填充。
所以问题是:有没有通常的方法来解决这个问题?这是3D问题还是只是一个数字问题(浮点数四舍五入的东西)?在计算积分时,我是否只为我的dz和dT添加了一点软糖因子?或明确地描边?这最后两个选项都产生了预期的结果,但我不能说我对它们感到满意。虽然每个品牌都用于个别插图,但它确实没有解决问题,你知道吗?
我收集了正在使用的积分。这是N = 12的前几个。
在我看来,正如预测的那样,v2和v3恰好与 band 上下一个片段的v1和v4重合。这些是传递给moveto
和lineto
以生成单个四边形的2D“用户坐标”。由于CTM没有变化,这些点应映射到相同的像素,对吧?所以它似乎与链接问题的问题非常相似。但我正在使用Postscript正是因为我不想写自己的光栅化例程:)。我真的认为映射到Postscript的链接问题的解决方案是反转交替棋盘格的方向,至少对于偶数N.这样,所有相应的边都是绘制在同一个方向(彼此)。
[-2.64550757 2.08465409] [-3.00470281 1.69015563] [-2.7090168 1.69015563] [-2.38403082 2.08465409] [-3.00470281 1.69015563] [-3.28940701 0.936108589] [-2.96660638 0.936108589] [-2.7090168 1.69015563] [-3.28940701 0.936108589] [-3.4 -0.0666666701] [-3.0666666 -0.0666666701] [-2.96660638 0.936108589] [-3.4 -0.0666666701] [-3.28940701 -1.05890918] [-2.96660638 -1.05890918] [-3.0666666 -0.0666666701] [-3.28940701 -1.05890918] [-3.00470281 -1.78584146] [-2.7090168 -1.78584146] [-2.96660638 -1.05890918]
我添加了一个简单的灯光模型并进行了调整以带来更多的中频。 Jpeg输出没有出现问题,可能是由于有损压缩。所以这是PNG快照。
如果我使用眼睛矢量作为光源,效果会更加明显。左边的xpost显示问题,右边的gs显示修改,其中dz和dt乘以软糖因子1.06。
代码:[不要使用此代码。 matmul例程中存在错误。更正了可用的例程here。完成的挑战here。]
%!
%A shaded cylinder! Woohoo!
%(mat.ps) run
%!
%mat.ps
%Matrix and Vector math routines
/.error where { pop /signalerror { .error } def } if
/dot { % u v
2 copy length exch length ne {
/dot cvx /undefinedresult signalerror
} if
% u v
0 % u v sum
0 1 3 index length 1 sub { % u v sum i
3 index 1 index get exch % u v sum u_i i
3 index exch get % u v sum u_i v_i
mul add % u v sum
} for % u v sum
3 1 roll pop pop % sum
} bind def
% [ x1 x2 x3 ] [ y1 y2 y3 ] cross [ x2*y3-y2*x3 x3*y1-x1*y3 x1*y2-x2*y1 ]
/cross { % u v
dup length 3 ne
2 index length 3 ne or {
/cross cvx /undefinedresult signalerror
} if
% u v
exch aload pop 4 3 roll aload pop % x1 x2 x3 y1 y2 y3
[
5 index 2 index mul % ... [ x2*y3
3 index 6 index mul sub % ... [ x2*y3-y2*x3
5 index 5 index mul % ... [ x2*y3-y2*x3 x3*y1
8 index 4 index mul sub % ... [ x2*y3-y2*x3 x3*y1-x1*y3
8 index 5 index mul % ... [ x2*y3-y2*x3 x3*y1-x1*y3 x1*y2
8 index 7 index mul sub % ... [ x2*y3-y2*x3 x3*y1-x1*y3 x1*y2-x2*y1
]
7 1 roll 6 { pop } repeat
} bind def
/transpose { STATICDICT begin
/A exch def
/M A length def
/N A 0 get length def
[
0 1 N 1 sub { /n exch def
[
0 1 M 1 sub { /m exch def
A m get n get
} for
]
} for
]
end } dup 0 6 dict put def
/matmul { STATICDICT begin
/B exch def
B 0 get type /arraytype ne { /B [B] def } if
/A exch def
A 0 get type /arraytype ne { /A [A] def } if
/Q B length def
/R B 0 get length def
/P A length def
Q A 0 get length ne {
/A A transpose def
/P A length def
Q A 0 get length ne {
A B end /matmul cvx /undefinedresult signalerror
} if
} if
[
0 1 R 1 sub { /r exch def
[
0 1 P 1 sub { /p exch def
0
0 1 Q 1 sub { /q exch def
A p get q get
B q get r get mul
add
} for
} for
]
} for
]
end } dup 0 10 dict put def
%u v {operator} vop u(op)v
%apply a binary operator to corresponding elements
%in two vectors producing a third vector as result
/vop { 1 dict begin
/op exch def
2 copy length exch length ne {
/vop cvx end /undefinedresult signalerror
} if
[ 3 1 roll % [ u v
0 1 2 index length 1 sub { % [ ... u v i
3 copy exch pop get % u v i u_i
3 copy pop get % u v i u_i v_i
op exch pop % u v u_i(op)v_i
3 1 roll % u_i(op)v_i u v
} for % [ ... u v
pop pop ]
end } def
%length of a vector
/mag { 0 exch { dup mul add } forall } def
% x y z ang -> x y' z'
/rotx { 3 dict begin
/theta exch def
/z exch def
/y exch def
y theta cos mul
z theta sin mul sub
y theta sin mul
z theta cos mul add
end } def
% x y z ang -> x' y z'
/roty { 4 dict begin
/theta exch def
/z exch def
/y exch def
/x exch def
x theta cos mul
z theta sin mul add
y
x theta sin mul neg
z theta cos mul add
end } def
% x y z ang -> x' y' z
/rotz { 4 dict begin
/theta exch def
/z exch def
/y exch def
/x exch def
x theta cos mul
y theta sin mul sub
x theta sin mul
y theta cos mul add
z
end } def
% x y z -> x' y' z'
/model {
%ang roty
%ang .25 mul rotx
%alpha rotz
beta roty
gamma rotx
} def
% Eye coords
/ex .1 def
/ey .1 def
/ez 5 def
/eyedir [ex ey ez]
dup mag [ exch dup dup ]{div} vop
def
% x y z -> X Y
/project {
3 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 } def
/light
[ 3 -7 -2 1 ]
dup mag [ exch dup dup dup ]{div} vop
def
/Ia .4 def % Incident Ambient Intensity
/Ka .4 def % Ambient Diffuse reflection constant
/Il .5 def % Incident intensity of Lightsource
/Kd .3 def % Diffuse reflection constant
%h R N
/cylinder { 20 dict begin
/N exch def
/R exch def
/h exch def
/dz 1 N div def
/dt 360 dz mul def
/hdz h dz mul def
0 dz 1 dz sub {
h mul h 2 div sub /z exch def
0 dt 360 { /t exch def
/v1 [ t cos R mul
t sin R mul
z ] def
/v4 [ v1 aload pop pop
z hdz add ] def
/t t dt add def
/v2 [ t cos R mul
t sin R mul
z ] def
/v3 [ v2 aload pop pop
z hdz add ] def
[ v1 v2 v3 v4 ] {
aload 4 1 roll model 4 3 roll astore pop
} forall
/normal v4 v1 {sub} vop
v2 v1 {sub} vop
cross def
/nlen normal mag def
/normal normal [nlen nlen nlen] {div} vop def
[normal aload pop 1] [eyedir aload pop 1] dot 0 lt {
/action { moveto /action { lineto } def } def
[ v1 v2 v3 v4 ]
{ aload pop project action }
forall
closepath
% gsave
[normal aload pop 1]
light
%[ex ey ez neg 1] %"radiant"
dot
Il Kd mul mul
Ia Ka mul add
setgray
fill
% grestore
% stroke
} if
} for
} for
end } def
300 400 translate
280 dup dup moveto
dup neg dup neg lineto
dup neg dup lineto
dup neg lineto closepath .6 setgray fill
1 70 dup dup scale div setlinewidth
%/beta 0 def
%/gamma 0 def
%4 2 50 cylinder
/beta 90 def
/gamma 0 def
4 2 50 cylinder
%/beta 0 def
%/gamma 90 def
%4 2 50 cylinder
showpage
答案 0 :(得分:0)
好吧,我想出了一些在肠道里更容易的东西。
6%的捏造让人觉得很可怕。
但肯建议可能涉及四舍五入。这意味着控制四舍五入应该获得对问题的一些控制措施。它看起来确实如此。
所以我尝试通过调用moveto
来预先调用所有lineto
和prep
来电:
/prep {
transform
%2 {
% exch
%floor
round
%ceiling
%2 mul cvi 2 div %round
%} repeat
itransform
} def
评论显示我试过的各种作品。在两个设备坐标上舍入消除了所有水平放气线并留下非常薄的垂直出血。假设Ghostscript通过水平扫描线进行栅格化,这似乎是有意义的:它可以更容易地与水平扫描线一起使用,只需要一些帮助,但近垂直更难。
然后我把它与捏造结合起来。我发现只需将设备四舍五入并将贴片尺寸捏合2%即可消除所有出血。它真的照亮了这个蝙蝠洞。
我认为,2%是可接受的捏造水平。 (?)不幸的是,当您调整N的值(切片数量)时,上述所有内容都需要调整。覆盖整个表面的最简单的方法是将边缘描边与填充颜色相同。这里唯一的难点是确保线宽适合规模。而这样做的简单方法就是将它们放在一起。对于非常高的分辨率,这应该以某种方式进行调整以考虑N.
1 70 dup dup scale div setlinewidth
这是最终程序生成的图像之一,带有坐标轴和随机颜色的Steinmetz实体,略微偏斜的视角(右脚伸出一点点)。