13.3 Загрузка, текстурирование и визуализация 3D моделей в OpenGL. Формат ASE. Часть 2.

Код данной функции:
/*http://esate.ru, Anvi*/



// функция отрисовки 
private void CreateList()
{

  // сохраняем тек матрицу 
  Gl.glPushMatrix();

  // проходим циклом по всем подобъектам 
  for ( int l = 0; l <= count_limbs; l++)
  {

      int nom_index = limbs[l].GetTextureNom();
      bool textureIsSet = false;

      if( nom_index > -1)
      if (limbs[l].NeedTexture() && text_objects[nom_index] != null)
      {
        Gl.glEnable( Gl.GL_TEXTURE_2D); // включаем режим текстурирования 
        // ID текстуры в памяти 
        uint nn = text_objects[limbs[l].GetTextureNom()].GetTextureObj();
        // активируем (привязываем) эту текстуру 
        Gl.glBindTexture( Gl.GL_TEXTURE_2D, nn);
      }

      Gl.glEnable( Gl.GL_NORMALIZE);

      // начинаем отрисовку полигонов 
      Gl.glBegin( Gl.GL_TRIANGLES);

      // по всем полигонам 
      for ( int i = 0; i < limbs[l].VandF[1]; i++)
      { 

        // временные переменные, чтобы код был более понятен 
        float x1, x2, x3, y1, y2, y3, z1, z2, z3 = 0;

        // вытаскиваем координаты треугольника (полигона) 
        x1 = limbs[l].vert[0, limbs[l].face[0, i]];
        x2 = limbs[l].vert[0, limbs[l].face[1, i]];
        x3 = limbs[l].vert[0, limbs[l].face[2, i]];
        y1 = limbs[l].vert[1, limbs[l].face[0, i]];
        y2 = limbs[l].vert[1, limbs[l].face[1, i]];
        y3 = limbs[l].vert[1, limbs[l].face[2, i]];
        z1 = limbs[l].vert[2, limbs[l].face[0, i]];
        z2 = limbs[l].vert[2, limbs[l].face[1, i]];
        z3 = limbs[l].vert[2, limbs[l].face[2, i]];

        // рассчитываем нормаль 
        float n1 = (y2 - y1) * (z3 - z1) - (y3 - y1) * (z2 - z1);
        float n2 = (z2 - z1) * (x3 - x1) - (z3 - z1) * (x2 - x1);
        float n3 = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);

        // устанавливаем нормаль 
        Gl.glNormal3f(n1, n2, n3);

        // если установлена текстура 
        if(textureIsSet)
        if (limbs[l].NeedTexture() && (limbs[l].t_vert != null) && (limbs[l].t_face != null))
        { // устанавливаем текстурные координаты для каждой вершины, ну и сами вершины 
        Gl.glTexCoord2f(limbs[l].t_vert[0, limbs[l].t_face[0, i]], limbs[l].t_vert[1, limbs[l].t_face[0, i]]);
        Gl.glVertex3f(x1, y1, z1);

        Gl.glTexCoord2f(limbs[l].t_vert[0, limbs[l].t_face[1, i]], limbs[l].t_vert[1, limbs[l].t_face[1, i]]);
        Gl.glVertex3f(x2, y2, z2);

        Gl.glTexCoord2f(limbs[l].t_vert[0, limbs[l].t_face[2, i]], limbs[l].t_vert[1, limbs[l].t_face[2, i]]);
        Gl.glVertex3f(x3, y3, z3);

      }
      else // иначе - отрисовка только вершин 
      { 
        Gl.glVertex3f(x1, y1, z1);
        Gl.glVertex3f(x2, y2, z2);
        Gl.glVertex3f(x3, y3, z3);
      }


    }

    // завершаем отрисовку 
    Gl.glEnd();
    Gl.glDisable( Gl.GL_NORMALIZE);

    // отключаем текстурирование 
    Gl.glDisable( Gl.GL_TEXTURE_2D);


  }

  // возвращаем сохраненную ранее матрицу 
  Gl.glPopMatrix();

}


Также рассмотрим код функции GetFirstWord, которая отвечает за получение первого слова в строке:

/*http://esate.ru, Anvi*/


