Проблемы потока C# с opengl и списками!
Так что у меня уже давно есть эта проблема, и я надеюсь, что у вас, ребята, есть решение для нее. Я пытаюсь создать куски через поток, а затем добавить этот кусок в свой список в моем основном классе, где я так рисую этот кусок. Но он терпит неудачу при попытке установить VBO, содержащий вершины Куба, и я получаю это исключение: "система.AccessViolationException'.
Это мой код для куба:
public Cube(Vector3 pos, float dimension) { position = pos; dimensions = dimension; float cubePos = dimension; cube = new VBO(new Vector3[] { new Vector3(cubePos, cubePos, -cubePos), new Vector3(-cubePos, cubePos, -cubePos), new Vector3(-cubePos, cubePos, cubePos), new Vector3(cubePos, cubePos, cubePos), new Vector3(cubePos, -cubePos, cubePos), new Vector3(-cubePos, -cubePos, cubePos), new Vector3(-cubePos, -cubePos, -cubePos), new Vector3(cubePos, -cubePos, -cubePos), new Vector3(cubePos, cubePos, cubePos), new Vector3(-cubePos, cubePos, cubePos), new Vector3(-cubePos, -cubePos, cubePos), new Vector3(cubePos, -cubePos, cubePos), new Vector3(cubePos, -cubePos, -cubePos), new Vector3(-cubePos, -cubePos, -cubePos), new Vector3(-cubePos, cubePos, -cubePos), new Vector3(cubePos, cubePos, -cubePos), new Vector3(-cubePos, cubePos, cubePos), new Vector3(-cubePos, cubePos, -cubePos), new Vector3(-cubePos, -cubePos, -cubePos), new Vector3(-cubePos, -cubePos, cubePos), new Vector3(cubePos, cubePos, -cubePos), new Vector3(cubePos, cubePos, cubePos), new Vector3(cubePos, -cubePos, cubePos), new Vector3(cubePos, -cubePos, -cubePos) }); color = new VBO(new Vector3[] { new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 1), }); elements = new VBO(new int[] { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23}, BufferTarget.ElementArrayBuffer); }
Это мой код в моем основном классе:
using System; using System.Threading; using System.Windows.Forms; using System.Collections.Generic; using OpenGL; using Tao.FreeGlut; using System.Collections.Concurrent; namespace OpenGLTutorial1 { public class Game1 : Game { private Block block; private Camera camera; private bool left = false, forward = false, back = false, right = false, up = false; //private List chunks = new List(); private ConcurrentBag chunks = new ConcurrentBag(); private Thread chunkThread; private Vector3 nextChunk; public override void LoadContent() { camera = new Camera(new Vector3(0, 50, 0), Quaternion.Identity); camera.SetDirection(new Vector3(0, 0, -1)); //cube1 = new Cube(Vector3.Zero, 1, "dirt.jpg"); Program.SetCursor(Glut.GLUT_CURSOR_NONE); Global.Manager.LoadBlocks("Blocks.xml"); block = Global.Manager.NewBlock(new Vector3(0, 0, 0), 0); chunks.Add(new Chunk(Vector3.Zero, 8)); chunkThread = new Thread(CreateChunk); //chunkThread.SetApartmentState(ApartmentState.STA); chunkThread.Start(); nextChunk = new Vector3(startChunk.X, startChunk.Y, startChunk.Z); Program.SetViewMatrix(camera.ViewMatrix); base.LoadContent(); } private static float add = 0; private static int speed = 5; public override void Update(float deltaTime) { Program.SetViewMatrix(camera.ViewMatrix); if (back) camera.MoveRelativeXZ(Vector3.UnitZ * deltaTime * speed); if (forward) camera.MoveRelativeXZ(-Vector3.UnitZ * deltaTime * speed); if (left) camera.MoveRelativeXZ(-Vector3.UnitX * deltaTime * speed); if (right) camera.MoveRelativeXZ(Vector3.UnitX * deltaTime * speed); if (up) camera.Move(new Vector3(0, deltaTime * 2.5f, 0)); /*add += deltaTime*100; if (add >= 20) { CreateChunk(); add = 0; }*/ base.Update(deltaTime); } public override void Draw(ref ShaderProgram program) { block.Draw(ref program); foreach (var item in chunks) { Chunk chunk= (Chunk)item; chunk.Draw(ref program); } base.Draw(ref program); } public override void OnKeyboardDown(byte key, int x, int y) { if (key == 'd') right = true; else if (key == 'a') left = true; else if (key == 'w') forward = true; else if (key == 's') back = true; else if (key == ' ') up = true; base.OnKeyboardDown(key, x, y); } public override void OnKeyboardUp(byte key, int x, int y) { if (key == 'd') right = false; else if (key == 'a') left = false; else if (key == 'w') forward = false; else if (key == 's') back = false; else if (key == ' ') up = false; base.OnKeyboardUp(key, x, y); } private int prevX = 0, prevY = 0; public override void OnMove(int x, int y) { // if the mouse move event is caused by glutWarpPointer then do nothing if (x == prevX && y == prevY) return; if (prevX == 0 && prevY == 0) { Program.WarpPointer(width / 2, height / 2); prevX = x; prevY = y; return; } // move the camera when the mouse is down float yaw = -(x - width / 2) * 0.002f; camera.Yaw(yaw); float pitch = -(y - height / 2) * 0.002f; camera.Pitch(pitch); prevX = x; prevY = y; Program.WarpPointer(width / 2, height / 2); base.OnMove(x, y); } private int layerIndex = 0; private int layerDim = 2; private int state = 0; private Vector3 startChunk = new Vector3(-1, 0, -1); private void CreateChunk() { while (true) { int size = 8; //chunks.Add(new Chunk(new Vector3(nextChunk.X, nextChunk.Y, nextChunk.Z), size)); //Console.WriteLine(nextChunk.X.ToString() + ", " + nextChunk.Y.ToString() + ", " + nextChunk.Z.ToString()); AddChunkFromThread(new Vector3(nextChunk.X, nextChunk.Y, nextChunk.Z), size); if (state == 0) nextChunk.X++; else if (state == 1) nextChunk.Z++; else if (state == 2) nextChunk.X--; else if (state == 3) nextChunk.Z--; layerIndex++; if (layerIndex >= layerDim) { layerIndex = 0; state++; } if (state == 4) { layerDim += 2; startChunk = new Vector3(startChunk.X - 1, 0, startChunk.Z - 1); nextChunk = new Vector3(startChunk.X, startChunk.Y, startChunk.Z); state = 0; } } } private void AddChunkFromThread(Vector3 pos, int size) { /*if (this.InvokeRequired) this.Invoke(new MethodInvoker(AddChunkFromThread)); else { chunks.Add(new Chunk(pos, size)); }*/ chunks.Add(new Chunk(pos, size)); } public override void OnClose() { /*for (int i = 0; i < chunks.Count; i++) { for (int q = 0; q < chunks[i].block.GetLength(1); q++) for (int y = 0; y < chunks[i].block.GetLength(0); y++) chunks[i].block[y, q].Dispose(); }*/ if (chunkThread != null) chunkThread.Abort(); base.OnClose(); } } }
Код для куска:
using System; using OpenGL; using Tao.FreeGlut; using System.Collections.Concurrent; namespace OpenGLTutorial1 { public class Chunk { public Vector3 position; //public Block[,] block; public ConcurrentBag blocks; public Vector2 Size; public Chunk(Vector3 pos, int size) { position = pos * new Vector3(size*2, size*2, size*2); //block = new Block[size, size]; blocks = new ConcurrentBag(); /*for(int z = 0; z < block.GetLength(1); z++) for(int x = 0; x < block.GetLength(0); x++) { block[x, z] = new Block((x*2)+ position.X, position.Y,(z*2)+ position.Z, 0); }*/ for (int z = 0; z < size; z++) for (int x = 0; x < size; x++) { blocks.Add(new Block((x * 2) + position.X, position.Y, (z * 2) + position.Z, 0)); //block[x, z] = new Block((x * 2) + position.X, position.Y, (z * 2) + position.Z, 0); } Size = new Vector2(size, size); } public void Draw(ref ShaderProgram program) { /*for (int z = 0; z < block.GetLength(1); z++) for (int x = 0; x < block.GetLength(0); x++) { blocks[x, z].Draw(ref program); }*/ foreach(var item in blocks) { Block block = (Block)item; block.Draw(ref program); } } } }
Код для блока:
public class Block { public Vector3 position; public string name; public Texture texture; private Cube cube1; public Block(float x, float y, float z, int id) { position = new Vector3(x, y, z); cube1 = new Cube(position, 1); } public void SetTexture(Texture newTexture) { texture = newTexture; cube1.SetTexture(newTexture); } public void Draw(ref ShaderProgram program) { cube1.Draw(ref program); } public void Dispose() { cube1.Dispose(); } }
Вот источник:
Что я уже пробовал:
Я попытался переключиться с List<chunk> На ConcurrentBag<chunk>, потому что это потокобезопасно, так что это может быть не проблема. Я довольно новичок в OpenGL и не привык к потокам и тому подобному, оооочень да.