前回の第21回
立方体に上面と底面を加える
前回は、

そして、

function getFacesVertices() {
var vertices = [
new Face(0, 1, 2, 3, getRandomColor()),
new Face(1, 5, 6, 2, getRandomColor()),
new Face(4, 0, 3, 7, getRandomColor()),
new Face(4, 5, 1, 0, getRandomColor()), // 上面
new Face(6, 7, 3, 2, getRandomColor()), // 底面
new Face(5, 4, 7, 6, getRandomColor())
];
return vertices;
}
x軸とy軸の回転を扱う準備
いきなりx軸で回す前に、
var angle = new createjs.Point();
// var stageCenterX;
var stageCenter = new createjs.Point();
function initialize() {
var canvasElement = document.getElementById("myCanvas");
stage = new createjs.Stage(canvasElement);
// stageCenterX = canvasElement.width / 2;
stageCenter.x = canvasElement.width / 2;
stageCenter.y = canvasElement.height / 2;
// drawGraphics = createGraphics(stageCenterX, canvasElement.height / 2);
drawGraphics = createGraphics(stageCenter.x, stageCenter.y);
createjs.Ticker.addEventListener("tick", rotate);
stage.addEventListener("stagemousemove", setAngle);
}
function setAngle(eventObject) {
var mouseX = eventObject.stageX;
// angle = (mouseX - stageCenterX) * 1 / 300;
angle.y = (mouseX - stageCenter.x) / 300;
}
function rotate(eventObject) {
// matrix.identity().rotate(angle);
matrix.identity().rotate(angle.y);
}
前述のとおり、

var stage;
var drawGraphics;
var points;
var angle = new createjs.Point();
var matrix = new createjs.Matrix2D();
var stageCenter = new createjs.Point();
var _point = new createjs.Point();
var points2D = [];
var facesVertices;
var focalLength = 300;
function initialize() {
var canvasElement = document.getElementById("myCanvas");
stage = new createjs.Stage(canvasElement);
stageCenter.x = canvasElement.width / 2;
stageCenter.y = canvasElement.height / 2;
drawGraphics = createGraphics(stageCenter.x, stageCenter.y);
points = createCubePoints(50);
facesVertices = getFacesVertices();
drawFaces(points, facesVertices);
createjs.Ticker.addEventListener("tick", rotate);
stage.addEventListener("stagemousemove", setAngle);
}
function setAngle(eventObject) {
var mouseX = eventObject.stageX;
angle.y = (mouseX - stageCenter.x) / 300;
}
function rotate(eventObject) {
var count = points.length;
points2D.length = 0;
matrix.identity().rotate(angle.y);
for (var i = 0; i < count; i++) {
var point = points[i];
matrix.transformPoint(point.x, point.z, _point);
point.x = _point.x;
point.z = _point.y;
points2D[i] = point.getProjetedPoint(focalLength);
}
drawFaces(points2D, facesVertices);
}
function drawFaces(points, faces) {
var numFaces = faces.length;
drawGraphics.clear();
for (var i = 0; i < numFaces; i++) {
var face = faces[i];
var facePoints = face.getFacePoints(points);
if (isFront(facePoints)) {
draw(facePoints, face.color);
}
}
stage.update();
}
function isFront(facePoints) {
var origin = facePoints[0];
var point0 = MathUtils.subtractVectors(origin, facePoints[1]);
var point1 = MathUtils.subtractVectors(origin, facePoints[2]);
return (0 <= MathUtils.crossProduct2D(point0, point1));
}
function draw(points, color) {
var count = points.length;
var point = points[count - 1];
drawGraphics
.beginFill(color)
.moveTo(point.x, point.y);
for (var i = 0; i < count; i++) {
point = points[i];
drawGraphics.lineTo(point.x, point.y);
}
}
function createGraphics(x, y) {
var drawShape = new createjs.Shape();
drawShape.x = x;
drawShape.y = y;
stage.addChild(drawShape);
return drawShape.graphics;
}
function createCubePoints(halfEdge) {
var cubePoints = [
new Point3D(-halfEdge, -halfEdge, -halfEdge),
new Point3D(halfEdge, -halfEdge, -halfEdge),
new Point3D(halfEdge, halfEdge, -halfEdge),
new Point3D(-halfEdge, halfEdge, -halfEdge),
new Point3D(-halfEdge, -halfEdge, halfEdge),
new Point3D(halfEdge, -halfEdge, halfEdge),
new Point3D(halfEdge, halfEdge, halfEdge),
new Point3D(-halfEdge, halfEdge, halfEdge)
];
return cubePoints;
}
function getFacesVertices() {
var vertices = [
new Face(0, 1, 2, 3, getRandomColor()),
new Face(1, 5, 6, 2, getRandomColor()),
new Face(4, 0, 3, 7, getRandomColor()),
new Face(4, 5, 1, 0, getRandomColor()),
new Face(6, 7, 3, 2, getRandomColor()),
new Face(5, 4, 7, 6, getRandomColor())
];
return vertices;
}
function getRandomColor() {
return createjs.Graphics.getRGB(Math.floor(MathUtils.getRandomInt(0, 0xFFFFFF)));
}
立方体をx軸でも回す
いよいよ、

