private void Form1_Load(object sender, EventArgs e) { Glut.glutInit(); Glut.glutInitDisplayMode(Glut.GLUT_RGB | Glut.GLUT_DOUBLE | Glut.GLUT_DEPTH); Il.ilInit(); Il.ilEnable(Il.IL_ORIGIN_SET); Gl.glClearColor(0, 0, 0, 1); Gl.glViewport(0, 0, AnT.Width, AnT.Height); Gl.glMatrixMode(Gl.GL_PROJECTION); Gl.glLoadIdentity(); Glu.gluPerspective(45, (float)AnT.Width / (float)AnT.Height, 0.1, 200); Gl.glMatrixMode(Gl.GL_MODELVIEW); Gl.glLoadIdentity(); Gl.glEnable(Gl.GL_DEPTH_TEST); Gl.glEnable(Gl.GL_NORMALIZE); Gl.glEnable(Gl.GL_LIGHTING); Gl.glEnable(Gl.GL_LIGHT0); float[] ambience = { 0.3f, 0.3f, 0.3f, 1.0f }; // Цвет мирового света float[] diffuse = { 0.5f, 0.5f, 0.5f, 1.0f }; // Цвет позиционного света // Чтобы установить мировое освещене, нужно передать OpenGL наши массивы. // OpenGL даёт нам возможность использовать несколько источников света. Общее количество // источников зависит от переменной GL_MAX_LIGHTS. Для первого используемого источника будем // использовать дефайн OpenGL GL_LIGHT0. После указания используемого источника передаём // OpenGL флаг говорящий, что мы устанавливаем значение ambience, и массив ambience-цветов. // Точно то же делаем с diffuse и GL_DIFFUSE. // Устанавливаем цвет рассеянного цвета (без направленного света) Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_AMBIENT, ambience); // И диффузный цвет (цвет света) Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_DIFFUSE, diffuse); Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_POSITION, _lightPos); Gl.glEnable(Gl.GL_COLOR_MATERIAL); var texture = new TexturesForObjects(); texture.LoadTextureForModel(@"face.jpg"); texIdFace = texture.GetTextureObj(); texture.LoadTextureForModel(@"grass.jpg"); texIdGround = texture.GetTextureObj(); texture.LoadTextureForModel(@"material.jpg"); texIdMaterial = texture.GetTextureObj(); texture.LoadTextureForModel(@"chest.jpg"); texIdChest = texture.GetTextureObj(); texture.LoadTextureForModel(@"torso.jpg"); texIdTorso = texture.GetTextureObj(); texture.LoadTextureForModel(@"metal.jpg"); texIdPress = texture.GetTextureObj(); RenderTimer.Start(); }
// загрузка модели public int LoadModel(string FileName) { // модель может содержать до 256 под-объектов limbs = new LIMB[256]; // счетчик скинут int limb_ = -1; // имся файла FName = FileName; // начинаем чтение файла StreamReader sw = File.OpenText(FileName); // временные буферы string a_buff = ""; string b_buff = ""; string c_buff = ""; // счетчики вершин и полигонов int ver = 0, fac = 0; // если строка успешно прочитана while ((a_buff = sw.ReadLine()) != null) { // получаем первое слово b_buff = GetFirstWord(a_buff, 0); if (b_buff[0] == '*') // определеям, является ли первый символ звездочкой { switch (b_buff) // если да, то проверяем какое управляющее слово содержится в первом прочитаном слове { case "*MATERIAL_COUNT": // счетчик материалов { // получаем первое слово от символа указанного в GlobalStringFrom c_buff = GetFirstWord(a_buff, GlobalStringFrom); int mat = System.Convert.ToInt32(c_buff); // создаем объект для текстуры в памяти text_objects = new TexturesForObjects[mat]; continue; } case "*MATERIAL_REF": // номер текстуры { // записываем для текущего под-объекта номер текстуры c_buff = GetFirstWord(a_buff, GlobalStringFrom); int mat_ref = System.Convert.ToInt32(c_buff); // устанавливаем номер материала, соответствующий данной модели. limbs[limb_].SetMaterialNom(mat_ref); continue; } case "*MATERIAL": // указание на материал { c_buff = GetFirstWord(a_buff, GlobalStringFrom); mat_nom = System.Convert.ToInt32(c_buff); continue; } case "*GEOMOBJECT": // начинается описание геметрии под-объекта { limb_++; // записываем в счетчик под-объектов continue; } case "*MESH_NUMVERTEX": // количесвто вершин в под-объекте { c_buff = GetFirstWord(a_buff, GlobalStringFrom); ver = System.Convert.ToInt32(c_buff); continue; } case "*BITMAP": // имя текстуры { c_buff = ""; // обнуляем временный буффер for (int ax = GlobalStringFrom + 2; ax < a_buff.Length - 1; ax++) c_buff += a_buff[ax]; // считываем имя текстуры text_objects[mat_nom] = new TexturesForObjects(); // новый объект для текстуры text_objects[mat_nom].LoadTextureForModel(c_buff); // загружаем текстуру continue; } case "*MESH_NUMTVERTEX": // количество текстурных координат, данное слово говорит о наличии текстурных координат - следовательно мы должны выделить память для них { c_buff = GetFirstWord(a_buff, GlobalStringFrom); if (limbs[limb_] != null) { limbs[limb_].createTextureVertexMem(System.Convert.ToInt32(c_buff)); } continue; } case "*MESH_NUMTVFACES": // память для текстурных координат (faces) { c_buff = GetFirstWord(a_buff, GlobalStringFrom); if (limbs[limb_] != null) { // выделяем память для текстурныйх координат limbs[limb_].createTextureFaceMem(System.Convert.ToInt32(c_buff)); } continue; } case "*MESH_NUMFACES": // количество полиговов в под-объекте { c_buff = GetFirstWord(a_buff, GlobalStringFrom); fac = System.Convert.ToInt32(c_buff); // если было объвляющее слово *GEOMOBJECT (гарантия выполнения условия limb_ > -1) и были указаны количство вершин if (limb_ > -1 && ver > -1 && fac > -1) { // создаем новый под-объект в памяти limbs[limb_] = new LIMB(ver, fac); } else { // иначе завершаем неудачей return -1; } continue; } case "*MESH_VERTEX": // информация о вершине { // под-объект создан в памяти if (limb_ == -1) return -2; if (limbs[limb_] == null) return -3; string a1 = "", a2 = "", a3 = "", a4 = ""; // полчучаем информацию о кооринатах и номере вершины // (получаем все слова в строке) a1 = GetFirstWord(a_buff, GlobalStringFrom); a2 = GetFirstWord(a_buff, GlobalStringFrom); a3 = GetFirstWord(a_buff, GlobalStringFrom); a4 = GetFirstWord(a_buff, GlobalStringFrom); // преобразовываем в целое цисло int NomVertex = System.Convert.ToInt32(a1); // заменяем точки в представлении числа с плавающей точкой, на запятые, чтобы правильно выполнилась функция // преобразования строки в дробное число a2 = a2.Replace('.', ','); a3 = a3.Replace('.', ','); a4 = a4.Replace('.', ','); // записываем информацию о вершине limbs[limb_].vert[0, NomVertex] = (float)System.Convert.ToDouble(a2); // x limbs[limb_].vert[1, NomVertex] = (float)System.Convert.ToDouble(a3); // y limbs[limb_].vert[2, NomVertex] = (float)System.Convert.ToDouble(a4); // z continue; } case "*MESH_FACE": // информация о полигоне { // под-объект создан в памяти if (limb_ == -1) return -2; if (limbs[limb_] == null) return -3; // временные перменные string a1 = "", a2 = "", a3 = "", a4 = "", a5 = "", a6 = "", a7 = ""; // получаем все слова в строке a1 = GetFirstWord(a_buff, GlobalStringFrom); a2 = GetFirstWord(a_buff, GlobalStringFrom); a3 = GetFirstWord(a_buff, GlobalStringFrom); a4 = GetFirstWord(a_buff, GlobalStringFrom); a5 = GetFirstWord(a_buff, GlobalStringFrom); a6 = GetFirstWord(a_buff, GlobalStringFrom); a7 = GetFirstWord(a_buff, GlobalStringFrom); // получаем нмоер полигона из первого слова в строке, заменив последний символ ":" после номера на флаг окончания строки. int NomFace = System.Convert.ToInt32(a1.Replace(':', '\0')); // записываем номера вершин, которые нас интересуют limbs[limb_].face[0, NomFace] = System.Convert.ToInt32(a3); limbs[limb_].face[1, NomFace] = System.Convert.ToInt32(a5); limbs[limb_].face[2, NomFace] = System.Convert.ToInt32(a7); continue; } // текстурые координаты case "*MESH_TVERT": { // под-объект создан в памяти if (limb_ == -1) return -2; if (limbs[limb_] == null) return -3; // временные перменные string a1 = "", a2 = "", a3 = "", a4 = ""; // получаем все слова в строке a1 = GetFirstWord(a_buff, GlobalStringFrom); a2 = GetFirstWord(a_buff, GlobalStringFrom); a3 = GetFirstWord(a_buff, GlobalStringFrom); a4 = GetFirstWord(a_buff, GlobalStringFrom); // преобразуем первое слово в номер вершины int NomVertex = System.Convert.ToInt32(a1); // заменяем точки в представлении числа с плавающей точкой, на запятые, чтобы правильно выполнилась функция // преобразования строки в дробное число a2 = a2.Replace('.', ','); a3 = a3.Replace('.', ','); a4 = a4.Replace('.', ','); // записываем значение вершины limbs[limb_].t_vert[0, NomVertex] = (float)System.Convert.ToDouble(a2); // x limbs[limb_].t_vert[1, NomVertex] = (float)System.Convert.ToDouble(a3); // y limbs[limb_].t_vert[2, NomVertex] = (float)System.Convert.ToDouble(a4); // z continue; } // привязка текстурных координат к полигонам case "*MESH_TFACE": { // под-объект создан в памяти if (limb_ == -1) return -2; if (limbs[limb_] == null) return -3; // временные перменные string a1 = "", a2 = "", a3 = "", a4 = ""; // получаем все слова в строке a1 = GetFirstWord(a_buff, GlobalStringFrom); a2 = GetFirstWord(a_buff, GlobalStringFrom); a3 = GetFirstWord(a_buff, GlobalStringFrom); a4 = GetFirstWord(a_buff, GlobalStringFrom); // преобразуем первое слово в номер полигона int NomFace = System.Convert.ToInt32(a1); // записываем номера вершин, которые опиывают полигон limbs[limb_].t_face[0, NomFace] = System.Convert.ToInt32(a2); limbs[limb_].t_face[1, NomFace] = System.Convert.ToInt32(a3); limbs[limb_].t_face[2, NomFace] = System.Convert.ToInt32(a4); continue; } } } } // пересохраняем количесвто полигонов count_limbs = limb_; // получаем ID для создаваемого дисплейного списка int nom_l = Gl.glGenLists(1); thisList = nom_l; // генерируем новый дисплейный список Gl.glNewList(nom_l, Gl.GL_COMPILE); // отрисовываем геометрию CreateList(); // завершаем дисплейный список Gl.glEndList(); // загрузка завершена isLoad = true; return 0; }