Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   API приложений и сред (http://www.flasher.ru/forum/forumdisplay.php?f=61)
-   -   Away + jiglib: как заставить куб упасть нужной стороной кверху? (http://www.flasher.ru/forum/showthread.php?t=139995)

KIVagant 17.05.2010 15:27

Away + jiglib: как заставить куб упасть нужной стороной кверху?
 
Вложений: 1
Здравствуйте, уважаемые эксперты. :umnik2:

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

Я нашел реализацию, близкую к тому, что мне нужно. Для реализации полета кубов был использован 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-файл.

Заранее благодарю откликнувшихся за помощь.

KIVagant 17.05.2010 19:20

Таакс, кажется мне удалось связать два куба вместе. Сейчас попробую к каждому из кубов прилепить на какую-нибудь грань другой маленький и тяжелый объект... Посмотрим, чего из этого получится...

UPD: Нащупал два варианта связки объектов.
1. С помощью JConstraintPoint.
2. С помощью HingeJoint.

В обоих случаях добиться вменяемого результата не удаётся, т.к. они связываются не жестко и двигаются как на резинке.
Секрет знает Limeflash в теме, но пока что этот полезный человек прячется от широкой общественности :)

Alex Lexcuk 19.05.2010 02:56

Вложений: 1
Ради прикола по тутору на своем же сайте сделал такуб анимашку с кубом, потратил минут 10 на втыкание в свой же контент, а пофиг чего анимировать кости персоонажа или кубы, один фиг работает.
ЗЫ: Blender рулит

KIVagant 19.05.2010 03:15

Alex Lexcuk, близко к теме, но это не совсем то, о чем я говорил или я просто не вижу в приложенном файле необходимой реализации.
Если я не прав - поправьте меня.

Насколько я вижу, это лишь анимация — то есть куб всегда летит строго по одной и той же траектории? Меня интересует вариант, который во вложении к теме - то есть кубы падают всегда по-разному. Но останавливаться должны одной стороной вверх.

Добавлено через 9 минут
Я нашел примеры использования Papervision плюс JigLib.
Там есть пример «Interactive boxes». В этом примере падает несколько кубов на плоскость. Отдельный куб можно захватить, включается привязка к мыши:
Код AS3:

mouseConstraint = new MouseConstraint(event.displayObject3D, new Number3D(0, 0, 1), camera, viewport);

Захватываем мышью куб за одну из граней, протаскиваем по плоскости и затем тянем вниз, прижимая его к "земле". Куб практически всегда ложиться одной и той же стороной вверх, так как мышь его сильно прижимает вниз.

Как это повторить, но вместо мыши кодом привязать какой-нибудь другой объект, чтобы он тянул куб вниз?

Alex Lexcuk 22.05.2010 21:00

Вложений: 1
Цитата:

Сообщение от KIVagant (Сообщение 909214)
Захватываем мышью куб за одну из граней, протаскиваем по плоскости и затем тянем вниз, прижимая его к "земле". Куб практически всегда ложиться одной и той же стороной вверх, так как мышь его сильно прижимает вниз.

Как это повторить, но вместо мыши кодом привязать какой-нибудь другой объект, чтобы он тянул куб вниз?

Кубы простые геометрические тела и можно поступить так - кидаем кубы но в память, методом
Код AS3:

physic.engine.integrate(0.12);

естественно кадров за 300 они упадут, по ходу падения заносим матрицы объектов (кубов) в архив. Так заранее будет известно какой гранью упал куб на плоскость, Нетрудно догадаться что повернув куб на 90 градусов по пределенным осям он ляжет заранее нужной гранью. Теперь включаем кнопку "плай" и проигрывается эта просщитанная анимация.


ЗЫ: я на жиглибе гочку делал, жаль что она никого не проперла.


Часовой пояс GMT +4, время: 04:53.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.