Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
8. Трехмерное моделирование полигональными сетк...doc
Скачиваний:
10
Добавлен:
23.11.2019
Размер:
310.27 Кб
Скачать

8.3. Структура хранения данных

Приведенный пример прост и не требует никаких усилий. Однако легко догадаться, что количество данных для описания полигональной сетки может быть весьма велико. Поэтому актуальным является поиск структуры данных для представления полигональной сетки, при которой обеспечивалось бы их экономное хранение. Широко распространенной и популярной является следующая структура хранения данных полигональной сетки:

- в массиве вершин хранятся без повторений координаты всех вершин;

- в массиве нормалей хранятся без повторений компоненты нормалей к каждой грани;

- в массиве граней для каждой грани хранятся индексы вершин из массива вершин и индексы нормалей, ассоциированных с каждой вершиной грани.

Приведем пример для тетраэдра, изображенного на рис. 8.4.

Таблица 8.1

Массив

вершин

нормалей

граней

v

x

y

z

n

x

y

z

f

v, n

v, n

v, n

0

0

0

0

0

0,577

0,577

0,577

0

1, 0

2, 0

3, 0

1

1

0

0

1

0

0

–1

1

0, 1

2, 1

1, 1

2

0

1

0

2

–1

0

0

2

0, 2

3, 2

2, 2

3

0

0

1

3

0

–1

0

3

1, 3

3, 3

0, 3

В этой таблице v, n и f – индексы массивов вершин, нормалей и граней соответственно. Здесь каждой грани поставлен в соответствие массив индексов. Каждый элемент массива индексов имеет структуру (v, n).

В листинге 8.2 приведен пример библиотеки классов, описывающих такую структуру представления данных. Для простоты методы не приводятся.

Листинг 8.2. Классы для работы с полигональной сеткой.

class Point3{

public:

float x, y, z;

};

class Vector3{

public:

float x, y, z;

};

class VertexID{

public:

int vertIndex;

int normIndex;

};

class Face{

public:

int nVerts;

VertexID *vert;

};

class Mesh{

private:

int numVerts;

Point3 *pt;

int numNormals;

Vector3 *norm;

int numFaces;

Face *face;

};

Нас интересует способ доступа к v-й вершине f-й грани:

face – массив граней (указатель на массив граней);

face[f] – f-я грань (указатель на структуру, описывающую f-ю грань) ;

face[f].vert[v] – v-я точка f-й грани (указатель на структуру, описывающую v-ю вершину, f -й граней) ;

face[f].vert[v].vertIndex = iv – это индекс v-й вершины f-й грани в массиве вершин pt;

face[f].vert[v].normIndex = in – это индекс вектора нормали ассоциированного с v-й вершиной f-й грани;

pt[iv] – искомая вершина;

pt[iv].x – координата x искомой вершины;

pt[iv].y – координата y искомой вершины;

pt[iv].z – координата z искомой вершины;

norm[in] – нормаль, ассоциированная с искомой вершиной;

pt[in].x – компонента x искомой нормали;

pt[in].y – компонента y искомой нормали;

pt[in].z – компонента z искомой нормали.

Для примера приведем несколько методов класса Mesh. Если структура объекта описана данными как в классе Mesh, то рисование объекта можно выполнить, как это приведено в листинге 10.3.

Листинг 10.3. Метод рисования класса Mesh.

void Mesh::draw()

{ for (int f = 0; f < numFaces; f++)

{ glBegin(GL_POLYGON);

for(int v = 0; v < face[f].nVerts; v++)

{ int in = face[f].vert[v].normIndex;

int iv = face[f].vert[v].vertIndex;

glNormal3f(norm[in].x, norm[in].y, norm[in].z);

glVertex3f(pt[iv].x, pt[iv].y, pt[iv].z);

}

glEnd();

}

}

Часто целесообразно данные хранить в файле. Сделать это можно как в листинге 8.4.

Листинг 8.4. Метод сохранения класса Mesh

void Mesh::writeMesh(char * fname)

{ if (numVerts == 0 || numNorms == 0 || numFaces == 0) return;

fstream outStream(fname, ios::out); //открываем поток вывода

if (outStream.fail())

{ cout << " ошибка открытия файла: " << fname << end; return;}

outStream << numVerts << " " << numNorms << " " << numFaces <<"\n";

//записываем список вершин и нормалей :

for(int i = 0; i < numVerts; i++)

outStream << pt[i].x << " " << pt[i].y << " " << pt[i].z << "\n";

for(int ii = 0; ii < numNorms; ii++)

outStream << norm[ii].x << " " << norm[ii].y << " " << norm[ii].z << "\n";

//записываем данные по грани

for(int f = 0; f < numFaces; f++)

{ int n = face[f].nVerts;

outStream << n << "\n";

for(int v = 0; v < n; v++)

//записываем индексы вершин для каждой грани

outStream << face[f].vert[v].vertIndex << " "; outStream << "\n";

for(int k = 0; k < n; k++)

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

outStream << face[f].vert[k].normIndex << " "; outStream << "\n";

}

outStream.close();

}

Потребуется как минимум еще метод чтения данных из файла и некоторые другие (это – для самостоятельной работы).

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]