// функция получения первого слова строки 
private string GetFirstWord( string word, int from)
{

  // from указывает на позицию, начиная с которой будет выполнятся чтение файла 
  char a = word[from]; // первый символ 
  string res_buff = ""; // временный буфер 
  int L = word.Length; // длина слова 

  if (word[from] == ' ' || word[from] == '  ') // если первый символ, с которого предстоит искать слово, является пробелом или знаком табуляции 
  { 

    // необходимо вычислить наличие секции пробелов или знаков табуляции и откинуть их 
    int ax = 0;
    // проходим до конца слова 
    for( ax = from; ax < L; ax++)
    { 
      a = word[ax];
      if( a != ' ' && a != '  ') // если встречаем символ пробела или табуляции, 
        break ; // выходим из цикла. 
      // таким образом, мы откидываем все последовательности пробелов или знаков табуляции, с которых могла начинаться переданная строка 
    }

    if( ax == L) // если вся представленная строка является набором пробелов или знаков табуляции, возвращаем res_buff 
      return res_buff;
    else
      from = ax; // иначе сохраняем значение ax 

  }
  int bx = 0;

  // теперь, когда пробелы и табуляция откинуты, мы непосредственно вычисляем слово 
  for (bx = from; bx < L; bx++)
  { 
    // если встретили знак пробела или табуляции, завершаем чтение слова 
    if (word[bx] == ' ' || word[bx] == '  ')
      break ;
    // записываем символ во временный буфер, постепенно получая таким образом слово 
    res_buff += word[bx];
  }

  // если дошли до конца строки, 
  if (bx == L)
    bx--; // уберем последнее значение 

  GlobalStringFrom = bx; // позиция в данной строке для чтения следующего слова в данной строке 

  return res_buff; // возвращаем слово 

}


Функция, которая будет использоваться для вызова отрисовки модели из оболочки программы:

/*http://esate.ru, Anvi*/


// функция отрисовки 3D модели 
public void DrawModel()
{
  // если модель не загружена, возврат из функции 
  if (!isLoad)
    return ;

  // сохраняем матрицу 
  Gl.glPushMatrix();

  // масштабирование по умолчанию 
  Gl.glScalef(0.05f, 0.05f, 0.05f);

  // вызов дисплейного списка 

  Gl.glCallList(thisList);

  // возврат матрицы 
  Gl.glPopMatrix();
}


Изменения в коде оболочки

Оболочка претерпела совсем незначительные изменения, которые сводятся к нескольким строкам кода для описания переменных класса и для загрузки 3D модели, выбора файла и ее отрисовки. Должна быть объявлена переменная:

/*http://esate.ru, Anvi*/

anModelLoader Model = null; 


Функция Form1_Load:

/*http://esate.ru, Anvi*/

…
// опции для загрузки файла 
openFileDialog1.Filter = "ase files (*.ase)|*.ase|All files (*.*)|*.*";
… 


Отрисовка модели в функции Draw:

/*http://esate.ru, Anvi*/

…

if( Model != null)
Model.DrawModel();
… 


Загрузка модели:

/*http://esate.ru, Anvi*/

// загрузка модели 
private void выбратьФайлДляЗагрузкиToolStripMenuItem_Click( object sender, EventArgs e)
{

  if (openFileDialog1.ShowDialog() == DialogResult.OK)
  { 
    Model = new anModelLoader();
    Model.LoadModel(openFileDialog1.FileName);
    RenderTimer.Start();
  }

}


Ну вот и все. На следующих скриншотах вы можете увидеть сцены в окне 3D Studio Max, затем сцены визуализированные после загрузки 3D модели из формата ASE. Во втором примере вы можете увидеть, что модель текстурирована.

По качеству она уступает визуализированной модели в 3D Studio Max, но это уже задача создания качественного рендера для вашего приложения (свойства материалов, освещение, сглаживание, различные шейдеры, что поднимает уровень визуализации сцены и является уже совсем другой задачей).
Уроки OpenGL + C#: Сцена в окне 3D Studio Max Рисунок 4. Сцена в окне 3D Studio Max.
Уроки OpenGL + C#: Сцена в окне программы после загрузки Рисунок 5. Сцена в окне программы после загрузки.
Уроки OpenGL + C#: Модель вертолета в редакторе 3D Studio Max Рисунок 6-a. Модель вертолета в редакторе 3D Studio Max.
Уроки OpenGL + C#: Текстурированная модель вертолета в редакторе 3D Studio Max Рисунок 6-b. Текстурированная модель вертолета в редакторе 3D Studio Max.
Уроки OpenGL + C#: Сцена, загруженная в программу Рисунок 7. Сцена, загруженная в программу.

Прикрепленные файлы для скачивания:
Добавить комментарий
Расширенный режим добавления комментариев доступен на форуме: загрузка изображений, цитирование, форматирование текста, и т.д.
Ваше имя:
Текст сообщения:
Комментарии (22):
mike124
mike124,  
Отсутствует определение функции SetMaterialNom в классе Limb.

О том, что в Form_Load надо вставить код

Код
Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
 Gl.glEnable(Gl.GL_BLEND);
 Gl.glEnable(Gl.GL_LINE_SMOOTH);
 Gl.glLineWidth(1.0f);

