GameDev.ru
/ GameDev.ru / Пользователи / Andrey / Сообщения на форуме пользователя Andrey (216 стр.)

Сообщения на форуме пользователя Andrey (216 стр.)

Рендер через Octree-дерева:FPS низок по сравнению с прямым рендером.Прошу помощи.26 мая 20059:58#7
Спасибо большое сколько сразу ответов!!!
resurected_timofei
>Если из 5000 - не знаю =)
сейчас продебагил вот 5282 полигона для сцены из скриншота
>То же самое тебе скажут и дядки-профи ГеймДева. Всем так говорят.
>Да так и есть на самом деле ;) Так что не волнуйся! Когда сцена будет
>огромной ты это почувствуешь!
Спасибо ты меня успокоил!!! а то я уже вообще в панике я даже про это не

задумался теперь чуть чуть врубаюсь...
>PS: Ты мне скажи, а что ты делаешь с дробными тругольниками между
>границ узлов? Мне самому интересно, что люди применяют ;)
Я просто пробовал вести учет индексов тех полигонов которые уже попали в узел.

т.е. просто перед добавление смотрел
находится ли он в узле или нет... но там что-то не получилось.Мне кажется для

больших сцен процент дублей не окажет большого влияния на производительность

Sandman
>Ничего удивительного, что тормозит. Ты ведь по одному треугольнику рисуешь, да ещё и каждый треугольник на >попадание в фрустум проверяешь....
Пробовал отключать проверку в frustum эффект такой-же...
скажи а как это влияет ведь и там и там по 1 треугольнику, что скажешь?

Правка: 26 мая 2005 10:00

Рендер через Octree-дерева:FPS низок по сравнению с прямым рендером.Прошу помощи.26 мая 20059:30#4
Продолжение
		//установить максимальную точку
		boundingBox.SetMaxPoint(Max);
		//установить минимальную точку
		boundingBox.SetMinPoint(Min);
		//получить дочерний узел
		childNode = node -> GetChildNode(i);
		//цикл по полигонам
		for (j = 0; j < num; j++) {
			//Вершина 1
			vert0 = model -> GetVertice(j).vert[0];
			//Вершина 2
			vert1 = model -> GetVertice(j).vert[1];
			//Вершина 3
			vert2 = model -> GetVertice(j).vert[2];
			//проверить нахождение 3 точек полигона в ограничивающем теле
			if (boundingBox.contains(vert0, vert1, vert2)) {
				//если не был создан
				if (!childNode) {
					childNode = new OctreeNode;
					childNode -> GetBoundingBox().SetMaxPoint(Max);
					childNode -> GetBoundingBox().SetMinPoint(Min);
				}
				//добавить индекс в узел
				childNode -> AddIndexPoligon(j);
				//Если получилось большее число полигонов
				if (childNode -> GetNumberPoligons() > OctreeNode::NUMBERPOLIGONS) {
					break;//выйти из цикла
				}
			}
		}
		//установить указатель на узел
		node -> SetChild(childNode, i);
		//если существует узел
		if (childNode)
			//если число полигонов превышает
			if (childNode -> GetNumberPoligons() > OctreeNode::NUMBERPOLIGONS) {
				childNode -> ClearPoligons();
				//Обработка дочернего узла узла
				ProcessingNode(model, childNode, Depth + 1);
			}
			else
				childNode -> SetLeaf();//узел является листом
	}
}
Теперь самое главное рендеринг Octree-дерева:
//отображение дерева
void Octree::Draw(Mesh *mesh, OctreeNode *&node, const Frustum& frustum)
{
	if (!node)
		return;
	//отображение Bounding Box'а для отладки
	if (DrawBox)
		node -> DrawBoundingBox();
	//Если нет потомков
	//отобразить узел
	if (node -> IsLeaf()) {
		node -> Draw(model, frustum);
...
		return;
	}
	int i;
	//дочерний узел
	OctreeNode *childNode;
	//цикл по дочерним узлам
	for (i = 0; i < 8; i++) {
		//получить дочерний узел
		childNode = node -> GetChildNode(i);
		//если узел существует
		if (childNode)
			//проверка нахождения в пирамиде видимости
			if (frustum.BoundingBoxInFrustum(childNode -> GetBoundingBox()))
				//рекурсивное отображение остальных узлов
				Draw(mesh, childNode, frustum);
	}
}
//отображение узла
void OctreeNode::Draw(Mesh *mesh, const Frustum& frustum)
{
	if (!mesh)
		return;
	Vector3D Normal;
	int i;
	Vector4D v;
	int k = 0;
	int index = 0;
	int Id;
	//число полигонов
	int Number = int(indexs.size());
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	Vector3D v0;
	Vector3D v1;
	Vector3D v2;
	Vector2D tvert;
	Mesh::Vertice *vertice;
	glEnable(GL_TEXTURE_2D);
	//обнулить число полигонов
	nPoligons = 0;
	//проход по граням
	for (i = 0; i < Number; i ++)  {
		//получить индекс
		index = indexs[i];
		//получить index грань
		vertice = &mesh -> GetVertice(index);
		//если есть материалы
		if (mesh -> MaterialsIsOk()) {
			//получить индекс материала
			Id = vertice -> MatId;
			//если индекс другой
			if (k != Id) {
				//запомнить его
				k = Id;
				//отражение
				float shininess;
				//индекс текстуры
				unsigned int TextId = mesh -> GetTextureDiffuseId(Id);
					glBindTexture(GL_TEXTURE_2D, TextId);
				//получить спекулярный цвет материала
				v = mesh -> GetSpecular(Id);
				//Спекулярная состовляющая материала
				glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &v[0]);
				//получить диффузионный цвет материала
				v = mesh -> GetDiffuse(Id);
				//Диффузионная состовляющая материала
				glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, &v[0]);
				//Получить Фоновый цвет для материала
				v = mesh -> GetAmbient(Id);
				//модель освещения
				glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &v[0]);
				//Фоновая состовляющая материала
				glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, &v[0]);
				//получить отражение
				shininess = mesh -> GetShininess(Id);
				//Отраженная состовляющая материала
				glMaterialfv(GL_FRONT, GL_SHININESS, &shininess);
			}
		}
		//получить 1 вершину
		v0 = vertice -> vertex[0].vert;
		//получить 2 вершину
		v1 = vertice -> vertex[1].vert;
		//получить 3 вершину
		v2 = vertice -> vertex[2].vert;
