challenge ポリゴンを表示するプログラム

適当なポリゴンを表示させて、描画するプログラムを書いてください。
ポリゴンは回転させてください。

2D処理だけなら、標準ライブラリで大体いけますが、
3D処理は追加でライブラリを利用すると思うので、
何のライブラリを利用したのか書いてください。

Posted feedbacks - Flatten

Nested Hidden
ネタ回答~
適当なポリゴンを表示してしかもポリゴンは回っています
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
use strict;

my @pos = (
[[0,0],[1,1],[2,2],[3,3]],
[[1,0],[1,1],[2,2],[2,3]],
[[2,0],[2,1],[1,2],[1,3]],
[[3,0],[2,1],[1,2],[0,3]],
[[3,1],[2,1],[1,2],[0,2]],
[[3,2],[2,2],[1,1],[0,1]],
[[3,3],[2,2],[1,1],[0,0]],
[[2,3],[2,2],[1,1],[1,0]],
[[1,3],[1,2],[2,1],[2,0]],
[[0,3],[1,2],[2,1],[3,0]],
[[0,2],[1,2],[2,1],[3,1]],
[[0,1],[1,1],[2,2],[3,2]],
);

my $i = 0;
while (1) {
  my $cpos = $pos[$i];
  my @cell;
  $cell[$cpos->[0][0]][$cpos->[0][1]] = 'ポ';
  $cell[$cpos->[1][0]][$cpos->[1][1]] = 'リ';
  $cell[$cpos->[2][0]][$cpos->[2][1]] = 'ゴ';
  $cell[$cpos->[3][0]][$cpos->[3][1]] = 'ン';

  clear_screen();
  print "適当な\n";
  foreach my $c ( @cell ) {
    foreach my $cc ( @$c ) {
      print $cc ? $cc : '  ';
    }
    print "\n";
  }
  sleep 1;
} continue {
  if ( ++$i == @pos ) {
    $i = 0;
  }
}

sub clear_screen
{
  if ( $^O =~ /Win32/ ) {
    system('cls');
  }
  else {
    if (system('clear') != 0) {
      print "\x1b[2J";
    }
  }
}

HSP 3.1以降に標準添付のライブラリ d3module を使って。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include "d3m.hsp"
    
    xs = -1, 1, 1,-1
    ys = -1,-1, 1, 1
    
    repeat
        redraw 0
        color 255, 255, 255 : boxf
        d3setcam 1500, 0, 500
        color
        d3initlineto
        rad = 0.05 * cnt
        repeat 5
            x = xs(cnt\4) * 500
            y = ys(cnt\4) * 500
            d3rotate x, y, x, y, rad
            d3lineto x, y, 0
            d3line x, y, 0, 0, 0, 700
            d3line x, y, 0, 0, 0, -700
        loop
        redraw
        await 40
    loop

Squeak Smalltalk で。Balloon3D というパッケージを用いて正十二面体を回転させました。

1
2
3
4
5
6
7
8
9
| sceneObj view solid colors |
solid := B3DRegularSolid dodekahedron.
colors := (Color wheel: 12) collect: [:each | each asB3DColor].
solid setFaceColors: colors.
sceneObj := B3DSceneObject named: 'solid'.
sceneObj geometry: solid.
view := AdvancedB3DSceneMorph new.
view scene objects: (OrderedCollection with: sceneObj).
view beRotating; openInHand

ポリゴン(多角形) でよいのでしょうか? それともポリヘドロン(多面体)? ポリゴンを面内で回す分には3次元ライブラリは要らなそうですが....


以下の手順で描いています(Mathematica 6)。

1. 頂点を定義
2. ポリゴンを定義
3. 描画

マウスでドラッグすると回転します。

