TwiSearch Sphere
機能修正・追加しました
http://wonderfl.net/c/uDFr
----
・遊び方
1)下の検索窓に何か単語をいれてください。
twitter 検索を元にステージデータを作成します。
unique チェックがついていると同一人物の発言は省きます。
2)ブロックが配置されたらマウスを動かすだけ。
正しい場所にマウスをあわせるとアイコンが浮かび上がり、検索結果の発言がでてきます。
3)あきるまで繰り返す。
・参考にさせていただいた巨匠たち(Thanks!)
さめがめ - 完成版 http://wonderfl.net/c/nYXj
Twitterの検索z軸つき http://wonderfl.net/c/g2Gi
Picasaから画像検索をして表示する。 http://wonderfl.net/c/342x/
・追加/修正したい箇所
1) 負荷へらす。
2) 検索結果のシャッフル
3) エフェクトる
4) エラー処理
/**
* Copyright ug24k8 ( http://wonderfl.net/user/ug24k8 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/1KAG
*/
/**
TwiSearch Sphere
・遊び方
1)下の検索窓に何か単語をいれてください。
twitter 検索を元にステージデータを作成します。
unique チェックがついていると同一人物の発言は省きます。
2)ブロックが配置されたらマウスを動かすだけ。
正しい場所にマウスをあわせるとアイコンが浮かび上がり、検索結果の発言がでてきます。
3)あきるまで繰り返す。
・追加/修正したい箇所
1) 負荷へらす。
2) 検索結果のシャッフル
3) エフェクトる
4) エラー処理
・参考にさせていただいた巨匠たち(Thanks!)
さめがめ - 完成版 http://wonderfl.net/c/nYXj
Twitterの検索z軸つき http://wonderfl.net/c/g2Gi
Picasaから画像検索をして表示する。 http://wonderfl.net/c/342x/
・誤算
1)最初は透視変換するつもりだったけど、初期配置がうまく計算できなかったので正射変換でとりあえず…
…ってそれなら最初からPapervision3Dでビルボードとかで作ればよかったんじゃないかと気づかないふり。
2)よく知らずに、ID入れたらフォロワーを対象にデータを作れるようにしてたら
web公開だとcrossdomainとかけっこうめんどいという事に1日たってから気づいて結局検索方式に…
*/
package {
import flash.display.Sprite;
import flash.events.Event;
[SWF(width="465", height="465", backgroundColor="0x202040", fps="30")]
public class Main extends Sprite {
private var manager_:Manager;
public function Main() {
manager_ = addChild(new Manager()) as Manager;
addEventListener(Event.ENTER_FRAME,
function(evt:Event):void {
manager_.update();
});
}
}
}
import adobe.utils.CustomActions;
import Box2D.Dynamics.Joints.b2RevoluteJointDef;
import com.adobe.images.BitString;
import com.bit101.components.CheckBox;
import flash.display.*;
import flash.events.*;
import flash.geom.Matrix;
import flash.geom.Matrix3D;
import flash.geom.PerspectiveProjection;
import flash.geom.Point;
import flash.geom.Vector3D;
import flash.net.*;
import flash.system.LoaderContext;
import flash.text.*;
import flash.ui.Keyboard;
import flash.utils.ByteArray;
import jp.nium.utils.ObjectUtil;
import jp.progression.casts.buttons.ParentButton;
import jp.progression.commands.Var;
import org.libspark.betweenas3.BetweenAS3;
class GameWork {
public static const INIT_WORD:String = "ホビロン";
public static const ICON_SIZE:int = 25;
public static const PANEL_SIZE:Number = 15.0;
public var search_word_:String;
public var entry_list_:Vector.<EntryData>;
}
class EntryData extends Object {
public var link:String;
public var uri:String;
public var author_name:String;
public var title:String;
public var img_url:String;
public function EntryData(src:EntryData = null) {
if (src) {
link = src.link;
uri = src.uri;
author_name = src.author_name;
title = src.title;
img_url = src.img_url;
}
}
}
class Panel extends Shape {
public var position:Vector3D;
public var color:uint;
public var z_value:Number;
public var z_range:Number;
public var enable:Boolean;
}
/**
* 管理体
*/
class Manager extends Sprite{
private var game_work_:GameWork;
private var search_bar_:SearchBar;
private var game_main_:GameMain;
/**
* コンストラクタ
*/
public function Manager() {
game_work_ = new GameWork();
game_work_.search_word_ = GameWork.INIT_WORD;
// ゲームメイン追加
game_main_ = addChild(new GameMain(game_work_)) as GameMain;
// 検索バー追加
search_bar_ = addChild(new SearchBar(game_work_)) as SearchBar;
search_bar_.y = 465 - SearchBar.HEIGHT;
}
/**
* 更新処理
* @return true … 処理中
*/
public function update():Boolean {
if (search_bar_.isUpdate()) {
// 更新があった
game_main_.reloadList();
}
game_main_.update();
return true;
}
}
/**
* 検索バー
*/
class SearchBar extends Sprite {
public static const WIDTH:int = 465;
public static const HEIGHT:int = 25;
// 共通ワーク用
private var game_work_:GameWork;
private var unique_:Boolean = true;
private var status_:TextField;
private var updated_:Boolean;
/**
* コンストラクタ
*/
public function SearchBar(game_work:GameWork) {
game_work_ = game_work;
//ヘッダーのサーチエリア
//背景
var title_area:Shape = addChild(new Shape()) as Shape;
title_area.graphics.beginFill(0x000000);
title_area.graphics.drawRect(0, 0, WIDTH, HEIGHT);
//Serchの文字
var serch_word:TextField = addChild(Utility.createTextField(12, 0xFFFFFF)) as TextField;
serch_word.text = "Serch:";
serch_word.x = 2;
serch_word.y = 2;
//テキスト入力欄。キーボードのキーを押し上げた際にonKeyUpが実行される
var search_box:TextField = addChild(Utility.createTextField(11, 0x000000)) as TextField;
search_box.text = game_work_.search_word_;
search_box.autoSize = TextFieldAutoSize.NONE;
search_box.width = 200;
search_box.height = 18;
search_box.x = 50;
search_box.y = 2;
search_box.border = true;
search_box.borderColor = 0xFFFFFF;
search_box.background = true;
search_box.backgroundColor = 0xC0C0C0;
search_box.type = TextFieldType.INPUT;
search_box.selectable = true;
search_box.addEventListener(KeyboardEvent.KEY_UP, onSearchKeyUp);
// チェックボックスの準備
var check_box:CheckBox = new CheckBox(this, 260, 6, "unique",
function (evt:MouseEvent):void {
unique_ = evt.currentTarget.selected;
});
check_box.selected = unique_;
// 状態表示欄
status_ = addChild(Utility.createTextField(11, 0xFF8080)) as TextField;
status_.text = "";
status_.x = 310;
status_.y = 2;
requestSearch(game_work_.search_word_);
}
/**
* 更新があったか?
* 更新フラグはクリアされる
* @return true 更新があった
*/
public function isUpdate():Boolean {
var ret:Boolean = updated_;
updated_ = false
return ret;
}
/**
* サーチボックスキー判定
*/
private function onSearchKeyUp(evt:KeyboardEvent):void {
var tf:TextField = evt.currentTarget as TextField;
if (evt.keyCode == Keyboard.ENTER) {
if (tf.text.length > 0) {
requestSearch(tf.text);
}
}
}
/**
* 検索リクエスト
*/
private function requestSearch(word:String):void {
var loader:TwitterXmlLoader = new TwitterXmlLoader();
loader.addEventListener(Event.COMPLETE, onLoadSearch);
loader.loadSearchXml(word);
}
/**
* 検索終了処理
*/
private function onLoadSearch(evt:Event):void {
var xml_data:XML = evt.currentTarget.xmlObj;
if (xml_data == null) {
status_.text = "Search Fail.";
return;
}
// 解析開始ー
//namespaceを設定
default xml namespace = new Namespace("http://www.w3.org/2005/Atom");
var entry_size:int = xml_data.entry.length();
if (entry_size <= 0) {
status_.text = "No Articles.";
return;
}
// リスト再構築
game_work_.entry_list_ = new Vector.<EntryData>();
//要素を取り出して、textFieldを作りならべる
for (var i:int = 0; i < entry_size; ++i) {
var entry:EntryData = new EntryData();
//xmlからauthorNameを取得
entry.author_name = xml_data.entry[i].author.name;
// 既に登録されていればはじく
if (unique_) {
if (game_work_.entry_list_.some(
function(item:EntryData, index:int, list:Vector.<EntryData>):Boolean {
return item.author_name == this;
},
entry.author_name)) continue;
}
//xmlからlink,titleの各値を取得
entry.link = xml_data.entry[i].link[0].@href;
entry.uri = xml_data.entry[i].author.uri;
entry.title = xml_data.entry[i].title;
//アイコン画像のURLを取得
entry.img_url = xml_data.entry[i].link[1].@href;
//bmpフォーマットのアイコン画像を使っている人も少なくないため、Flashで使えるファイルの拡張子かどうかを判別
var extention:String = entry.img_url.substr( -4);
extention = extention.toLowerCase();
if (extention != ".jpg" && extention != ".gif" && extention != ".png") {
//Flashで使える画像の拡張子ではなかった場合にはデフォルトアイコンを指定
entry.img_url = "http://a3.twimg.com/sticky/default_profile_images/default_profile_0_normal.png";
}
//画像のファイル名が日本語などの規定外の文字である場合を考慮しエンコードする
entry.img_url = encodeURI(entry.img_url);
game_work_.entry_list_.push(entry);
}
status_.text = "Count: " + game_work_.entry_list_.length.toString();
game_work_.search_word_ = xml_data.title.toString().replace(" - Twitter Search", "");
updated_ = true;
}
}
/**
* ゲームメイン画面
*/
class GameMain extends Sprite {
public static const WIDTH:int = 465;
public static const HEIGHT:int = 440;
private static const STATE_STANDBY:int = 0;
private static const STATE_LOAD:int = 1;
private static const STATE_GAME:int = 2;
private static const STATE_CLEAR:int = 3;
// 共通ワーク
private var game_work_:GameWork;
// ステージ情報
private var stage_entry_:EntryData;
private var entry_index_:int;
private var stage_bmd_:BitmapData;
private var offset_pitch_:Number;
private var offset_head_:Number;
// 結果画面
private var result_icon_:Bitmap;
private var result_message_:ResultMessage;
// パネル表示
private var panel_base_:Sprite;
private var panel_list_:Vector.<Panel>;
private var panel_order_:Vector.<int>;
private var pitch_:Number = 0.0;
private var head_:Number = 0.0;
// デバッグ用
private var status_:TextField;
private var state_:int;
// 座標変換
private var lookat_:Matrix3D;
private var local_:Matrix3D;
private var screen_:Matrix3D;
/**
* コンストラクタ
*/
public function GameMain(game_work:GameWork) {
game_work_ = game_work;
const ICON_SIZE:int = GameWork.ICON_SIZE;
const PANEL_SIZE:Number = GameWork.PANEL_SIZE;
// 背景描画
graphics.beginFill(0x808090);
graphics.drawRect(0, 0, WIDTH, HEIGHT);
graphics.endFill();
// パネル背景
panel_base_ = addChild(new Sprite()) as Sprite;
panel_base_.x = WIDTH / 2.0;
panel_base_.y = HEIGHT / 2.0;
panel_base_.alpha = 0.0;
// パネル生成
const CENTER_OFFSET:Number = PANEL_SIZE * ICON_SIZE * 0.5;
panel_list_ = new Vector.<Panel>(ICON_SIZE * ICON_SIZE, true);
panel_order_ = new Vector.<int>();
for (var y:int = 0; y < ICON_SIZE; ++y) {
for (var x:int = 0; x < ICON_SIZE; ++x) {
var panel:Panel = new Panel();
panel.position = new Vector3D(x * PANEL_SIZE - CENTER_OFFSET, y * PANEL_SIZE - CENTER_OFFSET, 0, 1);
var xy2:Number = panel.position.x * panel.position.x + panel.position.y * panel.position.y;
if (CENTER_OFFSET * CENTER_OFFSET <= xy2) {
continue;
}
panel.z_range = Math.sqrt(CENTER_OFFSET * CENTER_OFFSET - xy2) * 2;
panel_list_[y * ICON_SIZE + x] = panel;
panel_base_.addChild(panel);
panel_order_.push(y * ICON_SIZE + x);
}
}
// ステージにつかうbitmapデータ
stage_bmd_ = new BitmapData(ICON_SIZE, ICON_SIZE);
lookat_ = Utility.createLookAt(
new Vector3D(0, 0, 700, 1),
new Vector3D(0, 0, 0, 1),
new Vector3D(0, 1, 0, 1));
local_ = Utility.createOrtho( -WIDTH * 0.5, WIDTH * 0.5, -HEIGHT * 0.5, HEIGHT * 0.5, 200, 1000);
screen_ = Utility.createViwPort( -WIDTH / 2, -HEIGHT / 2, WIDTH, HEIGHT);
// 状態表示欄
status_ = addChild(Utility.createTextField(12, 0x40c040)) as TextField;
status_.text = "";
status_.x = 2;
status_.y = 2;
// 正解画面
result_icon_ = addChild(new Bitmap()) as Bitmap;
result_icon_.visible = false;
// クリアメッセージ画面
result_message_ = addChild(new ResultMessage()) as ResultMessage;
result_message_.x = WIDTH * 0.5;
result_message_.y = 350;
result_message_.visible = false;
addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
addEventListener(MouseEvent.CLICK, onMouseClick);
state_ = STATE_STANDBY;
}
/**
* 更新処理
* @return true … 処理中
*/
public function update():Boolean {
status_.text = "Head = " + head_ + " / Pitch = " + pitch_;
// Panelの更新
updatePanels();
// クリア判定
if (isClearGame()) {
resultGame();
}
return true;
}
/**
* リストの更新通知
*/
public function reloadList():void {
entry_index_ = 0;
loadAndStart();
}
/**
* マウス移動イベント
*/
private function onMouseMove(evt:MouseEvent):void {
if (state_ == STATE_GAME) {
pitch_ = mouseX / WIDTH;
head_ = mouseY / HEIGHT;
}
}
/**
* マウスクリックイベント
*/
private function onMouseClick(evt:MouseEvent):void {
if (state_ == STATE_CLEAR) {
++entry_index_;
if (entry_index_ >= game_work_.entry_list_.length) {
entry_index_ = 0;
}
// 次のステージへ
loadAndStart();
}
}
/**
* アイコンの読み込み
*/
private function loadAndStart():void {
stage_entry_ = EntryData(game_work_.entry_list_[entry_index_]);
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadIcon);
var loader_context:LoaderContext = new LoaderContext(true);
loader.load(new URLRequest(stage_entry_.img_url), loader_context);
result_icon_.visible = false;
result_message_.visible = false;
state_ = STATE_LOAD;
}
/**
* アイコン読み込みイベント
*/
private function onLoadIcon(evt:Event):void {
var src_bmd:BitmapData = evt.target.content.bitmapData;
var src_bmd_width:int = src_bmd.width;
var src_bmd_height:int = src_bmd.height;
for (var h:int = 0; h < GameWork.ICON_SIZE; ++h) {
for (var w:int = 0; w < GameWork.ICON_SIZE; ++w) {
var src_x:int = w * Number(src_bmd_width) / GameWork.ICON_SIZE;
var src_y:int = h * Number(src_bmd_height) / GameWork.ICON_SIZE;
var color:uint = src_bmd.getPixel(src_x, src_y);
stage_bmd_.setPixel(w, h, color);
}
}
result_icon_.bitmapData = src_bmd;
startGame();
}
/**
* ゲーム開始処理
*/
private function startGame():void {
for (var h:int = 0; h < GameWork.ICON_SIZE; ++h) {
for (var w:int = 0; w < GameWork.ICON_SIZE; ++w) {
var panel:Panel = getPanel(w, h);
if (panel == null) continue;
panel.color = stage_bmd_.getPixel(w, h);
panel.graphics.clear();
panel.graphics.beginFill(panel.color);
panel.graphics.lineStyle(1, 0x000000);
panel.graphics.drawRect(
-GameWork.PANEL_SIZE / 2.0, -GameWork.PANEL_SIZE / 2.0,
GameWork.PANEL_SIZE, GameWork.PANEL_SIZE);
panel.graphics.endFill();
var z_range:Number = panel.z_range; //PANEL_SIZE * ICON_SIZE;
panel.position.z = (Math.random() - 0.5) * z_range;
}
}
// クリアメッセージ登録
result_message_.setName(stage_entry_.author_name, stage_entry_.link);
result_message_.setMessage(stage_entry_.title);
offset_pitch_ = Math.random() * (0.98 - 0.02) + 0.01;
offset_head_ = Math.random() * (0.98 - 0.02) + 0.01;
BetweenAS3.tween(panel_base_, { alpha:1.0 }, null, 0.5).play();
state_ = STATE_GAME;
}
/**
* クリア画面の呼び出し
*/
private function resultGame():void {
head_ = offset_head_;
pitch_ = offset_pitch_;
BetweenAS3.tween(panel_base_, { alpha:0.0 }, null, 1).play();
result_icon_.visible = true;
result_icon_.width = GameWork.ICON_SIZE * GameWork.PANEL_SIZE;
result_icon_.height = GameWork.ICON_SIZE * GameWork.PANEL_SIZE;
result_icon_.x = panel_base_.x - result_icon_.width / 2 - GameWork.PANEL_SIZE / 2;
result_icon_.y = panel_base_.y - result_icon_.width / 2 - GameWork.PANEL_SIZE / 2;
BetweenAS3.tween(result_icon_, { alpha:1.0 }, { alpha:0.0 }, 1).play();
result_message_.visible = true;
BetweenAS3.parallel(
BetweenAS3.tween(result_message_, { scaleX:1 }, { scaleX:0 }, 0.5),
BetweenAS3.tween(result_message_, { scaleY:1 }, { scaleY:0 }, 0.5),
BetweenAS3.tween(result_message_, { alpha:1 }, { alpha:0 }, 0.5)).play();
state_ = STATE_CLEAR;
}
// クリア判定
private function isClearGame():Boolean {
if (state_ != STATE_GAME) return false;
return (new Point(pitch_ - offset_pitch_, head_ - offset_head_)).length < 0.008;
}
/**
* パネル 取得
* @param x icon x座標
* @param y icon y座標
* @return パネル
*/
private function getPanel(x:int, y:int):Panel {
return panel_list_[y * GameWork.ICON_SIZE + x];
}
/**
* パネルの更新
*/
private function updatePanels():void {
var trans:Matrix3D = new Matrix3D();
trans.appendRotation(180 * (pitch_ - offset_pitch_), new Vector3D(0, 1, 0));
trans.appendRotation(180 * (head_ - offset_head_), new Vector3D(1, 0, 0));
trans.append(lookat_);
trans.append(local_);
trans.append(screen_);
for (var h:int = 0; h < GameWork.ICON_SIZE; ++h) {
for (var w:int = 0; w < GameWork.ICON_SIZE; ++w) {
var panel:Panel = getPanel(w, h);
if (panel == null) continue;
var new_pos:Vector3D = trans.transformVector(panel.position);
new_pos.project();
panel.x = new_pos.x;
panel.y = new_pos.y;
panel.z_value = new_pos.z;
}
}
panel_order_.sort(function(l:int, r:int):Number {
return panel_list_[r].z_value - panel_list_[l].z_value;
});
for (var i:int = 0; i < panel_order_.length; ++i) {
panel_base_.setChildIndex(panel_list_[panel_order_[i]], i);
}
}
}
class ResultMessage extends Sprite {
public static const WIDTH:int = 400;
public static const HEIGHT:int = 140;
private var name_:TextField;
private var message_:TextField;
public function ResultMessage() {
// 背景枠
graphics.lineStyle(2, 0xD0FFD0, 0.5);
graphics.beginFill(0x000000, 0.5);
graphics.drawRoundRect(-0.5 * WIDTH, -0.5 * HEIGHT, WIDTH, HEIGHT, 10, 10);
graphics.endFill();
mouseEnabled = false;
name_ = addChild(Utility.createTextField(16, 0xFFD0D0)) as TextField;
name_.htmlText = "";
name_.x = -0.5 * WIDTH + 10;
name_.y = -0.5 * HEIGHT + 5;
message_ = addChild(Utility.createTextField(12, 0xFFFFFF)) as TextField;
message_.text = "";
message_.autoSize = TextFieldAutoSize.NONE;
message_.multiline = true;
message_.wordWrap = true;
message_.width = WIDTH - 40;
message_.height = HEIGHT;
message_.x = -0.5 * WIDTH + 20;
message_.y = -0.5 * HEIGHT + 40;
message_.mouseEnabled = false;
}
/**
* 名前の設定
* @param name 名前
* @param link リンク
*/
public function setName(name:String, link:String = null):void {
if (link) {
name_.htmlText = "<a href=\"" + link + "\">" + name + "</a>";
}
else {
name_.htmlText = name;
}
}
/**
* メッセージ本文
* @param msg
*/
public function setMessage(msg:String):void {
message_.text = msg;
}
}
/**
* Twitter情報読み込み
*/
class TwitterXmlLoader extends EventDispatcher {
private var xmlLoader_:URLLoader;
private var standby_:Boolean;
public var xmlObj:XML;
/**
* コンストラクタ
*/
function TwitterXmlLoader() {
//URLLoader作成
xmlLoader_ = new URLLoader();
//読み込み完了イベントのイベントリスナーになる
xmlLoader_.addEventListener(Event.COMPLETE, onXMLloaded);
xmlLoader_.addEventListener(IOErrorEvent.IO_ERROR, onIoError);
standby_ = true;
}
/**
* 読み込み完了
*/
private function onXMLloaded(evt:Event):void {
//XMLオブジェクトに変換する
xmlObj = new XML(xmlLoader_.data);
//カスタムイベントを配信する
dispatchEvent(new Event(Event.COMPLETE));
standby_ = true;
}
/**
* エラー処理
*/
private function onIoError(evt:IOErrorEvent):void {
standby_ = true;
}
/**
* ユーザー情報取得
* @param user 対象のユーザー名
*/
public function loadSearchXml(search_word:String):Boolean {
if (! standby_) return false;
//URL
var xmlUrl:String = "http://search.twitter.com/search.atom?rpp=100&q=";
xmlUrl += encodeURIComponent(search_word);
//読み込み開始
xmlLoader_.load(new URLRequest(xmlUrl));
standby_ = false;
return true;
}
}
/**
* 汎用処理
*/
class Utility {
/**
* テキストフィールドの生成
* @param size フォントサイズ
* @param color フォントカラー
* @param align アライン
* @return テキストフィールドインスタンス
*/
public static function createTextField(
size:int, color:int,
align:String = TextFormatAlign.LEFT):TextField {
var tf:TextField = new TextField();
tf.defaultTextFormat = new TextFormat("Arial", size, color, true, null, null, null, null, align);
tf.autoSize = TextFieldAutoSize.LEFT;
tf.selectable = false;
return tf;
}
/**
* 正射影行列を得る。
*/
public static function createOrtho(
left:Number, right:Number, bottom:Number, top:Number, near:Number, far:Number):Matrix3D {
var div_r_l:Number = 1.0 / (right - left);
var div_t_b:Number = 1.0 / (top - bottom);
var div_n_f:Number = 1.0 / (near - far);
var raw_data:Vector.<Number> = new Vector.<Number>(16);
raw_data[0 * 4 + 0] = 2.0 * div_r_l;
raw_data[1 * 4 + 1] = 2.0 * div_t_b;
raw_data[2 * 4 + 2] = 2.0 * div_n_f;
raw_data[3 * 4 + 0] = -(right + left) * div_r_l;
raw_data[3 * 4 + 1] = -(top + bottom) * div_t_b;
raw_data[3 * 4 + 2] = (near * far) * div_n_f;
raw_data[3 * 4 + 3] = 1.0;
return new Matrix3D(raw_data);
}
/**
* LookAt行列を得る。
* @param eye 視点ポジション
* @param target 注視ポジション
* @param up カメラ上方
* @return LookAt行列
*/
static public function createLookAt(
eye:Vector3D, target:Vector3D, up:Vector3D):Matrix3D {
var d0:Number, d1:Number, d2:Number;
var r0:Vector3D, r1:Vector3D, r2:Vector3D;
var n_eye:Vector3D;
r2 = eye.subtract(target);
r2.normalize();
r0 = up.crossProduct(r2);
r0.normalize();
r1 = r2.crossProduct(r0);
n_eye = eye.clone();
n_eye.scaleBy( -1.0);
d0 = r0.dotProduct(n_eye);
d1 = r1.dotProduct(n_eye);
d2 = r2.dotProduct(n_eye);
var raw_data:Vector.<Number> = new Vector.<Number>(16);
raw_data[0] = r0.x; raw_data[1] = r1.x; raw_data[2] = r2.x;
raw_data[4] = r0.y; raw_data[5] = r1.y; raw_data[6] = r2.y;
raw_data[8] = r0.z; raw_data[9] = r1.z; raw_data[10] = r2.z;
raw_data[12] = d0; raw_data[13] = d1;
raw_data[14] = d2; raw_data[15] = 1.0;
return new Matrix3D(raw_data);
}
/**
* スクリーン行列の作成
* @param x 左上オフセット
* @param y 左上オフセット
* @param w 幅
* @param h 高さ
* @return スクリーン行列
*/
static public function createViwPort(
x:Number, y:Number, w:Number, h:Number): Matrix3D {
var w2:Number = w * 0.5;
var h2:Number = h * 0.5;
var raw_data:Vector.<Number> = new Vector.<Number>(16);
raw_data[0] = w2;
raw_data[5] = h2;
raw_data[10] = 1000;
raw_data[12] = x + w2;
raw_data[13] = y + h2;
raw_data[14] = 0;
raw_data[15] = 1;
return new Matrix3D(raw_data);
}
}