16 ноября 2010 г.

Серия уроков по Alternativa3D. Урок II. Добавление материала

Продолжаем наше увлекательное путешествие по урокам Мэтью Касперсена, посвященным отечественной разработке — 3-мерному движку для Flash под названием Alternativa3D.

Оригинал статьи находится здесь.

Для работы вам понадобится например FlashDevelop, а так же Adobe Flex SDK, который, к слову, подгружается при установке последней версии FlashDevelop. Как настроить FlashDevelop можно прочитать здесь. Также необходимо скачать 3 SWC-библиотеки Alternativa3D 5 версии и подключить к каждому вашему проекту.

Для подключения библиотеки в среде FlashDevelop жмите правую кнопку мыши в окне Project на той папке, в которой хотите разместить библиотеку (например libs) и выбирайте Add->Library Asset... Затем выбирайте файл *.swc и всё, библиотека подключена.

Перевод:

В первой части серии уроков вы увидели, как создать простое Flash-приложение с помощью Alternativa3D. Конечным результатом был вращающийся куб, отрисованный с использованием каркасного материала, который отображал грани полигонов, из которых он сделан. В этом уроке я покажу вам, как добавить материал на куб, чтобы придать ему более привлекательный вид.

Альтернатива поставляется с тремя стандартными типами материалов: каркасный материал, материал заполнения, и текстурируемый материал. Как уже упоминалось, каркасный материал (WireMaterial) показывает грани полигонов, из которых состоит модель. Материал заполнения (FillMaterial) отображает один простой цвет на всей модели, а при необходимости отображает также грани сетки материала. Наконец, текстурируемый материал (TextureMaterial) отображает двухмерное изображение как материал на модели.

Этот пример позволяет применить один из этих трех типов материалов к вращающемуся кубу, созданному в первом уроке. Для этого нам нужно создать несколько кнопок и ползунков для взаимодействия с пользователем.

<!-- Alternativa2.mxml -->
<?xml version="1.0" encoding="utf-8"?>

<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="absolute"
    xmlns:ns1="*"
    width="600"
    height="400"
    color="#FFFFFF"
    backgroundGradientAlphas="[1.0, 1.0]"
    backgroundGradientColors="[#FFFFFF, #C0C0C0]"
    frameRate="100">

    <ns1:EngineManager id="engineManager" x="0" y="0" width="100%" height="100%"/>
    <mx:HSlider x="56" y="147" width="53" id="sliderRed" minimum="0" maximum="255" snapInterval="1" change="{ApplicationManager.Instance.onColorChanged()}"/>
    <mx:Label x="10" y="147" text="Red" color="#000000"/>
    <mx:HSlider x="56" y="199" width="53" id="sliderBlue" minimum="0" maximum="255" snapInterval="1" change="{ApplicationManager.Instance.onColorChanged()}"/>
    <mx:Label x="10" y="199" text="Blue" color="#000000"/>

    <mx:Image x="10" y="10" id="imgAlternativa" source="@Embed(source='../media/alternativa.jpg')"/>
    <mx:Image x="10" y="340" source="@Embed(source='../media/thetechlabs.png')"/>
    <mx:Button x="10" y="50" label="Wireframe" color="#000000" id="btnWireframe" click="{ApplicationManager.Instance.setWireMaterial()}"/>
    <mx:Button x="10" y="80" label="Texture" color="#000000" id="btnTexture" width="88" click="{ApplicationManager.Instance.setTextureMaterial()}"/>
    <mx:Button x="10" y="110" label="Color Fill" color="#000000" width="88" id="btnColorFill" click="{ApplicationManager.Instance.setFillMaterial()}"/>
    <mx:HSlider x="56" y="173" width="53" id="sliderGreen" minimum="0" maximum="255" snapInterval="1" change="{ApplicationManager.Instance.onColorChanged()}"/>

    <mx:Label x="10" y="173" text="Green" color="#000000"/>

</mx:Application>

Отметим, что мы можем добавить стандартные Flex-овые GUI-контролы к нашей 3D-сцене так же, как и в любом другом приложении Flex. В нашем случае мы добавили 3 кнопки (по одной для каждого типа материала), 3 ползунка (для определения красного, зеленого и синего компонентов цвета каркасного материала или материала заполнения), и несколько Label-компонентов. Событие изменения значения слайдера устанавливает значения для компонентов цветов в функции getCurrentColor и определяя текущий тип материала применяет его к кубу, а событие клика по кнопке переключает тип материала функциями setWireMaterial, setFillMaterial, setTextureMaterial.

