今回から、
といっても、
もっとも、
お題の説明と準備
本論に入る前に、
けれど、
今回採上げるベクトルの内積では、
第48回スクリプト2は、
まず準備として、
ベクトルの内積から面の向きがわかる
ベクトルは方向をもった大きさで、
つまり、
3次元空間のベクトルを表すために、
| ベクトル | 座標 | 
|---|---|
| 視線 | (0, 0, 1) | 
| 面(初期値) | (0, 0, -1) | 
そして、
| 面の向き | ふたつのベクトルのなす角 | 内積の符号 | 
|---|---|---|
| 裏 | 90度より小さい | +(正) | 
| 真横 | 90度 | 0 | 
| 表 | 90度より大きい | -(負) | 
ここまでくれば、
- Vector3Dオブジェクト.dotProduct
(もうひとつのVector3Dオブジェクト)  
面の表と裏を塗替える
では、
第2は、
今回3次元空間の頂点座標は動かさない。変換のMatrix3Dオブジェクトに回転を加えて、
その結果のオブジェクトを変数 (worldMatrix3D) に残す。つまり、 座標ではなく変換行列で座標変換を管理するのだ。 
したがって、
// フレームアクションに追加
var viewVector3D:Vector3D = Vector3D.Z_AXIS;   // 視線のベクトル
var faceVector3D:Vector3D = new Vector3D(0, 0, -1);   // 面のベクトル
function xRotate(eventObject:Event):void {
  var nRotationY:Number = mySprite.mouseX * nDeceleration;
  var vertices2D:Vector.<Number> = new Vector.<Number>();
  xTransform(vertices2D, nRotationY);
  var bFront:Boolean = xIsFront(faceVector3D, worldMatrix3D);  // 面の表裏を調べる
  trace(bFront);  // 確認用
  xDraw(vertices2D);
}
// 面の表裏を調べる関数の定義
function xIsFront(myVector3D:Vector3D, myMatrix3D:Matrix3D):Boolean {
  var directionVector3D:Vector3D = myMatrix3D.transformVector(myVector3D);
  var bFront:Boolean = (viewVector3D.dotProduct(directionVector3D) < 0);
  return bFront;
}
面の表裏を調べる関数
それでは、
第2に、
そして第3に、
// フレームアクションに追加
var backTexture:BitmapData = new Image2();   // 追加
function xRotate(eventObject:Event):void {
  var nRotationY:Number = mySprite.mouseX * nDeceleration;
  var vertices2D:Vector.<Number> = new Vector.<Number>();
  xTransform(vertices2D, nRotationY);
  var bFront:Boolean = xIsFront(faceVector3D, worldMatrix3D);
  // trace(bFront);  // 確認用
  // xDraw(vertices2D);
  xDraw(vertices2D, bFront);
}
// function xDraw(vertices2D:Vector.<Number>):void {
function xDraw(vertices2D:Vector.<Number>, bFront:Boolean):void {
  var texture:BitmapData = bFront ? myTexture : backTexture;   // 追加
  myGraphics.clear();
  // myGraphics.beginBitmapFill(myTexture);
  myGraphics.beginBitmapFill(texture);
  myGraphics.drawTriangles(vertices2D, indices, uvtData);
  myGraphics.endFill();
}
修正し終えたフレームアクション全体を、
// フレームアクション
var nUnit:Number = 100 / 2;
var mySprite:Sprite = new Sprite();
var myTexture:BitmapData = new Image();
var backTexture:BitmapData = new Image2();
var viewVector3D:Vector3D = Vector3D.Z_AXIS;
var faceVector3D:Vector3D = new Vector3D(0, 0, -1);
var vertices:Vector.<Number> = new Vector.<Number>();
var indices:Vector.<int> = new Vector.<int>();
var uvtData:Vector.<Number> = new Vector.<Number>();
var nDeceleration:Number = 0.3;
var myGraphics:Graphics = mySprite.graphics;
var myPerspective:PerspectiveProjection = transform.perspectiveProjection;
var worldMatrix3D:Matrix3D = new Matrix3D();
var viewMatrix3D:Matrix3D = myPerspective.toMatrix3D();
viewMatrix3D.prependTranslation(0, 0, myPerspective.focalLength);
mySprite.x = stage.stageWidth / 2;
mySprite.y = stage.stageHeight / 2;
vertices.push(-nUnit, -nUnit, 0);
vertices.push(nUnit, -nUnit, 0);
vertices.push(nUnit, nUnit, 0);
vertices.push(-nUnit, nUnit, 0);
indices.push(0, 1, 3);
indices.push(1, 2, 3);
uvtData.push(0, 0, 0);
uvtData.push(1, 0, 0);
uvtData.push(1, 1, 0);
uvtData.push(0, 1, 0);
addChild(mySprite);
addEventListener(Event.ENTER_FRAME, xRotate);
function xRotate(eventObject:Event):void {
  var nRotationY:Number = mySprite.mouseX * nDeceleration;
  var vertices2D:Vector.<Number> = new Vector.<Number>();
  xTransform(vertices2D, nRotationY);
  var bFront:Boolean = xIsFront(faceVector3D, worldMatrix3D);
  xDraw(vertices2D, bFront);
}
function xTransform(vertices2D:Vector.<Number>, myRotation:Number):void {
  worldMatrix3D.prependRotation(myRotation, Vector3D.Y_AXIS);
  var myMatrix3D:Matrix3D = worldMatrix3D.clone();
  myMatrix3D.append(viewMatrix3D);
  Utils3D.projectVectors(myMatrix3D, vertices, vertices2D, uvtData);
}
function xDraw(vertices2D:Vector.<Number>, bFront:Boolean):void {
  var texture:BitmapData = bFront ? myTexture : backTexture;
  myGraphics.clear();
  myGraphics.beginBitmapFill(texture);
  myGraphics.drawTriangles(vertices2D, indices, uvtData);
  myGraphics.endFill();
}
function xIsFront(myVector3D:Vector3D, myMatrix3D:Matrix3D):Boolean {
  var directionVector3D:Vector3D = myMatrix3D.transformVector(myVector3D);
  var bFront:Boolean = (viewVector3D.dotProduct(directionVector3D) < 0);
  return bFront;
}
ベクトルの内積を数学的に理解する
ベクトルの内積について、
ベクトルAとBの内積は、
A・
B = |A||B|cosθ A||B| > 0 (|A|≠0、
|B|≠0とする) A・
B = axbx + ayby A・
B = axbx + ayby + azbz - スクリプト1のサンプルファイル
(CS5形式/約61KB)  
ベクトルAとBの始点を結んだとき、
ベクトルAとBの絶対値は、
つまり、
内積は、
3次元空間のベクトルA
次回は、
今回解説した次のサンプルファイルがダウンロードできます。