...
			//если треугольник в пирамиде видимости
			if (frustum.TriangleInFrustum(v0, v1, v2)) {
				//установить смешанный массив
				glInterleavedArrays(GL_T2F_N3F_V3F, 0, vertice -> vertex);
				//отобразить 3 эелемента
				glDrawArrays(GL_TRIANGLES, 0, 3);
			}
...
	}
	glDisable(GL_TEXTURE_2D);
}
В конечном этоге получается вот такое разбиение сцены со сложной геометрией:
Изображение удалено
Скажите что тут может быть не так? может нужно пересмотреть или где-то есть ошибка но я не мог ее найти?
ведь строиться дерево правильно. Очень прошу помощи в плане оптимизации я стою на месте...
Буду рад любому совету(дельному)
Спасибо всем заранее.
С уважением Андрей.

Правка: 26 мая 2005 9:33

Рендер через Octree-дерева:FPS низок по сравнению с прямым рендером.Прошу помощи.26 мая 20059:30#3
//Обработка узла
void Octree::ProcessingNode(Mesh* model, OctreeNode *&node, int Depth)
{
	//выход при нулевом узле
	if (!node)
		return;
	//проверка глубины разбиения
	if (Depth > DepthOctree)
		return;
	//если узел является листом
	if (node -> IsLeaf())
		return;
	//Вершина 1
	Vector3D vert0;
	//Вершина 1
	Vector3D vert1;
	//Вершина 2
	Vector3D vert2;
	int i = 0;
	int j = 0;
	int l = 0;
	//указатель на ограничивающее тело
	AABB *BoundingBox = &node -> GetBoundingBox();
	//число полигонов
	int num = model -> GetNumFaces();
	//индекс занят индекса
	bool occuped = false;
	//цикл по полигонам
	for (j = 0; j < num; j++) {
		//Вершина 1
		vert0 = model -> GetVertice(j).vertex[0].vert;
		//Вершина 2
		vert1 = model -> GetVertice(j).vertex[1].vert;
		//Вершина 3
		vert2 = model -> GetVertice(j).vertex[2].vert;
		//проверить нахождение 3 точек полигона в ограничивающем теле
		if (BoundingBox -> contains(vert0, vert1, vert2)) {
			//добавить индекс в узел
			node -> AddIndexPoligon(j);
			//Если получилось большее число полигонов
			if (node -> GetNumberPoligons() > OctreeNode::NUMBERPOLIGONS) {
				//очистить
				//node -> ClearPoligons();
				break;//выйти из цикла
			}
		}
	}
	//если число полигонов меньше чем нужно то это  является листом
	if (node -> GetNumberPoligons() <= OctreeNode::NUMBERPOLIGONS) {
		//установить флаг листа
		node -> SetLeaf();
		return;
	}
	else//очистить полигоны
		node -> ClearPoligons();
	//обработка
	//максимальная точка
	Vector3D max;
	//минмимальная точка
	Vector3D min;
	//разница между координатами
	float dz = 0;
	//середина по координате x
	float dcenterx = 0;
	//середина по координате y
	float dcentery = 0;
	//середина по координате z
	float dcenterz = 0;
	//для прибавления
	float k = 0;
	//временный вектор
	Vector3D Min;
	//временный вектор
	Vector3D Max;
	//дочерний узел
	OctreeNode *childNode = NULL;
	//получить максимальную точка
	max = node -> GetBoundingBox().GetMaxPoint();
	//получить минимальную точку
	min = node -> GetBoundingBox().GetMinPoint();
	//4 это - 2 по 4 всего 8 дочерних
	dz = (max.z  - min.z) / 4;
	//середина по координате x
	dcenterx = (max.x - min.x) / 2;
	//середина по координате y
	dcentery = (max.y - min.y) / 2;
	//середина по координате z
	dcenterz = (max.z - min.z) / 2;
	//ограничивающий бокс узла
	AABB boundingBox;
	//цикл по 8 дочерним узлам
	for (i = 0; i < 8; i++) {
		//сохранить значение
		Min = min;
		//сохранить значение
		Max = max;
		//в зависимости от номера
		switch (i) {
			//расчет max и min точек BoundingBox'а для 0 дочернего бокса
			case 0: {
				Max.x -= dcenterx;
				Max.y -= dcentery;
				Max.z -= dcenterz;
			}
			break;
			//расчет max и min точек BoundingBox'а для 1 дочернего бокса
			case 1: {
				Min.y += dcentery;
				Max.z -= dcenterz;
				Max.x -= dcenterx;
			}
			break;
			//расчет max и min точек BoundingBox'а для 2 дочернего бокса
			case 2: {
				Min.z += dcenterz;
				Max.y -= dcentery;
				Max.x -= dcenterx;
			}
			break;
			//расчет max и min точек BoundingBox'а для 3 дочернего бокса
			case 3: {
				Min.z += dcenterz;
				Min.y += dcentery;
				Max.x -= dcenterx;
			}
			break;
			//расчет max и min точек BoundingBox'а для 4 дочернего бокса
			case 4: {
				Min.x += dcenterx;
				Max.z -= dcenterz;
				Max.y -= dcentery;
			}
			break;
			//расчет max и min точек BoundingBox'а для 5 дочернего бокса
			case 5: {
				Min.x += dcenterx;
				Min.y += dcentery;
				Max.z -= dcenterz;
			}
			break;
			//расчет max и min точек BoundingBox'а для 6 дочернего бокса
			case 6: {
				Min.x += dcenterx;
				Min.z += dcenterz;
				Max.y -= dcentery;
			}
			break;
			//расчет max и min точек BoundingBox'а для 7 дочернего бокса
			case 7: {
				Min.x += dcenterx;
				Min.z += dcenterz;
				Min.y += dcentery;
			}
		}

Правка: 26 мая 2005 9:41

Рендер через Octree-дерева:FPS низок по сравнению с прямым рендером.Прошу помощи.26 мая 20059:27#2
Итак теперь представлю код построения дерева думаю без него не особо будет понятно как я произвожу рендер:
//построение octree
void Octree::BuildOctree(Mesh* model)
{
	if (!model)
		return;
	if (root == NULL) {
		root = new OctreeNode;
		int i;
		//число полигонов
		int num = int(model -> GetNumFaces());
		//получить Bounding Box узла
		AABB* bbox = &root -> GetBoundingBox();
		//грань
		Mesh::Vertice* vertice = &model -> GetVertice(0);
		//инициализация минимальной точки
		bbox -> SetMaxPoint(vertice -> vert[0]);
		//инициализация максимальной точки точки
		bbox -> SetMinPoint(vertice -> vert[1]);
		//вершина
		Vector3D v;
		//цикл по граням
		for (i = 0; i < num; i++) {
			//получить грань
			vertice = &model -> GetVertice(i);
			//получить 1 вершину
			v = vertice -> vert[0];
			//добавить 1 вершину
			bbox -> AddVertex(v);
			//получить 2 вершину
			v = vertice -> vert[1];
			//добавить 2 вершину
			bbox -> AddVertex(v);
			//получить 3 вершину
			v = vertice -> vert[2];
			//добавить 3 вершину
			bbox -> AddVertex(v);
		}
	}
	//начинаем с корневого узла
	ProcessingNode(model, root, 0);
	ok = true;
	MessageBox(NULL, "Octree build complete", "Info", MB_OK);
}

Правка: 26 мая 2005 9:40

Рендер через Octree-дерева:FPS низок по сравнению с прямым рендером.Прошу помощи.26 мая 20059:26#1
класс AABB выглядет просто:
//Класс AABB (Axis-Aligned Bounding Box)
class AABB {
private:
	...
	//Максимальная точка
	Vector3D maxPoint;
	//Минимальная точка
	Vector3D minPoint;
public:
	//добавление вершины
	void AddVertex(const Vector3D& vert)
	{
		//проверка границ
		if (minPoint.x > vert.x)
			minPoint.x = vert.x;
		if (minPoint.y > vert.y)
			minPoint.y = vert.y;
		if (minPoint.z > vert.z)
			minPoint.z = vert.z;

		if (maxPoint.x < vert.x)
			maxPoint.x = vert.x;
		if (maxPoint.y < vert.y)
			maxPoint.y = vert.y;
		if (maxPoint.z < vert.z)
			maxPoint.z = vert.z;
	}
...
	//Установка новой минимальной точки
	void SetMinPoint(const Vector3D& newPoint)
	{
		minPoint = newPoint;
	}
	//Установка новой максимальной точки
	void SetMaxPoint(const Vector3D& newPoint)
	{
		maxPoint = newPoint;
	}
...
	//возврат минимальной точки
	inline const Vector3D& GetMinPoint() const
	{
		return minPoint;
	}
	//возврат максимальной точки
	inline const Vector3D& GetMaxPoint()
	{
		return maxPoint;
	}
	//содерхание точки в Bounding Box'е
	inline bool contains(const Vector3D& point) const
	{


		//проверить нахождение точки в границах
		return ((point.x >= minPoint.x && point.x <= maxPoint.x) &&
				(point.y >= minPoint.y && point.y <= maxPoint.y) &&
				(point.z >= minPoint.z && point.z <= maxPoint.z));

	}
	//проверить содержание полигона в AABB
	inline bool contains(const Vector3D& v0, const Vector3D& v1,
		const Vector3D& v2) const
	{

		return (contains(v0) || contains(v1) || contains(v2));

	}
	inline AABB(const AABB& aabb) : maxPoint(aabb.maxPoint),
		minPoint(aabb.minPoint) {}
	inline AABB(const Vector3D& MaxP, const Vector3D& MinP) :
		maxPoint(MaxP), minPoint(MinP) {}
...
	AABB(){};
	~AABB(){};
};
#endif
последний класс это само Octree-дерево
//класс Octree-дерева
class Octree {
private:
...
	//занятые индексы
	vector<int> indexsOccuped;
	//Глубина разбиения
	int DepthOctree;
	//ссылка на mesh
	Mesh *mesh;
	//узел дерева
	OctreeNode *root;
	//дерево построено
	bool ok;
...
	//Обработка узла
	void ProcessingNode(Mesh* model, OctreeNode *&node, int Depth);
...
	//отображение дерева
	void Draw(Mesh *mesh, OctreeNode *&node, const Frustum& frustum);
public:
...
	//Установить глубину разбиения
	void SetDepth(int depth)
	{
		DepthOctree = depth;
	}
	//установка ссылки на Mesh
	void SetMesh(Mesh *Model)
	{
		mesh = Model;
	}
	//отображения дерева
	void DrawOctree(Camera& camera)
	{
		if (ok)
		Draw(mesh, root, camera.GetFrustum());

	}
...
	//построение octree
	void BuildOctree(Mesh* model);
	Octree() : root(NULL), mesh(NULL), DepthOctree(0), ok(false)

	{};
	~Octree()
	{
		delete root;
		root = NULL;
	};
};
#endif

Правка: 26 мая 2005 9:38

Рендер через Octree-дерева:FPS низок по сравнению с прямым рендером.Прошу помощи.26 мая 20059:25#0
Привет всем!!!
построил Octree-дерево. при отрисовки скорость рендера с помощью Octree меньше чем при обычном рендере.
Строил дерево как обычно в итоге получалось что в листьях имеются индексы по которым можно брать из массива полигоны
сцены.При рендере через Octree-дерево FPS падает... точно сказать не могу во сколько но не в 2 раза... приблизительно 50%разница в FPS. Для рендера использую OpenGL, вертикальная синхронизация отключена.Я думаю что бы было понятно приведу код.
Начну с Mesh'а который используется для рендера сцены:(Mesh пока может не оптимизирован)
//Класс мешь
class Mesh {
public:
	//класс материала
	class Material {
	private:
		//Амбиент свойство
		Vector4D Ambient;
		//Diffuse свойство
		Vector4D Diffuse;
		//Specular свойство
		Vector4D Specular;
		//текстура Diffuse
		unsigned int TextureDiffuseId;
		//текстура Bump
		unsigned int TextureBumpId;
		//сомоосвещение
		float shininess;
	public:
		//возврат самоосвешение
		inline float GetShininess() const
		{
			return shininess;
		}
...
		//возврат specular свойства
		inline const Vector4D& GetDiffuse() const
		{
			return Diffuse;
		}
...
		//возврат specular свойства
		inline const Vector4D& GetSpecular() const
		{
			return Specular;
		}
		//возврат ambient свойства
		inline const Vector4D& GetAmbient() const
		{
			return Ambient;
		}
...
		//возврат индекса Diffuse текстуры
		inline unsigned int GetTextureDiffuseId() const
		{
			return TextureDiffuseId;
		}
		//возврат Bump текстуры
		inline unsigned int GetTextureBumpId() const
		{
			return TextureBumpId;
		}
...
	};
	//вершина
	struct Vertex {
		//Текстурные координаты
		Vector2D tvert;
		//Нормали
		Vector3D normal;
		//координаты вершины
		Vector3D vert;
	};
	//Грань
	class Vertice {
	public:
		//индекс материала
		char MatId;
		//3 Вершины полигона
		Vertex vertex[3];
	};
private:
...
	//материалы
	vector<Material> materials;
	//Массив граней
	vector<Vertice> vertices;
public:
	//присутвие материалов
	inline bool MaterialsIsOk() const
	{
		return !materials.empty();
	}
	//возвратить отражение
	inline float GetShininess(int MatId)
	{
		return materials[MatId].GetShininess();
	}
	//индекс диффузионной текстуры
	inline unsigned int GetTextureDiffuseId(int MatId) const
	{
		return materials[MatId].GetTextureDiffuseId();
	}
	//индекс bump текстуры
	inline unsigned int GetTextureBumpId(int MatId) const
	{
		return materials[MatId].GetTextureBumpId();
	}
	inline const Vector4D& GetAmbient(int MatId) const
	{
		return materials[MatId].GetAmbient();
	}
	inline const Vector4D& GetDiffuse(int MatId) const
	{
		return materials[MatId].GetDiffuse();
	}
	inline const Vector4D& GetSpecular(int MatId) const
	{
		return materials[MatId].GetSpecular();
	}
...
	inline int GetNumFaces() const //число граней
	{
		return vertices.size();
	}
...
	//возврат грани
	inline Vertice& GetVertice(int index)
	{
		return vertices[index];
	}
	Mesh() {};
	~Mesh(){};
};
#endif
итак надеюсь с Mesh'ем все понятно.Вот так я представляю узел Octree-дерева:
//класс узла octree
class OctreeNode {
private:
...
	//флаг показывающий что узел является листом дерева
	bool isLeaf;
	//ограничивающее тело
	AABB Box;
	//индексы
	vector<int> indexs;
	//дети узла
	OctreeNode *child[8];
public:
	enum {
		NUMBERPOLIGONS = 100//максимальное число полигонов в узле
	};
...
//вернуть массив индексов
	inline const vector<int>& GetIndexs() const
	{
		return indexs;
	}
	//учтановка листа
	void SetLeaf()
	{
		isLeaf = true;
	}
	//Возврат флага узла
	inline bool IsLeaf() const
	{
		return isLeaf;
	}
	//очистить
	void ClearPoligons()
	{
		indexs.clear();
	}
	//возврат числа полигонов
	inline int GetNumberPoligons() const
	{
		return int(indexs.size());
	}
...
	//отображение узла
	void Draw(Mesh *model, const Frustum& frustum);
	//добавить индекс
	void AddIndexPoligon(const int index)
	{
		indexs.push_back(index);
	}
	//возвратить указатель на i-сына
	inline OctreeNode* GetChildNode(int i)
	{
		return child[i];
	}
	//присвоить новый узел
	void SetChild(OctreeNode* node, int index)
	{
		child[index] = node;
	}
	//возвратить ограничивающее тело
	inline AABB& GetBoundingBox()
	{
		return Box;
	}
	OctreeNode() : isLeaf(false)
	{
		//обнуление указателей
		memset(child, NULL, sizeof(child));
	};
	~OctreeNode()
	{
		//рекурсивное уаление
		for (int i = 0; i < 8; i++) {
			if (child[i])
				delete child[i];
			child[i] = NULL;
		}
	};
};

Правка: 26 мая 2005 9:35

GUNgine20 мая 20059:01#634
Maclaud
на чем компилируешь? там ве компилируеться на Visual C++ 6.0 с небольшими исправлениями некоторых мест...
на Visual C++ .Net 2002 компилируеться без проблем...
1C идёт на запад18 мая 200513:24#28
LS
>Значит - небольшие разработчики из провинции(!!!) никуда не денутся, только им будет немного сложнее маневрировать. И >лучший выход для них, мне кажется, это захватывающие и оригинальные проекты, не обладающие большим бюджетом.
-=InQ=-
>А его некому выдавать в провинции

обидная реальность....
-=InQ=-
>У нас программистов учат паскалю
у нас в институте раньше учили, теперь еще мышкой щелкать умеют :))GLoom
GLoom
>А мне вот страшненько. Столько лет убил на развитие в сторону PC
не переживай все у тебя получиться... ты человек с опытом и знаниями

