netlib.narod.ru< Назад | Оглавление | Далее >

Создание леса

Давайте попробуем изобразить на экране сценку из жизни леса: в ветвях весело щебечут птички, журчит ручеек, где-то ухает филин. Неплохая мысль — но для начала придется нарисовать что-нибудь, хотя бы отдаленно напоминающее дерево. На рис. 4.25 изображена елка (команда Edit | A Tree).


Рис. 4.25. Елка

Рис. 4.25. Елка


Конечно, елки бывают и покрасивее, но пока сойдет и такая. Наше дерево состоит из 25 вершин и 19 граней. Если мы хотим создать целый лес из 100 деревьев (из остальных елок сделали бумагу для книги, которую вы читаете), можно включить в макет еще 99 деревьев, похожих на рис. 4.25. Самое время подумать о том, как приказать механизму визуализации нарисовать еще 99 деревьев, в точности аналогичных первому, но расположенных в других местах макета.

Помните, что мы говорили о фреймах и визуальных элементах в главе 3? Объект C3dShape содержит фрейм, определяющий его положение, размер, ориентацию и т.д., а также визуальный элемент, который по сути дела описывает набор вершин, граней и т.д. для объекта, который мы хотим увидеть на экране. Функция C3dShape::Clone позволяет включить один и тот же визуальный элемент в несколько разных фреймов. Она создает новый объект C3dShape по существующему объекту, но вместо того, чтобы строить для него новый визуальный элемент, она присоединяет к объекту визуальный элемент исходной фигуры. Таким образом, чтобы изобразить лес, можно создать одно дерево и продублировать его 99 раз. Результат изображен на рис. 4.26 (команда Edit | A Forest).


Рис. 4.26. Лес

Рис. 4.26. Лес


Давайте рассмотрим функцию, в которой строится лес, поскольку некоторые аспекты процесса дублирования оказываются неочевидными.

void CMainFrame::OnEditForest()
{
    NewScene(); 

    // Создать первое дерево вместе со стволом
    m_pShape = new C3dShape;
    m_pShape->CreateCone(0, 0, 0, 1, TRUE,
                            0, 4, 0, 0, FALSE);
    C3dShape trunk;
    trunk.CreateRod(0, -2, 0, 0, 0, 0, 0.2);
    m_pShape->AddChild(&trunk);

    // Присоединить дерево к макету
    m_pScene->AddChild(m_pShape);

    // Получить позицию и ориентацию ствола
    // по отношению к родителю (дереву)
    C3dVector p, d, u;
    trunk.GetPosition(p);
    trunk.GetDirection(d, u);

    // Дублировать дерево 99 раз
    for (int i = 0; i < 99; i++) { 
        // Дублировать крону и ствол
        C3dShape* pTree = m_pShape->Clone();
        C3dShape* pTrunk = trunk.Clone();
        pTree->AddChild(pTrunk);
        // Задать относительную позицию ствола
        // по отношению к кроне
        pTrunk->SetPosition(p);
        pTrunk->SetDirection(d, u);

        // Присоединить дубли как потомков первого дерева,
        // чтобы можно было вращать весь лес
        m_pShape->AddChild(pTree);

        // Задать положение нового дерева в макете
        pTree->SetPosition(((double)(rand() % 100) / 5) — 10.0,
                          0, (double)(rand() % 100) / 5, m_pScene);

        // Удалить контейнеры
        delete pTrunk;
        delete pTree;
    }
}

Непременно обратите внимание на то, что ствол присоединяется в качестве потомка к конусу, образующему крону дерева, поэтому при дублировании кроны со стволом важно, чтобы при присоединении ствола-дубликата к кроне-дубликату была сохранена их относительная позиция. Если этого не сделать, ствол будет развернут в каком-нибудь странном направлении и по всей вероятности вообще не будет соединен с кроной. Попробуйте закомментировать фрагменты позиционирования (pTree->SetPosition) и ориентации ствола и заново постройте приложение, чтобы посмотреть, что из этого получится.

Второй важный момент заключается в том, что деревья-дубликаты становятся потомками самого первого дерева, чтобы можно было вращать весь лес с помощью одной переменной m_pShape (первое дерево). Поскольку дубликаты являются потомками первого дерева, их позиция должна быть задана по отношению ко всему макету. Если удалить из вызова pTree->SetPosition необязательный аргумент-фрейм (m_pScene), позиция будет указываться по отношению к родителю, и деревья расположатся неверно. Проверьте!


netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz