После большого количества вопросов о том, как сделать перемещаемую пользователем камеру для Альтернативы, а иногда и такую, которая не "проходит сквозь стены", я решил всё же написать простенький пример. Для облегчения понимания максимально упростил логику и оставил только показательный функционал — "навернуть" всегда можно.
Также, пример рассчитан на новую, 8-ю версию "движка" Альтернативы, который поддерживает аппаратное ускорение графики. Но так как Flash Player 11 еще не вышел, то для функционирования примера и его тестирования необходим Flash Player 11 Incubator. Как всё это дело настроить можно посмотреть в предыдущих моих записях в блоге.
Итак, для примера нам нужен уровень и камера. Уровень можно подготовить в любом трехмерном редакторе с поддержкой экспорта в формат Collada (*.dae). API
camera = new Camera3D(10, 10000); camera.view = new View(stage.stageWidth, stage.stageHeight); addChild(camera.view); camera.rotationX = -90 * Math.PI / 180; camera.rotationZ = -90 * Math.PI / 180; camera.z = 60; scene.addChild(camera);
Затем подгружаем наш трехмерный объект уровня. Процедура стандартна и массу раз описана во многих источниках. Далее подписываемся на нужные события. Нам понадобятся обработчики:
- перерисовки кадра onEnterFrame;
- изменения размеров кадра onResize;
- событие нажатия на кнопку клавиатуры _keyDownListener;
- событие отпускания кнопки клавиатуры _keyUpListener.
Назначения обработчиков события изменения размеров сцены, нажатия и отпускания кнопок клавиатуры понятны и банальны для платформы Flash. Достаточно посмотреть код.
Целью данного примера служит передвигаемая камера. Вся обработка пользовательского ввода с клавиатуры для управления камерой сосредоточена в методе onEnterFrame, который вызывается каждый кадр. Мы вычисляем предполагаемое смещение камеры и помещаем данные в Vector3D.
var delta:Vector3D = new Vector3D(); if (_keyUp) { delta.y = Math.cos(camera.rotationZ) * _directSpeed; delta.x = -Math.sin(camera.rotationZ) * _directSpeed; } else if (_keyDown) { delta.y = -Math.cos(camera.rotationZ) * _directSpeed; delta.x = Math.sin(camera.rotationZ) * _directSpeed; }
Затем, созданный нами объект определения столкновений collider класса EllipsoidCollider вычисляет для нас разрешенное новое местоположение и получившиеся величины мы присваиваем камере.
ar destination:Vector3D = collider.calculateDestination(position, delta, level); camera.x = destination.x; camera.y = destination.y;
Далее — перерисовываем сцену.
Вот так, все достаточно не сложно.
Исходный код примера вы можете взять здесь (*.rar, 517 Kb).
12 комментариев:
доброго времени суток)
вопрос не совсем в тему, но тем не менее..
есть сделанная в 3d Max модель. я экспортирую её в два файла: ".3ds" и ".DAE". Далее я вставляю эти файлы во флеш. результат следующий:
3ds - модель находится в нужных координатах и в правильном положении, но текстуры лежат очень криво.
DAE - текстуры лежат как нужно, но сама модель перевёрнута непонятным образом.
подскажите, пожалуйста, в чем может быть дело?
// если посчитаете мой пост флудом, прошу удалить его и ответить мне на почту. Заранее Спасибо:)
Cannibalistic@yandex.ru, думаю, вариантов может быть очень много: от ошибки в парсере (менее вероятно) до неправильной подготовки модели в 3d редакторе (более вероятно). Сложно сделать конкретный вывод из абстрактных данных. Могу попробовать порекомендовать упростить модель в редакторе например до куба и поэкспериментировать с его местоположением и текстурированием в разных форматах, и если ошибки повторяются - можно делать какой-то вывод.
спасибо за внимание:)
я так и сделал... прилагаю пару скринов... на сцене два параллелепипеда. один из .DAE файла, второй из .3DS. эти файлы экспортированы с одной сцены макса. К примитиву применён модификатор UVWMapping с параметром Box. Причем, если границы гизмо совпадают с размерами модели, то всё нормально. Но если сжать/растянуть гизмо, происходит то, что на скрине. Если вместо масштабирования гизмо использовать тайлинг, получается тоже самое...
текстура в формате .jpg. Пробовал .BMP - альтернатива ругается, что не знает такого формата, и .PNG - результат идентичен JPG'овскому.
скрины и код:
http://rghost.ru/18354511
Я, конечно, не претендую на экспертное мнение, но...
То что объекты позиционируются по-разному - это скорее работа экспортера из макса в dae или 3ds. Т.е. на самом деле, объект находится в одних координатах (0, 0, 0), только повернут по оси x или y. Выставите пивот в максе в центр объекта и поймете.
После картирования объекта в максе я лично предпочитаю конвертировать объект в меш (можно поли). Но это на уровне предположения и, вполне возможно, что и без этого текстурные координаты ложатся аналогично - не проверял - попробуйте.
С тем, что текстура не повторяется (как должна) тоже можно поковыряться. Например, выставить для меша свойство его текстурематериала repeat в true.
Отпишитесь по результату - интересно.
Pixel, спасибо))
дело было как раз в свойстве repeat. Когда разобрался с текстурами, в колладе ковыряться не стал - хватает 3DS :)
насчёт моделей - все их конвертирую в поли.
возник ещё вопрос. теперь ближе к теме столкновений... есть объект, управляемый контроллером. есть Sprite. можно ли определить момент прохождения объекта через спрайт? я делаю так...
if (collider.getCollision(begining, // текущая позиция
displacement,
resPoint,
resPlane,
sprite)) // спрайт, с которым определяется столкновение
trace("true");
не происходит вообще ничего...
Спрайт - вряд ли. Думаю, можно сделать невидимый меш, связать его по координатам со спрайтом и определять столкновение с ним, а не со спрайтом.
А такой вопрос,загрузи модель, model.z ++ ; model.rotatinZ ++ ;
я смещаю вместе с пивотом ... как этого избежать...
то есть поворот идет вокруг
x:0,y:0,z:0
а мне надо что бы модель вокруг своей оси крутилась ...
> я смещаю вместе с пивотом
- это значит вместе с камерой?
> то есть поворот идет вокруг x:0,y:0,z:0
- это координаты чего? модели?
> что бы модель вокруг своей оси крутилась
а крутится?
Вообще данных для ответа мало. Например, модель грузится в какой контейнер? В рут?
modl1(Mesh),mod2(Mesh),mod3(Mesh) в одном
( class Obj extends Object3d ) класcе,в 'том же классе mod1.y++ ;mod2.y++ ;mod3.y++;
в главном классе (Main extends Sprite)
Obj.RotationX ++ ;
эффект спирали ,
как смещать точку вокруг которой происходит RotationX. при .y++ я удаляюсь от нее, если
не поняли о чем речь то это можна увидеть
в 3dMax - рядом с кнопкой для скалирования обьэктов
есть окошко System Coordinate мне нужно по системе Viev а у меня как Local....
Можно использовать матричные преобразования. Для каждого объекта строите единичную матрицу и на каждом кадре добавляете все трансформации. Для вложенных объектов они накапливаются и из родителя. Всё достаточно просто и расписано в литературе по 3д-программированию подробнейше и не раз. Например здесь: http://www.ozon.ru/context/detail/id/1633721/
спасибо...
Отправить комментарий