XNA 2D Occlusion Culling
| |
dima13230 | Дата: Четверг, 24 Марта 2016, 00:33 | Сообщение # 1 |
частый гость
Сейчас нет на сайте
| Не получается сделать так, чтобы если камера не видит тайл, он не отображался. Всё это происходит в 2D среде. Вот скрипт камеры:
Код using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Terraria.Input; using Microsoft.Xna.Framework.Input;
namespace 2DBlocks { public class Camera { protected float _zoom; // Camera Zoom public Matrix _transform; // Matrix Transform public Vector2 _pos; // Camera Position protected float _rotation; // Camera Rotation public Game1 game;
public Camera(Game1 Game) { _zoom = 1.0f; _rotation = 0.0f; _pos = Vector2.Zero; game = Game; }
// Sets and gets zoom public float Zoom { get { return _zoom; } set { _zoom = value; if (_zoom < 0.1f) _zoom = 0.1f; } // Negative zoom will flip image }
public float Rotation { get { return _rotation; } set { _rotation = value; } }
// Auxiliary function to move the camera public void Move(Vector2 amount) { _pos += amount; } // Get set position public Vector2 Pos { get { return _pos; } set { _pos = value; } }
public Matrix get_transformation(GraphicsDevice graphicsDevice) { _transform = // Thanks to o KB o for this solution Matrix.CreateTranslation(new Vector3(-_pos.X, -_pos.Y, 0)) * Matrix.CreateRotationZ(Rotation) * Matrix.CreateScale(new Vector3(Zoom, Zoom, 1)) * Matrix.CreateTranslation(new Vector3(game.GraphicsDevice.Viewport.Width * 0.5f, game.GraphicsDevice.Viewport.Height * 0.5f, 0)); return _transform; }
} }
А набор тайлов представляет из себя двумерный массив с координатами x и y. Я думаю, что можно вычислить площадь видимой зоны окна и сравнивать с координатами. Но что точно нужно сделать?
Сообщение отредактировал dima13230 - Четверг, 24 Марта 2016, 00:36 |
|
| |
FlyOfFly | Дата: Четверг, 24 Марта 2016, 00:40 | Сообщение # 2 |
заслуженный участник
Сейчас нет на сайте
| Цитата dima13230 ( )
А набор тайлов представляет из себя двумерный массив с координатами x и y. Я думаю, что можно вычислить площадь видимой зоны окна и сравнивать с координатами. Но что точно нужно сделать?
В таком случае, надо просто не выводить весь массив стразу, а выводить только в радиусе определенном вот допустим типа такого
Код
for(int i = (camera._pos.x/TileSize)-5;i<(camera._pos.x/TileSize)+5;i++){ for(int j = (camera._pos.y/TileSize)-5;j<(camera._pos.y/TileSize)+5;j++){ if(i<0 && i>=MapWidth) continue; if(j<0 && j>=MapHeight) continue; //вывод тайла } }....
Сообщение отредактировал FlyOfFly - Четверг, 24 Марта 2016, 00:41 |
|
| |
dima13230 | Дата: Четверг, 24 Марта 2016, 00:56 | Сообщение # 3 |
частый гость
Сейчас нет на сайте
| Цитата FlyOfFly ( ) Цитата dima13230 ()
А набор тайлов представляет из себя двумерный массив с координатами x и y. Я думаю, что можно вычислить площадь видимой зоны окна и сравнивать с координатами. Но что точно нужно сделать?
В таком случае, надо просто не выводить весь массив стразу, а выводить только в радиусе определенном вот допустим типа такого Код
for(int i = (camera._pos.x/TileSize)-5;i<(camera._pos.x/TileSize)+5;i++){ for(int j = (camera._pos.y/TileSize)-5;j<(camera._pos.y/TileSize)+5;j++){ if(i<0 && i>=MapWidth) continue; if(j<0 && j>=MapHeight) continue; //вывод тайла } }....
Не, не работает, выдаёт исключение OutOfMemory ( наверное вечный цикл... )
|
|
| |
FlyOfFly | Дата: Четверг, 24 Марта 2016, 00:57 | Сообщение # 4 |
заслуженный участник
Сейчас нет на сайте
| Цитата dima13230 ( ) Не, не работает, выдаёт исключение OutOfMemory ( наверное вечный цикл... )
Код for(int i = (camera._pos.x/TileSize)-5;i<(camera._pos.x/TileSize)+5;i++){ for(int j = (camera._pos.y/TileSize)-5;j<(camera._pos.y/TileSize)+5;j++){ if(i<0 || i>=MapWidth) continue; if(j<0 || j>=MapHeight) continue; //вывод тайла, который на i,j } }
Попробуй так
Сообщение отредактировал FlyOfFly - Четверг, 24 Марта 2016, 00:58 |
|
| |
Lertmind | Дата: Четверг, 24 Марта 2016, 01:04 | Сообщение # 5 |
заслуженный участник
Сейчас нет на сайте
| Ты не объяснил как именно у тебя выглядит камера, я нарисовал пример:
Синяя - камера, и тебе надо узнать какие клетки отобразить (с галочкой) и не отображать (с крестиком)? UPD: Понял, у тебя нет направления.
Сообщение отредактировал Lertmind - Четверг, 24 Марта 2016, 01:07 |
|
| |
dima13230 | Дата: Четверг, 24 Марта 2016, 01:07 | Сообщение # 6 |
частый гость
Сейчас нет на сайте
| Спасибо! Только радиус увеличу, а то отображается лишь малая часть тайлов :-) Добавлено (24 марта 2016, 01:07) ---------------------------------------------
Цитата Lertmind ( ) Ты не объяснил как именно у тебя выглядит камера, я нарисовал пример:
Синяя - камера, и тебе надо узнать какие клетки отобразить (с галочкой) и не отображать (с крестиком)?
Камера квадратная. Отображает вид сбоку.
|
|
| |
FlyOfFly | Дата: Четверг, 24 Марта 2016, 01:08 | Сообщение # 7 |
заслуженный участник
Сейчас нет на сайте
| Цитата Lertmind ( ) Синяя - камера, и тебе надо узнать какие клетки отобразить (с галочкой) и не отображать (с крестиком)?
Читай, внимательно, он написал что камера 2д, этого хватит, что бы понять что он про это
|
|
| |
Lertmind | Дата: Четверг, 24 Марта 2016, 01:10 | Сообщение # 8 |
заслуженный участник
Сейчас нет на сайте
| Цитата dima13230 ( ) Камера квадратная. Отображает вид сбоку. Тогда да, всё просто. Твоё Occlusion Culling ввело в заблуждение, я думал тебе надо отсекать невидимые клетки.
|
|
| |
FlyOfFly | Дата: Четверг, 24 Марта 2016, 01:12 | Сообщение # 9 |
заслуженный участник
Сейчас нет на сайте
| Цитата dima13230 ( ) Спасибо! Только радиус увеличу, а то отображается лишь малая часть тайлов :-) Тогда используй, половины ширины и высоты камеры(делю сначала на TileSize, что бы получить количество возможных тайлов на экране, а половина, так камера у тебя вроде бы по середине)
Код for(int i = (camera._pos.x/TileSize)-Camera_Width/TileSize/2;i<(camera._pos.x/TileSize)+Camera_Width/TileSize/2;i++){ for(int j = (camera._pos.y/TileSize)-Camera_Height/TileSize/2;j<(camera._pos.y/TileSize)+Camera_Height/TileSize/2;j++){ if(i<0 || i>=MapWidth) continue; if(j<0 || j>=MapHeight) continue; //вывод тайла, который на i,j } }
или экрана
Код for(int i = (camera._pos.x/TileSize)-Screen_Width/TileSize/2;i<(camera._pos.x/TileSize)+Screen_Width/TileSize/2;i++){ for(int j = (camera._pos.y/TileSize)-Screen_Height/TileSize/2;j<(camera._pos.y/TileSize)+Screen_Height/TileSize/2;j++){ if(i<0 || i>=MapWidth) continue; if(j<0 || j>=MapHeight) continue; //вывод тайла, который на i,j } }
Сообщение отредактировал FlyOfFly - Четверг, 24 Марта 2016, 01:13 |
|
| |
Lertmind | Дата: Четверг, 24 Марта 2016, 01:12 | Сообщение # 10 |
заслуженный участник
Сейчас нет на сайте
| Цитата Lertmind ( ) Читай, внимательно, он написал что камера 2д, этого хватит, что бы понять что он про это Нет, это не очевидно, я думал он хочет использовать что-то типа фонарика в темноте.
|
|
| |
dima13230 | Дата: Четверг, 24 Марта 2016, 01:19 | Сообщение # 11 |
частый гость
Сейчас нет на сайте
| Цитата Lertmind ( ) что-то типа фонарика в темноте
Возможно и это спрошу потом :-)
Добавлено (24 марта 2016, 01:18) ---------------------------------------------
Цитата FlyOfFly ( ) Спасибо! Только радиус увеличу, а то отображается лишь малая часть тайлов :-)
Тогда используй, половины ширины и высоты камеры(делю сначала на TileSize, что бы получить количество возможных тайлов на экране, а половина, так камера у тебя вроде бы по середине) Код
for(int i = (camera._pos.x/TileSize)-Camera_Width/TileSize/2;i<(camera._pos.x/TileSize)+Camera_Width/TileSize/2;i++){ for(int j = (camera._pos.y/TileSize)-Camera_Height/TileSize/2;j<(camera._pos.y/TileSize)+Camera_Height/TileSize/2;j++){ if(i<0 || i>=MapWidth) continue; if(j<0 || j>=MapHeight) continue; //вывод тайла, который на i,j } }
или экрана Код
for(int i = (camera._pos.x/TileSize)-Screen_Width/TileSize/2;i<(camera._pos.x/TileSize)+Screen_Width/TileSize/2;i++){ for(int j = (camera._pos.y/TileSize)-Screen_Height/TileSize/2;j<(camera._pos.y/TileSize)+Screen_Height/TileSize/2;j++){ if(i<0 || i>=MapWidth) continue; if(j<0 || j>=MapHeight) continue; //вывод тайла, который на i,j } }
Пишет что индекс выходит за пределы массива
Добавлено (24 марта 2016, 01:19) --------------------------------------------- FlyOfFly, может я дам код отображения? Он чуть отличается от того, что ты давал. ( правда суть та же )
Сообщение отредактировал dima13230 - Четверг, 24 Марта 2016, 01:20 |
|
| |
FlyOfFly | Дата: Четверг, 24 Марта 2016, 01:20 | Сообщение # 12 |
заслуженный участник
Сейчас нет на сайте
| Цитата dima13230 ( ) FlyOfFly, может я дам код отображения? Он чуть отличается от того, что ты давал. ( правда суть та же )
Давай
|
|
| |
dima13230 | Дата: Четверг, 24 Марта 2016, 01:22 | Сообщение # 13 |
частый гость
Сейчас нет на сайте
| Код for (int x = ((int)cam.Pos.X / 15) - graphics.GraphicsDevice.Viewport.Width / 15 / 2; x < (cam.Pos.X / 15) + graphics.GraphicsDevice.Viewport.Width / 15 / 2; x++) { for (int y = ((int)cam.Pos.Y / 15) - graphics.GraphicsDevice.Viewport.Height / 15 / 2; y < (cam.Pos.Y / 15) + graphics.GraphicsDevice.Viewport.Height / 15 / 2; y++) { if (tiles[x, y] != null) { if (x < 0 || x >= ViewTilesWidth) continue; if (y < 0 || x >= ViewTilesHeight) continue; int id = (int)tiles[x, y].type;
DrawFrameTile(id, x, y, 0, 0);
} } }
|
|
| |
FlyOfFly | Дата: Четверг, 24 Марта 2016, 01:23 | Сообщение # 14 |
заслуженный участник
Сейчас нет на сайте
| Цитата dima13230 ( ) if (tiles[x, y] != null) {
после Код if (x < 0 || x >= ViewTilesWidth) continue; if (y < 0 || x >= ViewTilesHeight) continue;
|
|
| |
dima13230 | Дата: Четверг, 24 Марта 2016, 01:23 | Сообщение # 15 |
частый гость
Сейчас нет на сайте
| Заодно и сам вызов отображения тайла кинул на всякий случай
|
|
| |
FlyOfFly | Дата: Четверг, 24 Марта 2016, 01:25 | Сообщение # 16 |
заслуженный участник
Сейчас нет на сайте
| Цитата dima13230 ( ) Заодно и сам вызов отображения тайла кинул на всякий случай smile
Код for (int x = ((int)cam.Pos.X / 15) - graphics.GraphicsDevice.Viewport.Width / 15 / 2; x < (cam.Pos.X / 15) + graphics.GraphicsDevice.Viewport.Width / 15 / 2; x++) { for (int y = ((int)cam.Pos.Y / 15) - graphics.GraphicsDevice.Viewport.Height / 15 / 2; y < (cam.Pos.Y / 15) + graphics.GraphicsDevice.Viewport.Height / 15 / 2; y++) { if (x < 0 || x >= ViewTilesWidth) continue; if (y < 0 || x >= ViewTilesHeight) continue; if (tiles[x, y] != null) { int id = (int)tiles[x, y].type;
DrawFrameTile(id, x, y, 0, 0);
} } } вот такой у тебя щас код должен быть
|
|
| |
dima13230 | Дата: Четверг, 24 Марта 2016, 01:26 | Сообщение # 17 |
частый гость
Сейчас нет на сайте
| Спасибо, поставил, включил, там половина экрана отображается, убрал деление на два - стало показывать на полный экран, теперь всё работает так, как нужно :).
|
|
| |
FlyOfFly | Дата: Четверг, 24 Марта 2016, 01:27 | Сообщение # 18 |
заслуженный участник
Сейчас нет на сайте
| Цитата dima13230 ( ) Спасибо, поставил, включил, там половина экрана отображается, убрал деление на два - стало показывать на полный экран, теперь всё работает так, как нужно :). Тогда попробуй так
Код for (int x = ((int)cam.Pos.X / 15); x < (cam.Pos.X / 15) + graphics.GraphicsDevice.Viewport.Width / 15; x++) { for (int y = ((int)cam.Pos.Y / 15); y < (cam.Pos.Y / 15) + graphics.GraphicsDevice.Viewport.Height / 15; y++) { if (x < 0 || x >= ViewTilesWidth) continue; if (y < 0 || x >= ViewTilesHeight) continue; if (tiles[x, y] != null) { int id = (int)tiles[x, y].type;
DrawFrameTile(id, x, y, 0, 0);
} } }
|
|
| |
dima13230 | Дата: Четверг, 24 Марта 2016, 01:28 | Сообщение # 19 |
частый гость
Сейчас нет на сайте
| Если хотите, могу скрин кинуть :))) Добавлено (24 марта 2016, 01:28) ---------------------------------------------
Цитата FlyOfFly ( ) Спасибо, поставил, включил, там половина экрана отображается, убрал деление на два - стало показывать на полный экран, теперь всё работает так, как нужно :).
Тогда попробуй так Код
for (int x = ((int)cam.Pos.X / 15); x < (cam.Pos.X / 15) + graphics.GraphicsDevice.Viewport.Width / 15; x++) { for (int y = ((int)cam.Pos.Y / 15); y < (cam.Pos.Y / 15) + graphics.GraphicsDevice.Viewport.Height / 15; y++) { if (x < 0 || x >= ViewTilesWidth) continue; if (y < 0 || x >= ViewTilesHeight) continue; if (tiles[x, y] != null) { int id = (int)tiles[x, y].type;
DrawFrameTile(id, x, y, 0, 0);
} } }
я это уже и так исправил
|
|
| |
|