So I've had this problem for some time now and I'm hoping you guys have a solution for it. I'm trying to create chunks through a thread, and then add the chunk to my list in my main class, where I so draw the chunk. But it fails when trying to set the VBO that contains the vertices of a cube, and I get this exception: 'System.AccessViolationException'.
This is my code for the cube:
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);
}
This is my code in my main class:
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 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));
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.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));
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 (x == prevX && y == prevY) return;
if (prevX == 0 && prevY == 0)
{
Program.WarpPointer(width / 2, height / 2);
prevX = x;
prevY = y;
return;
}
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;
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)
{
chunks.Add(new Chunk(pos, size));
}
public override void OnClose()
{
if (chunkThread != null) chunkThread.Abort();
base.OnClose();
}
}
}
Code for the Chunk:
using System;
using OpenGL;
using Tao.FreeGlut;
using System.Collections.Concurrent;
namespace OpenGLTutorial1
{
public class Chunk
{
public Vector3 position;
public ConcurrentBag blocks;
public Vector2 Size;
public Chunk(Vector3 pos, int size)
{
position = pos * new Vector3(size*2, size*2, size*2);
blocks = new ConcurrentBag();
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));
}
Size = new Vector2(size, size);
}
public void Draw(ref ShaderProgram program)
{
foreach(var item in blocks)
{
Block block = (Block)item;
block.Draw(ref program);
}
}
}
}
Code for Block:
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();
}
}
Here is the source
What I have tried:
I've tried to switch from a List<chunk> to a ConcurrentBag<chunk>, because that is thread safe, so that might not be the problem. I'm pretty new to OpenGL and I'm not used to threads and stuff, sooooo yeah.