特別なライブラリは使っていません。
(Mathematica 5だと「<< RealTime3D`」が必要です。)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
a = {1, 0, 0};
b = {-1/2, Sqrt@3/2, 0};
c = {-1/2, -Sqrt@3/2, 0};
d = {0, 0, Sqrt@2};

tetra = {
   Polygon[{a, b, c}],
   Polygon[{a, b, d}],
   Polygon[{b, c, d}],
   Polygon[{c, a, d}]
  };

Show[Graphics3D[tetra]]

たぶん題意は「ポリゴンを3次元的に回す(面内で回すのではなく)」と言うことでしょう。


VPython

1
2
3
from visual import *
redbox=box()
while 1: redbox.rotate(angle=1)

題意を、

・ポリゴンによって任意の立体を表示する。
・立体は回転させる。

という意味と解釈しました。

Java3Dによって立方体を回転させています。回転はY軸方向とX軸方向のそれぞれで行っています(Y軸方向だけでも良かったのですが、それでは全部の面が見えないのでX軸方向の回転を追加しました)。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import javax.swing.*;
import java.awt.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.ColorCube;

@SuppressWarnings("serial")
public class Sample3D extends JFrame {
    public BranchGroup createSceneGraph() {
        BranchGroup objRoot = new BranchGroup();

        TransformGroup objTrans = new TransformGroup();
        objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        objRoot.addChild(objTrans);

        Transform3D axis = new Transform3D();
        axis.rotZ(Math.PI / 2);
        BoundingSphere bounds = new BoundingSphere(new Point3d(), 100.0);
        RotationInterpolator rotator = new RotationInterpolator(new Alpha(-1,
                20 * 4000), objTrans, axis, 0.0f, (float) Math.PI * 2.0f);
        rotator.setSchedulingBounds(bounds);
        objRoot.addChild(rotator);

        TransformGroup objTrans2 = new TransformGroup();
        objTrans2.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        objTrans.addChild(objTrans2);
        rotator = new RotationInterpolator(new Alpha(-1, 4000), objTrans2);
        rotator.setSchedulingBounds(bounds);
        objRoot.addChild(rotator);

        objTrans2.addChild(new ColorCube(0.4));
        objRoot.compile();
        return objRoot;
    }

    public Sample3D() {
        getContentPane().setLayout(new BorderLayout());
        GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
        Canvas3D canvas = new Canvas3D(config);
        getContentPane().add(canvas, BorderLayout.CENTER);
        BranchGroup scene = createSceneGraph();
        SimpleUniverse universe = new SimpleUniverse(canvas);
        universe.getViewingPlatform().setNominalViewingTransform();
        universe.addBranchGraph(scene);
    }

    public static void main(String[] args) {
        Sample3D sample = new Sample3D();

        sample.setBounds(10, 10, 480, 480);
        sample.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        sample.setVisible(true);
    }
}

DirectXを使いました~。
平面ポリゴンを回転させてるだけです。
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
using System;
using System.Drawing;
using System.Windows.Forms;

using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

class ViewPoly : Form
{
    private Device dev;
    private VertexBuffer vertex;
    private float polyTheta = 0.0f;

    public bool Init()
    {
        this.Text = "ポリゴン回ります";
        this.MaximizeBox = false;
        this.FormBorderStyle = FormBorderStyle.FixedSingle;
        this.Size = new Size(480, 480);

        PresentParameters pp = new PresentParameters();
        pp.Windowed = true;
        pp.SwapEffect = SwapEffect.Discard;
        pp.EnableAutoDepthStencil = true;
        pp.AutoDepthStencilFormat = DepthFormat.D16;

        try
        {
            this.dev = new Device(
                0, 
                DeviceType.Reference,
                this.Handle,
                CreateFlags.SoftwareVertexProcessing,
                pp
            );
        }
        catch
        {
            return false;
        }

        this.vertex = new VertexBuffer(
            typeof(CustomVertex.PositionColored),
            4,
            this.dev,
            Usage.None,
            CustomVertex.PositionColored.Format,
            Pool.Managed
        );

        this.dev.Transform.View = Matrix.LookAtLH(
            new Vector3(0.0f, 0.0f, -15.0f),
            new Vector3(0.0f, 0.0f, 0.0f),
            new Vector3(0.0f, 1.0f, 0.0f)
        );

        this.dev.Transform.Projection = Matrix.PerspectiveFovLH(
            Geometry.DegreeToRadian(60.0f),
            (float)this.dev.Viewport.Width / (float)this.dev.Viewport.Height,
            1.0f,
            100.0f
        );

        this.dev.RenderState.Lighting = false;
        this.dev.RenderState.CullMode = Cull.None;

        return true;
    }

    public void Render()
    {
        this.dev.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.DarkBlue, 1.0f, 0);
        this.dev.BeginScene();
        this.RollingPoly();
        this.dev.EndScene();
        this.dev.Present();

    }

    private void RollingPoly()
    {
        float theta = Geometry.DegreeToRadian(
            (float)((polyTheta -= 10.0f) % 360.0f)
        );

        CustomVertex.PositionColored[] vertexPc
            = new CustomVertex.PositionColored[4];

        vertexPc[0] = new CustomVertex.PositionColored(
            -4.0f * (float)(Math.Sin(theta)),
            4.0f,
            -4.0f * (float)Math.Cos(theta),
            Color.Red.ToArgb()
        );
        vertexPc[1] = new CustomVertex.PositionColored(
            4.0f * (float)(Math.Sin(theta)),
            4.0f,
            4.0f * (float)Math.Cos(theta),
            Color.Blue.ToArgb()
        );
        vertexPc[2] = new CustomVertex.PositionColored(
            -4.0f * (float)(Math.Sin(theta)),
            -4.0f,
            -4.0f * (float)Math.Cos(theta),
            Color.Red.ToArgb()
        );
        vertexPc[3] = new CustomVertex.PositionColored(
            4.0f * (float)(Math.Sin(theta)),
            -4.0f,
            4.0f * (float)Math.Cos(theta),
            Color.Blue.ToArgb()
        );

        using (GraphicsStream gs
            = this.vertex.Lock(0, 0, LockFlags.None))
        {
            gs.Write(vertexPc);
            this.vertex.Unlock();
        }

        this.dev.SetStreamSource(0, this.vertex, 0);
        this.dev.VertexFormat = CustomVertex.PositionColored.Format;
        this.dev.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);
    }

    public void dispose()
    {
        if (this.vertex != null)
            this.vertex.Dispose();

        if (this.dev != null)
            this.dev.Dispose();
    }

    public static void Main(string[] args)
    { 
        using (ViewPoly vp = new ViewPoly())
        {
            if (vp.Init())
            {
                vp.Show();
                while (vp.Created)
                {
                    vp.Render();
                    Application.DoEvents();
                    System.Threading.Thread.Sleep(50);
                }
                vp.dispose();
            }
        }
    }
}

プログラムと呼ぶのかはわかりませんが、マウスでぐりぐりっと回転できます.
VRMLビューアが必要です.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#VRML V2.0 utf8
Shape {
  geometry IndexedFaceSet {
    coord Coordinate {
      point [ 0 0 0.3, 0 2 0, 1.73 -1 0, -1.73 -1 0 ]
    }
    coordIndex [
     0 1 2 -1
     0 2 3 -1
     0 3 1 -1
    ]
    solid FALSE
  }
  appearance Appearance {
    material Material {}
  }
}

ありふれた環境でもできないものかと、 ECMA Script + SVGで書きました。

 tetrahedron.svgなどの名前でファイルを保存し、ブラウザにドラッグアンドドロップす
ることで、回転する四面体が表示されます。

Adobe SVG Viewerでは動作しません。 Firefox 2.0.0.8, Opera 9.26, Safari 3.1で動作
を確認しました。
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg" onload="new Tetrahedron(100).rotate(1, 1)">
    <script type="text/ecmascript">
    <![CDATA[
        var NS = document.documentElement.getAttribute('xmlns'); // 名前空間

        Function.prototype._setInterval = 
        function (t, o, v) {
            var _ = this;
            return setInterval(function () { _.apply(o, v); }, t);
        };

        var Tetrahedron = 
        function (n /* 一辺の長さ */) {
            this._ = null;
            this.u = null; // 上面
            this.l = null; // 下面
            this.s = [  ]; // 側面
            this.x = 0;
            this.y = 0;
            this.R = (Math.PI / 180).toFixed(2); // ラジアン角
            this.S = n;
            this.X = [ 0, n, n, 0 ];
            this.Z = [ 0, 0, n, n ];

            // 正四面体
            this._ = document.createElementNS(NS, 'g');
            this._.setAttribute('transform', 'translate(250, 250)');
            document.rootElement.appendChild(this._);
            // 上面
            this.u = document.createElementNS(NS, 'path');
            this.u.setAttribute('stroke', 'none');
            this.u.setAttribute('fill', '#000000');
            this.u.setAttribute('opacity', 0.4);
            this._.appendChild(this.u);
            // 下面
            this.l = document.createElementNS(NS, 'path');
            this.l.setAttribute('stroke', 'none');
            this.l.setAttribute('fill', '#000000');
            this.l.setAttribute('opacity', 0.4);
            this._.appendChild(this.l);
            // 側面
            for (i = 0; i < 4; i++) {
                this.s[i] = document.createElementNS(NS, 'path');
                this.s[i].setAttribute('stroke', 'none');
                this.s[i].setAttribute('fill', '#000000');
                this.s[i].setAttribute('opacity', 0.5);
                this._.appendChild(this.s[i]);
            }
            // ビューポート
            document.rootElement.setAttribute('width' , 500);
            document.rootElement.setAttribute('height', 500);
            // ビューボックス
            document.rootElement.setAttribute('viewBox', '0 0 500 500');
            document.rootElement.setAttribute('preserveAspectRatio', 'xMinYMin slice');
        };

        Tetrahedron.prototype.move = 
        function (v /* 垂直方向の増分 */, h /* 水平方向の増分 */) {
            var U = [], L = [];
            var l = '', u = '', s = '';
            var i, j;

            this.x += v; this.y += h;

            // 上面, 下面
            for (i = 0; i < 4; i++) {
                U[i] = this.transform(this.x * this.R, this.y * this.R, 0, this.X[i], this.S, this.Z[i]);
                L[i] = this.transform(this.x * this.R, this.y * this.R, 0, this.X[i],      0, this.Z[i]);
                u += ((i == 0) ? 'M' : 'L') + ' ' + U[i].x + ' ' + U[i].y + ' ';
                l += ((i == 0) ? 'M' : 'L') + ' ' + L[i].x + ' ' + L[i].y + ' ';
            }
            this.u.setAttribute('d', u + 'Z');
            this.l.setAttribute('d', l + 'Z');
            // 側面
            for (i = 0, j = 1; i < 4; i++, j++) {
                if (j == 4) j = 0;
                s = 'M ' + L[i].x + ' ' + L[i].y + ' '
                  + 'L ' + U[i].x + ' ' + U[i].y + ' '
                  + 'L ' + U[j].x + ' ' + U[j].y + ' '
                  + 'L ' + L[j].x + ' ' + L[j].y + ' ';
                this.s[i].setAttribute('d', s + 'Z');
            }
        };

        Tetrahedron.prototype.transform = 
        function (_x, _y, _z, x, y, z) {
            var __x, __y, __z;

            __x = x * Math.cos(_y) +   z * Math.sin(_y);
            __z = z * Math.cos(_y) -   x * Math.sin(_y);
            __y = y * Math.cos(_x) - __z * Math.sin(_x);

            return { 'x' : __x * Math.cos(_z) - __y * Math.sin(_z)
                   , 'y' : __x * Math.sin(_z) + __y * Math.cos(_z)
                   }; // アフィン変換
        };

        Tetrahedron.prototype.rotate = 
        function (h, v) {
            this.move._setInterval(50, this, [ h, v ]);
        };
    ]]>
    </script>
</svg>

昔どこかのページを参考に作った奴です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
module Main where

import System
import Graphics.UI.GLUT
import System.Random

display n = do
    clear [ ColorBuffer ]
    color $ Color3 (0.6::Double) 0.6 0.6
    preservingMatrix $ do
        renderPrimitive Polygon $ mapM_ vertex (nlist n)
    flush
    where
        nlist n = nVertex n du
        du = 2.0 * pi / fromIntegral n

nVertex n du
    | n == 0        = [ point ]
    | otherwise     = point : nVertex (n-1) du
    where
        radius = 0.75
        x = toRational (radius * cos (pi / 2.0 + fromIntegral n * du))
        y = toRational (radius * sin (pi / 2.0 + fromIntegral n * du))
        point = Vertex3 (fromRational x) (fromRational y) (0.0 :: GLfloat)


timer n = do
        rotate (1::Double) (Vector3 0 1 0)
        display n
        finish
        addTimerCallback 10 (timer n)

inputKey (Char 'q') _ _ _  = exitWith ExitSuccess
inputKey _ _ _ _            = return ()

main = do
    (fileName, args) <- getArgsAndInitialize
    let n = case args of
        [] -> 3
        _ -> max 3 $ read $ head args
    createWindow "Haskell OpenGL"
    displayCallback $= display n
    addTimerCallback 1000 (timer n)
    keyboardMouseCallback $= Just (inputKey)
    mainLoop

PostScript で。
2次元なら簡単なんですが、3次元は手頃なライブラリが見当らないので力技で。
動画というわけにはいかないので、パラパラ漫画を出力します。
シェーダーを実装する元気はないので、立体感は強引な陰線処理と
ステレオ図の出力で勘弁しといて下さい。
# どっかにレイトレースする PS のコードがあったような....
前半分はひたすら行列計算用のコードです。

このままプリンタ出力すると 36枚で立方体がぐるっと一周まわります。
ghostscriptかAcrobat でページをすばやく切り替えて眺めてやると
回っているように見えるかなぁ.....
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
%!PS

% Tiny Vector Library
/DotProduct { % [Vector1] [Vector2]  DotProduct scaler
    [ 3 1 roll
    dup length 1 sub 0 1 3 -1 roll {
        3 copy get 3 1 roll exch get mul 3 1 roll
    } for
    pop pop
    ]

    0 exch
    { add } forall
} bind def

/VectorAdd { % [Vector1] [Vector2]   VectorMul  [NewVector]
    [ 3 1 roll
    dup length 1 sub 0 1 3 -1 roll {
    3 copy get 3 1 roll exch get add 3 1 roll
    } for
    pop pop
    ]
} bind def

/VectorScale { % [Vector] scale  VectorScale  [Vector']
    0 1 3 index length 1 sub {
        2 index 1 index get
        2 index mul
        3 index 3 1 roll put
    } for
    pop
} bind def

/VectorCopy { % [Vector]  VectorScale  [NewVector]
    aload length array astore
} bind def


% Tiny Matrix Library
/MatrixTranspose { % [Matrix1] MatrixTranspose [NewMatrix]
    [ exch
    dup 0 get length 1 sub 0 1 3 -1 roll
    {
        [ exch 2 index
        {
            1 index get
            exch
        } forall
        pop ]
        exch
    } for
    pop
    ]
} bind def

/MatrixMul { % [[Matrix1]] [[Matrix2]]  MatrixMul  [[NewMatrix]]
    MatrixTranspose exch
    [ 3 1 roll
    {
        [ exch 2 index
        {
            1 index DotProduct exch
        } forall
        pop
    ] exch
    } forall
    pop
    ]
} bind def

/MatrixCopy { % [[Matrix]] MatrixCopy [[NewMatrix]]
    [ exch
    {
        VectorCopy
    } forall
    ]
} bind def

/Matrix3Copy { % [[[Matrix]]] Matrix3Copy [[[NewMatrix]]]
    [ exch
    {
        MatrixCopy
    } forall
    ]
} bind def

/VectorZero { % [Vector] VectorZero [Vector']
    0 1 2 index length 1 sub {
        1 index exch 0 put
    } for
} bind def
/VectorRoll { % [Vector] roll_count VectorRoll [Vector']
    mark 2 index aload length counttomark 1 add index roll
    counttomark 2 add index astore pop pop pop
} bind def

/MatrixIdentity { % size MatrixIdentity [[NewMatrix]]
    [ exch dup array VectorZero dup 0 1 put
    % [ size [1 0 ... 0]
    exch {
        dup VectorCopy 1 VectorRoll
    } repeat
    pop
    ]
} bind def

% End of Matrix Library
% --------------------------------------
/VY { [ exch ] MatrixTranspose } bind def
/VX { MatrixTranspose 0 get } bind def

/RotateMatrixX { % theta(degree)   RotateMatrixX   [Matrix]
    dup cos exch sin 2 copy neg % cos sin cos -sin
    [
        [ 1 0 0]
        [ 0 6 -2 roll ]
        [ 0 7 -2 roll exch ]
    ]
} bind def

/RotateMatrixY { % theta(degree)   RotateMatrixY   [Matrix]
    dup cos exch sin 2 copy neg % cos sin cos -sin
    [
        [ 6 -1 roll 0 7 -1 roll ]
        [ 0 1 0 ]
        [ 5 -1 roll 0 7 -1 roll ]
    ]
} bind def

/RotateMatrixZ { % theta(degree)   RotateMatrixZ   [Matrix]
    dup cos exch sin 2 copy neg % cos sin cos -sin
    [
        [ 4 -2 roll 0 ]
        [ 5 -2 roll exch 0 ]
        [ 0 0 1 ]
    ]
} bind def

/CompareDistance { % [x1 y1 z1] [x2 y2 z2] CompareDistance [] [] z1-z2
    dup 0 get 2 get 3 -1 roll dup 0 get 2 get
    % [V2] z2 [V1] z1
    exch 4 1 roll sub
} bind def

/Sort { % [[x y] [x1 y1] Array Data ] {CompareFunction}  Sort [ArrayData]
    cvx [ 3 -1 roll
    aload length
    % func -mark[- [] [] [] [] [] len
    -1 2 { % func -mark[- [] [] [] [] [] len2
        -1 2 {
            3 1 roll
            counttomark 1 add index exec  %% Compare
            0 lt { exch } if
            3 -1 roll
            1 roll
        } for
        counttomark 1 roll
    } for
    counttomark 1 roll
    ] exch pop
} bind def

/CalcVertex { % [Vect] distance scale  CalcVertex  x y
        3 -1 roll aload pop
        % distance scale x y z
        5 -2 roll exch
        % x y z scale  distance
        dup 0 eq {
            pop  exch pop
        } {
            3 -1 roll add div
        } ifelse
        % x y scale
        dup 3 -1 roll mul
        % x scale scale*y
        3 1 roll mul exch
} bind def


/DrawPolygon { % [[GC] [Vertex1] [Vertex2] ...] distance scale
    3 -1 roll mark exch aload pop
    counttomark 2 add index counttomark 1 add index CalcVertex
    moveto

    counttomark 1 sub {
        counttomark 2 add index counttomark 1 add index CalcVertex
        lineto
    } repeat
    closepath
    gsave 0.5 setgray fill  grestore
    0.1 setlinewidth stroke
    pop pop pop pop
} bind def

/Projection {
    % distance scale [[Object]] view_matrix Projection
    %                 distance scale [[Object]] view_matrix 
    4 1 roll dup Matrix3Copy dup {
        % vmt dist scale [[Obj]] [[NewObj]] [[Polygon-n]]
        {
            % vmt dist scale [[Obj]] [[NewObj]] [[Vertex-n]]
            dup 6 index exch VY MatrixMul VX
            0 exch putinterval
        } forall
    } forall
    /CompareDistance Sort
    % vmt dist scale [[Obj]] [[NewObj']] 
    {
        % vmt dist scale [[Obj]] [[NewPolygon-n]]
        3 index 3 index DrawPolygon
    } forall
    4 -1 roll
} bind def


/Translate { % [[[Object]]] [dx dy dz]  Translate [[[Object']]]
    1 index {
        % [[[Object]]] [dx dy dz] [[Polygon]]
        {
            % [[[Object]]] [dx dy dz] [x y z]
            dup 2 index VectorAdd
            % [[[Object]]] [dx dy dz] [x y z] [nx ny nz]
            0 exch putinterval
        } forall
    } forall
    pop
} bind def

% ---------------- Test Code -------------------

/Cube [
    % Gravity Center, Vertex1, 2, .... 
    [[0.5 0.5 0] [0 0 0] [1 0 0] [1 1 0] [0 1 0]]
    [[0.5 0.5 1] [0 0 1] [1 0 1] [1 1 1] [0 1 1]]
    [[0 0.5 0.5] [0 0 0] [0 1 0] [0 1 1] [0 0 1]]
    [[1 0.5 0.5] [1 0 0] [1 1 0] [1 1 1] [1 0 1]]
    [[0.5 0 0.5] [0 0 0] [0 0 1] [1 0 1] [1 0 0]]
    [[0.5 1 0.5] [0 1 0] [0 1 1] [1 1 1] [1 1 0]]
] def


/Demo {
    % Projection Distance  & Scale
    5   400
    % Object
    Cube [-0.5 -0.5 -0.5] Translate
    % Initial View Matrix
    3 MatrixIdentity
    -20 RotateMatrixX MatrixMul
    20 RotateMatrixY MatrixMul
    5 RotateMatrixZ MatrixMul

    % Rotation
    36 {
        gsave
        200 200 translate
        1 1 scale
        0.1 setlinewidth
        Projection
%---- Stereo Projection ----
        200 0 translate
        5 RotateMatrixY MatrixMul
        Projection
        -5 RotateMatrixY MatrixMul
%---- End Stereo Projection ----
        grestore
        showpage
        10 RotateMatrixY MatrixMul
    } repeat
    4 { pop } repeat
} bind def

Demo

Ruby/SDLとOpenGLでベタに書いてみました。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
require 'sdl'
require 'opengl'

vertices = [
  [[1.0, 0.0, 0.0], [-1.0, -1.0, 0.0]],
  [[0.0, 1.0, 0.0], [ 1.0, -1.0, 0.0]],
  [[0.0, 0.0, 1.0], [ 1.0,  1.0, 0.0]],
  [[1.0, 1.0, 1.0], [-1.0,  1.0, 0.0]]
]

SDL.init(SDL::INIT_VIDEO)
SDL::Screen.open(600, 600, 16, SDL::OPENGL)

GL.ClearColor(0.0, 0.0, 0.2, 1.0);
GL::Ortho(-2.0, 2.0, -2.0, 2.0, -2.0, 2.0)
GL::MatrixMode(GL::MODELVIEW);

loop {
  GL.Clear(GL::COLOR_BUFFER_BIT);
  
  GL::Rotate(1.0, 2.0, 3.0, 1.0);
  
  GL::Begin(GL::QUADS)
  vertices.each {|v|
    GL::Color(v[0])
    GL::Vertex(v[1])
  }  
  GL::End()
  
  SDL::GL.swap_buffers
  
  evt = SDL::Event.poll
  case evt
  when SDL::Event::Quit
    exit
  when SDL::Event::KeyUp
    exit if evt.sym == SDL::Key::ESCAPE
  end
}

Processing で。 可視化が本分の Processing で、 python より長いのがちょっと残念ですが。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
float theta = 0.0;

void setup() {
  size(200, 200, P3D);
}

void draw() {
  background(0);
  lights();
  translate(width/2, height/2, 0);
  rotateX(PI/3+theta);
  rotateY(theta);
  box(100);
  theta += PI/256;
}

ログインし忘れました


cl-glfwを利用しています。付属のサンプルを少し改造しただけです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
require '#:asdf)
(asdf:oos 'asdf:load-op '#:cl-glfw)
(asdf:oos 'asdf:load-op '#:cl-glfw-opengl)
(asdf:oos 'asdf:load-op '#:cl-glfw-glu)

(glfw:do-window ("A Polygon Example")
    ((gl:with-setup-projection
       (glu:perspective 45 4/3 0.1 50)))
  (gl:clear gl:+color-buffer-bit+)
  (gl:load-identity)
  (gl:translate-f 0 0 -5)
  (gl:rotate-f (* 10 (glfw:get-time)) 1 1 0)
  (gl:rotate-f (* 90 (glfw:get-time)) 0 0 1)
  (gl:with-begin gl:+line-loop+ ;+triangle-strip+
    (gl:color-3f 0 1 0) (gl:vertex-3f -1  1 0)
    (gl:color-3f 0 0 1) (gl:vertex-3f -1 -1 0)
    (gl:color-3f 0 1 0) (gl:vertex-3f -1  0 1)
    (gl:color-3f 0 1 0) (gl:vertex-3f -1  1 0)
    (gl:color-3f 1 0 0) (gl:vertex-3f  1  0 0)
    (gl:color-3f 0 1 0) (gl:vertex-3f -1  0 1)
    (gl:color-3f 1 0 0) (gl:vertex-3f  1  0 0)
    (gl:color-3f 0 0 1) (gl:vertex-3f -1 -1 0)))

Index

Feed

Other

Link

Pathtraq

loading...