3次元空間座標をxy両軸で回すなら、
Point3DオブジェクトrotatePoint(Matrix2Dオブジェクト, 回転軸)
例によって、
立方体を回すTicker.
// var matrix = new createjs.Matrix2D();
var matrixX = new createjs.Matrix2D();
var matrixY = new createjs.Matrix2D();
// var _point = new createjs.Point();
function setAngle(eventObject) {
var mouseX = eventObject.stageX;
var mouseY = eventObject.stageY;
angle.y = (mouseX - stageCenter.x) / 300;
angle.x = (mouseY - stageCenter.y) / -300;
}
function rotate(eventObject) {
var count = points.length;
points2D.length = 0;
// matrix.identity().rotate(angle.y);
matrixY.identity().rotate(angle.y);
matrixX.identity().rotate(angle.x);
for (var i = 0; i < count; i++) {
var point = points[i];
/*
matrix.transformPoint(point.x, point.z, _point);
point.x = _point.x;
point.z = _point.y;
*/
point.rotatePoint(matrixY, "y");
point.rotatePoint(matrixX, "x");
points2D[i] = point.getProjetedPoint(focalLength);
}
drawFaces(points2D, facesVertices);
}
改めて、
Point3D._point = new createjs.Point();
Point3D.prototype.rotatePoint = function(matrix, axis) {
if (axis == "y") {
matrix.transformPoint(this.x, this.z, Point3D._point);
this.x = Point3D._point.x;
this.z = Point3D._point.y;
} else if (axis == "x") {
matrix.transformPoint(this.z, this.y, Point3D._point);
this.z = Point3D._point.x;
this.y = Point3D._point.y;
}
};
これらの手を加えれば、


