Показать сообщение отдельно
Старый 17.05.2010, 15:27
KIVagant вне форума Посмотреть профиль Отправить личное сообщение для KIVagant Найти все сообщения от KIVagant
  № 1  
Ответить с цитированием
KIVagant

Регистрация: May 2009
Сообщений: 34
Question Away + jiglib: как заставить куб упасть нужной стороной кверху?

Здравствуйте, уважаемые эксперты.

Возникла необходимость сделать небольшую анимацию с падающими кубами. Цель в том, чтобы некоторое множество кубиков начали падать с высоты, отображаясь изначально стороной А к камере, а затем после падения перевернулись вверх стороной Х.

Я нашел реализацию, близкую к тому, что мне нужно. Для реализации полета кубов был использован Away3D + Jiglib. Немного разобравшись с кодом, я смог добиться некоторых успехов. Но возникает два вопроса, которые я не могу решить, т.к. не соображаю в трехмерной графике и тем более, движках.

1. Почему некоторые кубы падают сквозь плоскость? Как этого избежать? Рисовать несколько плоскостей друг под другом, "затормаживая" движение (обход бага)? При чем чем быстрее скорость и больше количество кубов, тем больше они проваливаются.

2. Как заставить кубики упасть нужной стороной вверх? Для этого я определил углы поворота для каждой из сторон (использую их при отправной точке полета). Думая над этой проблемой, я вижу два решения:
I) Заставить кубики катиться, прорисовывая анимацию. Абсолютно не представляю, как это сделать. Мне даже не удалось просто насильно передвинуть кубик по какой-нибудь траектории.
II) "Прикрепить" к нужной грани каждого куба (внутри него) "утяжелитель" - некий объект, масса которого создаст эффект неваляшки. Объект должен быть достаточно тяжелым и находиться с некоторым смещением от центра нужной грани, например так:
ооооооо
оооохоо
ооооооо
ооооооо
То есть, у куба будет смещенный центр тяжести, который заставит его перевернуться в нужную сторону. При этом он, конечно, может "хромать" при анимации, но это не критично.
Но опять же, я не представляю, как присоединить к существующему объекту ещё объект, чтобы они двигались неотрывно друг от друга. Я так понимаю, это нужно создавать другую модель, не куб.

Вот код, на который я опираюсь (используется слегка устаревший away3d для совместимости с jiglib):
Код AS3:
import away3d.cameras.*;
import away3d.containers.*;
import away3d.materials.*;
import away3d.primitives.*
import away3d.lights.DirectionalLight3D
 
import jiglib.physics.RigidBody;
import jiglib.plugin.away3d.Away3DPhysics;
import jiglib.plugin.away3d.Away3dMesh;
import jiglib.math.JNumber3D
 
import flash.utils.*; // Временно
 
var scene:Scene3D;
var camera:HoverCamera3D;
var view:View3D;
var light:DirectionalLight3D;
var physics:Away3DPhysics;
var speed:Number = 8; // Скорость физического движка
 
var boxWidth:Number = 400; // Ширина коробочки по X
var boxHeight:Number = 65; // Глубина коробочки по Z
var boxDepth:Number = 400; // Длина коробочки по Y
var boxThickness:Number = 0.5; // Ширина границ
 
var cubeTextures:Array = [ new WireColorMaterial(0xFF4444), //Куб
						   new WireColorMaterial(0x44FF44),
						   new WireColorMaterial(0x4444FF),
						   new WireColorMaterial(0xFFFF44),
						   new WireColorMaterial(0x44FFFF),
						   new WireColorMaterial(0xFF44FF) ]
var wallTexture:WireColorMaterial = new WireColorMaterial(0xFFFFFF); // Текстура стенок
var groundTexture:WireColorMaterial = new WireColorMaterial(0xFFFFFF); // Фон доски
var backgroundTexture:WireColorMaterial = new WireColorMaterial(0x000000); // Задний план
 
var cubeScale:Number = 15; // Размер кубиков
var cubes:Array = new Array()
var cubeMaxLinVel = 30; // Максимальная скорость линейного движения (не уверен)
var cubeMaxRotVel = 20; // Максимальная скорость вращения объекта (не уверен)
var flyHeight:Number = cubeScale*5+200; // Регулятор высоты полета
var cubeMass:Number = 10; // Масса кубика, влияет на скорость полета
// Стороны
var cubeNumbersRotation:Array = new Array();
cubeNumbersRotation[1] = new Array(0, 0, 90); //сторона 1
cubeNumbersRotation[2] = new Array(90, 90, 0); //сторона 2
cubeNumbersRotation[3] = new Array(270, 0, 270); //сторона 3
cubeNumbersRotation[4] = new Array(90, 0, 0);//сторона 4
cubeNumbersRotation[5] = new Array(0, 0, 0); //сторона 5
cubeNumbersRotation[6] = new Array(0, 0, 180); //сторона 6 (180, 0, 0)
var startSide = 1; // Какой стороной вверх начинать полет
var stopSide = 5; // Какой стороной вверх приземлиться (<<<<<<<<<<<<<<<<< как?)
 
