こんにちは。きんくまです。
8月末日、関東は見事に台風直撃の状態の中、皆様いかがお過ごしでしょうか。
お正月に見て面白かった、恐竜SFドラマの「プライミーバル」。
第二章が先週始まりまして、見ました。
>> 恐竜SFドラマ プライミーバル|NHK 総合 海外ドラマ
これがまた、恐竜が実写に馴染んですごくよくできていて面白いです。
前回、半分悪役キャラだったリーダーの奥さんがまだ出てきていないんですが、また出てきてひと悶着起こしてくれれば、物語がますます面白くなることでしょう。
これはさっきTwitterにも書いたんですが。
CGといえば、Tron。Tronは国産OSの方じゃなくて1982年の映画の方です。
以前NHKの海外ドキュメンタリーで「VFXの歴史」みたいな番組を見てたときに知りました。
まずはこっちの映像を。
wikiによると「世界で初めて全面的にコンピュータグラフィックスを導入した映画」となっています。
この翌年1983年にファミコンの登場。
1984年に初代ターミネーター(ラストシーンが模型のコマ撮り)
1985年に初代バック・トゥ・ザ・フューチャー
と考えるとCGで意欲的に取り組んだ作品であることは間違いなしですね。
ただNHKでもやっていましたが、興行的には振るわなかったようです。
まあ今見ると、見た目ショボそうだもんね。
だけど、このときに関わったスタッフが現在のCG・IT界で活躍しているみたいです。
今調べたら、ターンAのシド・ミードやフランスの漫画家メビウスも関わってたみたい。
>> 解説・あらすじ – トロン(1982)
前置きが長くなりました。それで、来年にリメイク版が公開(日本でそこまでいくのか?)されるみたい。
ぜひ音つきでみてくださいな。
30年でここまで変わるんですね。シド・ミードとメビウスのイメージしてた世界ってこんなんだったのかな。
————————-
おっと、ASに関係ない話が続きましたね。
前回drawTrianglesでポリゴンを作ったんですが、zバッファーが実装できずに描画が変な風になってました。
それを以下の3Dの基本的なアルゴリズムで修正しました。
1. zバッファ(1pxごとのz値)は無理なので、三角形ポリゴンごとの最大z値を取得
2. zソート
3. 奥のものから順番に描画することで奥行きを表現
という感じです。
実際のデモ
結局のところおじさんとタワーの関係があやしい瞬間がまだありますが、前回よりはよしとしましょう!
以下ソースです。
Main2
package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Graphics; import flash.display.MovieClip; import flash.display.Sprite; import flash.display.TriangleCulling; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Matrix3D; import flash.geom.PerspectiveProjection; import flash.geom.Utils3D; import flash.geom.Vector3D; import flash.text.TextField; import flash.utils.getDefinitionByName; import fl.controls.Slider; import fl.controls.CheckBox; public class Main2 extends MovieClip { public var s1:Slider; public var s1_txt:TextField; public var cullingChk:CheckBox; public var fl:Number = 180; public var proj:Matrix3D; public var triangles:Array = new Array(); public var stratBtn:MovieClip; public var texture:BitmapData; public var canvas:Sprite; public var yAxisDeg:Number = 0; public function Main2() { stratBtn.addEventListener(MouseEvent.CLICK, init); } public function init(e:Event):void { stratBtn.removeEventListener(MouseEvent.CLICK, init); stratBtn.visible = false; var TextureC:Class = getDefinitionByName("Texture") as Class; texture = new TextureC(0, 0); canvas = new Sprite(); canvas.x = stage.stageWidth / 2; canvas.y = stage.stageHeight / 2; addChildAt(canvas, 0); setTriangles(); addEventListener(Event.ENTER_FRAME, render); } private function setTriangles():void { var tri:Triangle; var i:int; var mat:Matrix3D = new Matrix3D(); var tverts:Vector.<Number>; //tower for (i = 0; i < 4; i++) { tverts = new Vector.<Number>(); tri = new Triangle(); tri.texture = texture; tri.pt1.push(0, -160, 0); tri.pt2.push(80, 160, -80); tri.pt3.push( -80, 160, -80); tri.setVerts(); mat.appendRotation(90 * i, Vector3D.Y_AXIS); //90度ずつ回転 mat.transformVectors(tri.verts, tverts); tri.verts = tverts; tri.uv.push( 0.1 + 0.2 * i, 0, 0.2 + 0.2 * i, 1.0, 0.2 * i, 1.0 ); triangles.push(tri); } //man for (i = 0; i < 2; i++) { tri = new Triangle(); tri.texture = texture; if (i == 0) { tri.pt1.push(-150, 0, 0); tri.pt2.push(-70, 0, 0); tri.pt3.push( -150, 160, 0); tri.uv.push( 0.8, 0, 1, 0, 0.8, 1.0 ); }else { tri.pt1.push(-70, 0, 0); tri.pt2.push(-70, 160, 0); tri.pt3.push( -150, 160, 0); tri.uv.push( 1, 0, 1, 1, 0.8, 1.0 ); } tri.setVerts(); triangles.push(tri); } } private function render(e:Event):void { var setCulling:String = cullingChk.selected ? TriangleCulling.NEGATIVE : TriangleCulling.NONE; fl = s1.value; s1_txt.text = "focalLength: " + s1.value; var transe:Matrix3D = new Matrix3D(); var verts:Vector.<Number> = new Vector.<Number>(); var drawVerts:Vector.<Number> = new Vector.<Number>(); var tVerts:Vector.<Number> = new Vector.<Number>(); var uvts:Vector.<Number> = new Vector.<Number>(); var perse:PerspectiveProjection = new PerspectiveProjection(); perse.focalLength = fl; proj = perse.toMatrix3D(); transe.appendRotation(yAxisDeg, Vector3D.Y_AXIS); transe.appendRotation(30, Vector3D.X_AXIS); transe.appendTranslation(0, 0, 1.1 * fl); var i:int; var tri:Triangle; for (i = 0; i < triangles.length; i++) { tri = triangles[i]; transe.transformVectors(tri.verts, tri.tverts); tri.setUVT(fl); tri.setMaxZ(); } triangles.sortOn("maxZ", Array.DESCENDING | Array.NUMERIC); for (i = 0; i < triangles.length; i++) { tri = triangles[i]; verts = verts.concat(tri.tverts); uvts = uvts.concat(tri.uvt); } Utils3D.projectVectors(proj, verts, drawVerts, uvts); var g:Graphics = canvas.graphics; g.clear(); g.beginBitmapFill(texture, null, false, true); g.drawTriangles(drawVerts, null, uvts, setCulling); g.endFill(); yAxisDeg += 1; } } }
Triangle
package { import flash.display.BitmapData; public class Triangle { public var pt1:Vector.<Number>; public var pt2:Vector.<Number>; public var pt3:Vector.<Number>; public var maxZ:Number; public var uv:Vector.<Number>; public var uvt:Vector.<Number>; public var verts:Vector.<Number>; public var texture:BitmapData; public var tverts:Vector.<Number>; public function Triangle() { pt1 = new Vector.<Number>(); pt2 = new Vector.<Number>(); pt3 = new Vector.<Number>(); uv = new Vector.<Number>(); } public function setVerts():void { verts = Vector.<Number>(pt1); verts = verts.concat(pt2); verts = verts.concat(pt3); tverts = new Vector.<Number>(); } public function setUVT(fl:Number):void { uvt = new Vector.<Number>(); var z1:Number = pt1[2]; var z2:Number = pt2[2]; var z3:Number = pt3[2]; uvt.push( uv[0], uv[1], fl / (fl + z1), uv[2], uv[3], fl / (fl + z2), uv[4], uv[5], fl / (fl + z3) ); } public function setMaxZ():void { var z1:Number = tverts[2]; var z2:Number = tverts[5]; var z3:Number = tverts[8]; maxZ = z1 > z2 ? z1 : z2; maxZ = maxZ > z3 ? maxZ : z3; } } }
■ 自作iPhoneアプリ 好評発売中!
・フォルメモ - シンプルなフォルダつきメモ帳
・ジッピー電卓 - 消費税や割引もサクサク計算!
■ LINEスタンプ作りました!
毎日使える。とぼけたウサギ