нигде не упоминается, а догадаться невозможно.

В целом, как учебное пособие, статья плохая, т.к. приходится лезть в приложенный исходник, чтобы добиться работоспособности программы. Исходный код из архива практически не откомментирован.

О назначении тех или иных функций необходимо просто догадываться.
mike124
mike124,  
Также имеется ошибка в использованном в статье коде функции CreateList:

из фрагмента кода
Код
 Gl.glNormal3f(n1, n2, n3);

// если установлена текстура 
if(textureIsSet)
if (limbs[l].NeedTexture() && (limbs[l].t_vert != null) && (limbs[l].t_face != null))
  { // устанавливаем текстурные координаты для каждой вершины, ну и сами вершины 
необходимо исключить
Код
if(textureIsSet)
Иначе модель не рисуется.
Елена Глушко
Елена Глушко,  
У меня возникла проблема с текстурами.
В 3ds max текстуры накладываются ровно, а в программе очень очень криво. В чем может быть проблема?
Анви Анви
Анви Анви,  
Цитата
В 3ds max текстуры накладываются ровно, а в программе очень очень криво. В чем может быть проблема?
Скорее всего где-то ошибка в назначении текстурных координат.
А если откомпеллировать архив с кодом к уроку и попробовать зашу модель загрузить в нем? Так же не корректно отображается?
Елена Глушко
Елена Глушко,  
Цитата
Анви Анви пишет:
Цитата
В 3ds max текстуры накладываются ровно, а в программе очень очень криво. В чем может быть проблема?
Скорее всего где-то ошибка в назначении текстурных координат.
А если откомпеллировать архив с кодом к уроку и попробовать зашу модель загрузить в нем? Так же не корректно отображается?
Да. Так же ровно. Уже шаманила и переводила модель в треугольники, потому как растягивается именно так. И размер текстур меняла. Все так же.
Анви Анви
Анви Анви,  
Возм. тогда имеет смысл с дебагером посидеть и посверять текстурные координаты, которые в модели в итоге назначаются, при визуализации, сравнивая с текстурной разверткой.
По ощущениям как будто координаты текстурные мы ждем в glTexCoord2f, а в реале идут целые числа.
Mixail12345
Mixail12345,  
Цитата
Анви Анви написал:
Цитата
В 3ds max текстуры накладываются ровно, а в программе очень очень криво. В чем может быть проблема?
Скорее всего где-то ошибка в назначении текстурных координат.
А если откомпеллировать архив с кодом к уроку и попробовать зашу модель загрузить в нем? Так же не корректно отображается?
Здравствуйте! Столкнулся с такой же проблемой - текстуры накладываются не ровно. Кто-то нашёл как исправить этот баг?
admin
admin,  
Цитата
Mixail12345 написал:
Здравствуйте! Столкнулся с такой же проблемой - текстуры накладываются не ровно. Кто-то нашёл как исправить этот баг?
видимо придется мне поискать =)
DoroViska
DoroViska,  
Цитата
Елена Глушко пишет:
У меня возникла проблема с текстурами.
В 3ds max текстуры накладываются ровно, а в программе очень очень криво. В чем может быть проблема?
У меня всё было тоже самое. пока не заменил библиотеку Devil на System.Drawing. В итоге весь класс текстурирования ушёл на переработку.
Проблема в загрузки текстур, а не в отрисовки и назначение текстурных координат. если надо могу поделится исходниками.
DoroViska
DoroViska,  
Цитата
DoroViska пишет:
Цитата
Елена Глушко пишет:
У меня возникла проблема с текстурами.
В 3ds max текстуры накладываются ровно, а в программе очень очень криво. В чем может быть проблема?
У меня всё было тоже самое. пока не заменил библиотеку Devil на System.Drawing. В итоге весь класс текстурирования ушёл на переработку.
Проблема в загрузки текстур, а не в отрисовки и назначение текстурных координат. если надо могу поделится исходниками.
БЕРУ СВОИ СЛОВА ОБРАТНО. Всё дело было в стандартном повороте текстуры.
Anvi
Anvi,  
Mixail12345, приложите, пожалуйста, к сообщению файл с проблемной моделью и текустурой.

Нашел в старых бекапах пару моделек ASE. Загрузил в программу (исходник, приложенный к последней части урока). Модель из 3х подобъектов. С тремя текстурами, все наложилось корректно:



Архив с моделью и текстурой приложил.
Исходники пока не проверял.
Anvi
Anvi,  
ElenaPotter
ElenaPotter,  
Пытаюсь сделать модель Земли
Не могу понять, в чем проблема. Мало того, что он разрезает текстуру на какие-то блоки, так еще и обращает цвета (это вот для меня уже совсем странно и необъяснимо).
ElenaPotter
ElenaPotter,  
Изменила Il.ilEnable(Il.IL_ORIGIN_SET ) на Il.ilEnable(Il.IL_CONV_PAL) и всё пришло в норму :)
Viking8008
Viking8008,  
Подождите, модель то прога загружает, а как шкурку-то надеть? Помогите, пожалуйста! Если можете скиньте архив готовый.
Или, если я в 3д макс разрисую объект, то и в прогу он разрисованный засунеться?
Anvi
Anvi,  
Цитата
Viking8008 написал:
Подождите, модель то прога загружает, а как шкурку-то надеть? Помогите, пожалуйста! Если можете скиньте архив готовый.
Или, если я в 3д макс разрисую объект, то и в прогу он разрисованный засунеться?
Чтобы текстура корректно наложилась, нужно чтобы на 3D модели присутствовали текстурные координаты + была создана текстурная карта.

Пример создания текстурной карты в 3D max:
http://esate.ru/uroki/3d-max/materialy_i_osveshchenie/3D_max_urok_14_1/

Пример модели + текстуры приложен в сообщениях форума выше.
Viking8008
Viking8008,  
Цитата
Anvi написал:
Цитата
Viking8008 написал:
Подождите, модель то прога загружает, а как шкурку-то надеть? Помогите, пожалуйста! Если можете скиньте архив готовый.
Или, если я в 3д макс разрисую объект, то и в прогу он разрисованный засунеться?
Чтобы текстура корректно наложилась, нужно чтобы на 3D модели присутствовали текстурные координаты + была создана текстурная карта.

Пример создания текстурной карты в 3D max:
http://esate.ru/uroki/3d-max/materialy_i_osveshchenie/3D_max_urok_14_1/

Пример модели + текстуры приложен в сообщениях форума выше.
Решил вернуться и разобраться. Наконец-то постиг всю суть работы программы. Только я её теперь запустить не могу(
Качаю исходный проект, запускаю, визуалка его преобразовывает, типа проект старый ( у меня 2010 ultimate или как-то так). После нажатия запуска ошибка (картинка)
Попробывал в новый проект просто всё скопировать, так при выборе модели из файла программа просто СРАЗУ же закрывается. Она так же СРАЗУ же закрывается, если я дёргаю ползунки.
Помогите, пожалуйста(

ААААА РЕБЗЯ ВСЁ ЗАРАБОТАЛООООООООООООООООО
Всем спасибо, чмоки вам всем чмоки!
Я просто создал ещё 1 проект иииии О МАГИЯ!
noname
noname,  
Viking8008, по поводу скрина в вашем сообщении: http://esate.ru/blogs/noname/oshibka-pri-kompilyatsii-badimageformatexception-0x8007000B/
Elzette
Elzette,  
Как загрузить текстуру в модель? Она уже есть в .ASE файле, или нужно её как-то прикреплять? Есть готовая моделька и текстуры к ней, есть .max модель с загруженными текстурами, но загрузить в программу я её не могу.
Подскажите, пожалуйста, как это сделать :?:
noname
noname,  
Цитата
Как загрузить текстуру в модель? Она уже есть в .ASE файле, или нужно её как-то прикреплять? Есть готовая моделька и текстуры к ней, есть .max модель с загруженными текстурами, но загрузить в программу я её не могу.
Подскажите, пожалуйста, как это сделать
привет
когда экспорт делаете из 3d max в ASE, вы отмечаете чтобы экспортировались текстурные кооридинаты. Соответственно и имя текстуры попадает в файл ase. Текстура хранится вместе с файлом.
экспорт описан в начале урока http://esate.ru/uroki/OpenGL/uroki-OpenGL-c-sharp/zagruzka-trehmernyh-modeley-v-opengl/
asmil
asmil,  
А как загрузить на фон окна AnT какое-нибудь изображение?
я например, хочу сделать координатные оси или ограничить область 3д модели так называемой клеткой
в параметрах элемента AnT поставил изображение, но его не показывает- до визуализации черный экран, после - модель на белом фоне.
noname
noname,  
Цитата
asmil написал:
А как загрузить на фон окна AnT какое-нибудь изображение?
я например, хочу сделать координатные оси или ограничить область 3д модели так называемой клеткой
в параметрах элемента AnT поставил изображение, но его не показывает- до визуализации черный экран, после - модель на белом фоне.
никак,
все что отображается в объекте AnT визуализируется в 3D сцене.
лучше проходите уроки последовательно, чтобы разобраться, как визуализируются сцены.
^