function initAway3D():void {
	scene = new Scene3D();
 
	camera = new HoverCamera3D();
	camera.distance = 400; // Дистанция к объекту внимания
	camera.moveCamera(); // Надо подвинуть камеру после установки дистанции
	// Освещение
	light = new DirectionalLight3D({color:0xAAFFAA, ambient:0.25, diffuse:0.75, specular:0.9})
	scene.addChild(light)
 
	view=new View3D({scene:scene,camera:camera});
	view.x=stage.stageWidth/2; // Координаты расположения картинки
	view.y=stage.stageHeight/2; // Координаты расположения картинки
	addChild(view);
 
	physics = new Away3DPhysics(view,speed); // Старт физического движка
}
 
function createWalls():void { // Ограничиваем пространства для падения кубов, чтобы не выпадали
	//стенка
	var left:RigidBody = physics.createCube({width:boxThickness, height:boxHeight, depth:boxDepth+0.5});
	left.movable = false;
	left.x = -(boxWidth+boxThickness)/2
	Away3dMesh(left.skin).mesh.material = wallTexture
	//стенка
	var right:RigidBody = physics.createCube({width:boxThickness, height:boxHeight, depth:boxDepth+0.5});
	right.movable = false;
	right.x = (boxWidth+boxThickness)/2
	Away3dMesh(right.skin).mesh.material = wallTexture
	//стенка
	var front:RigidBody = physics.createCube({width:boxWidth, height:boxHeight, depth:boxThickness});
	front.movable = false;
	front.z =  (boxDepth+boxThickness)/2
	Away3dMesh(front.skin).mesh.material = wallTexture
	//стенка
	var back:RigidBody = physics.createCube({width:boxWidth, height:boxHeight, depth:boxThickness});
	back.movable = false;
	back.z = -(boxDepth+boxThickness)/2
	Away3dMesh(back.skin).mesh.material = wallTexture
	//пол
	var ground:RigidBody = physics.createCube({width:boxWidth, height:boxThickness, depth:boxDepth, segmentsW:2, segmentsH:2});
	ground.movable = false;
	ground.y = -(boxHeight+boxThickness)/2
	Away3dMesh(ground.skin).mesh.material = groundTexture
	Away3dMesh(ground.skin).mesh.pushback = true
}
function createBackground():void {
	var ground:RigidBody = physics.createCube({width:960, height:1, depth:960, segmentsW:2, segmentsH:2});
	ground.movable = false;
	ground.y = -(boxHeight+boxThickness)/2 - 10; // На 1 меньше, чем пол у пространства
	Away3dMesh(ground.skin).mesh.material = backgroundTexture;
	Away3dMesh(ground.skin).mesh.pushback = true; // отталкивать кубики
}
function createCube():void {
	var cube:RigidBody = physics.createCube({width:cubeScale, height:cubeScale, depth:cubeScale});
	cube.y=500;
	cube.movable=false;
	cube.mass = cubeMass;
	cube.maxRotVelocities = cubeMaxRotVel;
	cube.maxLinVelocities = cubeMaxLinVel;
	Cube(Away3dMesh(cube.skin).mesh).cubeMaterials.left = cubeTextures[0]
	Cube(Away3dMesh(cube.skin).mesh).cubeMaterials.right = cubeTextures[1]
	Cube(Away3dMesh(cube.skin).mesh).cubeMaterials.front = cubeTextures[2]
	Cube(Away3dMesh(cube.skin).mesh).cubeMaterials.back = cubeTextures[3]
	Cube(Away3dMesh(cube.skin).mesh).cubeMaterials.top = cubeTextures[4]
	Cube(Away3dMesh(cube.skin).mesh).cubeMaterials.bottom = cubeTextures[5]
	cubes.push(cube);
}
function resetAllCubesE(e:Event):void
{
	resetAllCubes();
}
function resetAllCubes():void {
	for(var i:int = 0; i<cubes.length; i++) {
		cubes[i].movable=true; // Разрешаем движение
		cubes[i].moveTo( new JNumber3D( i*(Math.random()*15)*(Math.random()*-1), flyHeight + i*(cubeScale*3) , i*(Math.random()*15)*(Math.random()*-1) ) ) // перемещаем по X, Z (высота полета) и Y
		cubes[i].rotationX = cubeNumbersRotation[startSide][0];
		cubes[i].rotationY = cubeNumbersRotation[startSide][1];
		cubes[i].rotationZ = cubeNumbersRotation[startSide][2];
	}
}
function initListeners():void {
	stage.addEventListener(Event.ENTER_FRAME, render);
	stage.addEventListener(MouseEvent.MOUSE_DOWN,resetAllCubesE)
}
function render( e:Event ):void {
	view.render();
	camera.targetpanangle = stage.mouseX/stage.stageWidth*360
	camera.targettiltangle = stage.mouseY/stage.stageHeight*30
	//camera.hover(); // Активация движения камеры мышью
	camera.x = 200;
	camera.z = 300;
	camera.y = 360
	physics.step();
 
	light.x = camera.x
	light.y = camera.y
	light.z = camera.z
}
initAway3D();
createBackground();
createWalls();
createCube();
createCube();
createCube();
createCube();
createCube();
createCube();
createCube();
initListeners();
Во вложении - fla-файл.

Заранее благодарю откликнувшихся за помощь.
Вложения
Тип файла: rar 3D Fly Cubes.rar (317.9 Кб, 228 просмотров)