MAX7 SDK14 мая 200514:21#10
VitGun
Имне пожалуйста!!
только если не сложно по частям по 1 метру
заранее спасибо :)
Поздравляем CEMEHа с днём рождения!!!12 мая 200513:04#40
Семен
Я присоеденяюсь к поздравлениям!!! всего тебе чего сам пожелаешь!!!
OpenGL vs DirectX или на чем лучше(легче:)) писать движок?11 мая 20059:04#15
Win32
лучше знать оба API, а качество написания  движков зависит не от API, а от кривизны рук :)
C++. Указатель на функцию-компонент класса. ?6 мая 200517:58#2
sdTolik
Ну на сколько я понял вот так попробуй:
class СD
{
public:
   CD(void CD::*ptrFunc());

   void DoFunc();

private:
   void (*func_ptr)(void);
};
...
//.cpp file
CA::CA()
{
   pD = new CD(void CD::*func_ptr ());
}
...
CD::CD(void CD::*func_ptr ())
{
   this->func_ptr = func_ptr;
}
Камера в Direct3D и OpenGL: почему в Direct3D работает неправильно?6 мая 20059:19#14
IPSer
Все получилось, поставил минус в повороте камеры
crazy25,IPSer,jm
Всем большое спасибо!!!!!! тема закрыта.
Камера в Direct3D и OpenGL: почему в Direct3D работает неправильно?6 мая 20059:10#13
IPSer
Спасибо большое!!!!! все заработало...
только во еще 1 мелочь как заставить что бы камера поворачивалась обратно перемещению мыши в плоскости X0Z?
т.е. мышью двиоаю влево камера вправо и наоборот?

Следующие темы >>

2001—2012 © GameDev.ru — Разработка игр