// ApplicationManager.as
package
{
    import alternativa.engine3d.materials.FillMaterial;
    import alternativa.engine3d.materials.TextureMaterial;
    import alternativa.engine3d.materials.WireMaterial;
    import alternativa.utils.ColorUtils;

    import flash.display.BlendMode;

    import mx.core.Application;

    /**
     *     The ApplicationManager holds all program related logic.
     */
    public class ApplicationManager
    {
        protected static const WIREFRAME:int = 1;
        protected static const TEXTURE:int = 2;
        protected static const FILL:int = 3;
        protected static var instance:ApplicationManager = null;
        protected var currentMaterial:int = 0;
        protected var rotatingBox:RotatingBox = null;

        public static function get Instance():ApplicationManager
        {
            if (instance == null)
                instance = new ApplicationManager();
            return instance;
        }

        public function ApplicationManager()
        {

        }

        public function startupApplicationManager():ApplicationManager
        {
            // create a new instance of the rotating box
            rotatingBox = new RotatingBox().startupRotatingBox();
            // give the box a wireframe material by default
            setWireMaterial();
            // tell the camera to look at the box
            Application.application.engineManager.cameraController.lookAt(rotatingBox.model.coords);

            return this;
        }

        public function setWireMaterial():void
        {
            currentMaterial = WIREFRAME;
            rotatingBox.model.cloneMaterialToAllSurfaces(new WireMaterial(1, getCurrentColor()));
        }

        public function setTextureMaterial():void
        {
            currentMaterial = TEXTURE;
            rotatingBox.model.cloneMaterialToAllSurfaces(new TextureMaterial(ResourceManager.Texture1_Tex));
        }

        public function setFillMaterial():void
        {
            currentMaterial = FILL;
            rotatingBox.model.cloneMaterialToAllSurfaces(new FillMaterial(getCurrentColor(), 1, BlendMode.NORMAL, 2, 0x000000));
        }

        public function onColorChanged():void
        {
            // reapply the current texture, taking into account the new color
            switch (currentMaterial)
            {
                case WIREFRAME:
                    setWireMaterial();
                    break;
                case FILL:
                    setFillMaterial();
                    break;
            }
        }

        /**
         *    Returns a uint reprensenting the color specified by the 3 sliders in the main GUI
         */
        protected function getCurrentColor():uint
        {
            return ColorUtils.rgb(Application.application.sliderRed.value, Application.application.sliderGreen.value, Application.application.sliderBlue.value);
        }
    }
}

Класс ApplicationManager содержит основную часть кода, который применяет материал на куб. Мы вводим свойство currentMaterial, которое приравнивается одной из трех предопределенных целочисленных констант в зависимости от типа материала, который мы назначаем на куб. Вы можете видеть это в функциях setWireMaterial, setFillMaterial и setTextureMaterial. Также в этих функциях мы используем метод cloneMaterialToAllSurfaces, назначающий различные типы материалов кубу.

Функция OnColorChanged вызывается, когда пользователь изменяет значение одого из слайдеров. Также переопределяется заново свойство currentMaterial. Заметим, что обе функции WireMaterial и FillMaterial содержат вызов функции getCurrentColor, которая возвращает беззнаковое целое число, определяющее цвет, выбранный пользователем с помощью ползунков. Вызывая функции setWireMaterial и setFillMaterial повторно, мы назначаем материал с новым значением цвета.

Класс TextureMaterial немного отличается от setWireMaterial и setFillMaterial. Он отображает двухмерное изображение в качестве материала. А откуда мы можем получить эту текстуру?

// ResourceManager.as
package
{
    import alternativa.types.Texture;

    /**
     *     ResourceManager is where we embed and create the resources needed by our application
     */
    public class ResourceManager
    {
        [Embed(source="../media/texture1.jpg")]
        public static const Texture1:Class;
        public static const Texture1_Tex:Texture = new Texture(new Texture1().bitmapData, "Texture1_Tex");
    }
}

Для этого мы определяем новый класс ResourceManager. В ResourceManager мы создаем и будем хранить ресурсы нашего приложения. Взгляните на строку кода [Embed(source="../media/texture1.jpg")]. Она позволяет внедрить ресурс (картинку, в нашем случае, моё прим.) как часть приложения Flex. Используя ключевое слово Embed, мы размещаем файл, расположенный на нашем компьютере в полученный при компиляции SWF-файл. Это значит, что нам не надо отдавать пользователям наш SWF-файл и файл ресурса (JPG, в данном случае) отдельно. Теперь это встроенный файл, который затем используется классом TextureMaterial и применяется к нашему кубу как материал.

Вы видите как быстро и легко мы создали приложение на основе кода первого урока. Классы EngineManager, BaseObject и MeshObject не изменились. ApplicationManager изменился совсем немного, но это потому что наше приложение содержит не так много специфичной логики. Мы также создали класс ResourceManager, который будет создавать и хранить наши ресурсы, используемые движком. Теперь ResourceManager будет дополняться другими свойствами практически в каждом уроке.

Что получилось можно увидеть здесь, исходный код — здесь

Комментариев нет:

Отправить комментарий