// Point3D
function Point3D(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
Point3D._point = new createjs.Point();
Point3D.prototype.getProjetedPoint = function(focalLength) {
var point2D = new createjs.Point();
var w = focalLength / (focalLength + this.z);
point2D.x = this.x * w;
point2D.y = this.y * w;
return point2D;
};
Point3D.prototype.rotatePoint = function(matrix, axis) {
if (axis == "y") {
matrix.transformPoint(this.x, this.z, Point3D._point);
this.x = Point3D._point.x;
this.z = Point3D._point.y;
} else if (axis == "x") {
matrix.transformPoint(this.z, this.y, Point3D._point);
this.z = Point3D._point.x;
this.y = Point3D._point.y;
}
};
// Face
function Face(pos0, pos1, pos2, pos3, color) {
this.length = 4;
this.color = color;
this[0] = pos0;
this[1] = pos1;
this[2] = pos2;
this[3] = pos3;
}
Face.prototype.getFacePoints = function (points) {
var faces = this.length;
var facePoints = [];
for (var i = 0; i < faces; i++) {
facePoints[i] = points[this[i]];
}
return facePoints;
};
// MathUtils
var MathUtils = {};
MathUtils.getRandomInt = function(min, max) {
if (min > max) {
var temp = min;
min = max;
max = temp;
}
var randomNumber = Math.random() * (max - min) + min;
return Math.floor(randomNumber);
};
MathUtils.subtractVectors = function(vector0, vector1) {
var vectorX = vector1.x - vector0.x;
var vectorY = vector1.y - vector0.y;
return new createjs.Point(vectorX, vectorY);
};
MathUtils.crossProduct2D = function(vector0, vector1) {
return vector0.x * vector1.y - vector0.y * vector1.x;
}
var stage;
var drawGraphics;
var points;
var angle = new createjs.Point();
var matrixX = new createjs.Matrix2D();
var matrixY = new createjs.Matrix2D();
var stageCenter = new createjs.Point();
var points2D = [];
var facesVertices;
var focalLength = 300;
function initialize() {
var canvasElement = document.getElementById("myCanvas");
stage = new createjs.Stage(canvasElement);
stageCenter.x = canvasElement.width / 2;
stageCenter.y = canvasElement.height / 2;
drawGraphics = createGraphics(stageCenter.x, stageCenter.y);
points = createCubePoints(50);
facesVertices = getFacesVertices();
drawFaces(points, facesVertices);
createjs.Ticker.addEventListener("tick", rotate);
stage.addEventListener("stagemousemove", setAngle);
}
function setAngle(eventObject) {
var mouseX = eventObject.stageX;
var mouseY = eventObject.stageY;
angle.y = (mouseX - stageCenter.x) / 300;
angle.x = (mouseY - stageCenter.y) / -300;
}
function rotate(eventObject) {
var count = points.length;
points2D.length = 0;
matrixY.identity().rotate(angle.y);
matrixX.identity().rotate(angle.x);
for (var i = 0; i < count; i++) {
var point = points[i];
point.rotatePoint(matrixY, "y");
point.rotatePoint(matrixX, "x"); //
points2D[i] = point.getProjetedPoint(focalLength);
}
drawFaces(points2D, facesVertices);
}
function drawFaces(points, faces) {
var numFaces = faces.length;
drawGraphics.clear();
for (var i = 0; i < numFaces; i++) {
var face = faces[i];
var facePoints = face.getFacePoints(points);
if (isFront(facePoints)) {
draw(facePoints, face.color);
}
}
stage.update();
}
function isFront(facePoints) {
var origin = facePoints[0];
var point0 = MathUtils.subtractVectors(origin, facePoints[1]);
var point1 = MathUtils.subtractVectors(origin, facePoints[2]);
return (0 <= MathUtils.crossProduct2D(point0, point1));
}
function draw(points, color) {
var count = points.length;
var point = points[count - 1];
drawGraphics
.beginFill(color)
.moveTo(point.x, point.y);
for (var i = 0; i < count; i++) {
point = points[i];
drawGraphics.lineTo(point.x, point.y);
}
}
function createGraphics(x, y) {
var drawShape = new createjs.Shape();
drawShape.x = x;
drawShape.y = y;
stage.addChild(drawShape);
return drawShape.graphics;
}
function createCubePoints(halfEdge) {
var cubePoints = [
new Point3D(-halfEdge, -halfEdge, -halfEdge),
new Point3D(halfEdge, -halfEdge, -halfEdge),
new Point3D(halfEdge, halfEdge, -halfEdge),
new Point3D(-halfEdge, halfEdge, -halfEdge),
new Point3D(-halfEdge, -halfEdge, halfEdge),
new Point3D(halfEdge, -halfEdge, halfEdge),
new Point3D(halfEdge, halfEdge, halfEdge),
new Point3D(-halfEdge, halfEdge, halfEdge)
];
return cubePoints;
}
function getFacesVertices() {
var vertices = [
new Face(0, 1, 2, 3, getRandomColor()),
new Face(1, 5, 6, 2, getRandomColor()),
new Face(4, 0, 3, 7, getRandomColor()),
new Face(4, 5, 1, 0, getRandomColor()),
new Face(6, 7, 3, 2, getRandomColor()),
new Face(5, 4, 7, 6, getRandomColor())
];
return vertices;
}
function getRandomColor() {
return createjs.Graphics.getRGB(Math.floor(MathUtils.getRandomInt(0, 0xFFFFFF)));
}
第20回から3回にわたって取り組んできたお題は、