Texturing primitives with custom vertex declaration - c#

I'm having a problem with XNA 4.0 and couldn't even google it. It occurs in my main project as well as in my test project which is very plain version to reduce unnecessary code.
I need to use my own custom vertex declaration and use it to draw textured primitives (or why not models too).
Drawing and texturing works fine with BasicEffect and any built-in vertex declarations (like VertexPositionColorTexture)...but what on earth is wrong that textures aren't drawn properly if I use BasicEffect with my custom vertex declaration? I'd love to keep all combinations of built-in types in one VD. My only idea as a fix is that I should make a new vertex/pixel shader but would it help? And if it would, how should I do it?
I tried to upload images to describe but I'd need at least 10 reputation so I'll explain in words:
With my custom VD, textures of my square (and any other shape) object seems to be tiled instead of scaled/fit. Also, textures won't rotate when I rotate the object.
Here's my custom vertex declaration:
namespace WindowsGame2
{
public struct VertexPositionNormalColorTexture : IVertexType
{
public Vector3 Position;
public Vector3 Normal;
public Color Color;
public Vector2 TextureCoordinate;
VertexDeclaration IVertexType.VertexDeclaration
{
get { return VertexDeclaration; }
}
public readonly static VertexDeclaration VertexDeclaration =
new VertexDeclaration(
new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
new VertexElement(sizeof(float) * 3, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0),
new VertexElement((sizeof(float) * 3) * 2, VertexElementFormat.Color, VertexElementUsage.Color, 0),
new VertexElement((sizeof(float) * 3) * 3, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0)
);
public VertexPositionNormalColorTexture(Vector3 p)
{
Position = p;
Normal = Vector3.Zero;
Color = Color.White;
TextureCoordinate = Vector2.Zero;
}
public VertexPositionNormalColorTexture(Vector3 p, Color c)
{
Position = p;
Normal = Vector3.Zero;
Color = c;
TextureCoordinate = Vector2.Zero;
}
public VertexPositionNormalColorTexture(Vector3 p, Vector2 t)
{
Position = p;
Normal = Vector3.Zero;
Color = Color.White;
TextureCoordinate = t;
}
public VertexPositionNormalColorTexture(Vector3 p, Color c, Vector2 t)
{
Position = p;
Normal = Vector3.Zero;
Color = c;
TextureCoordinate = t;
}
public VertexPositionNormalColorTexture(Vector3 p, Vector3 n, Color c)
{
Position = p;
Normal = n;
Color = c;
TextureCoordinate = Vector2.Zero;
}
public VertexPositionNormalColorTexture(Vector3 p, Vector3 n, Vector2 t)
{
Position = p;
Normal = n;
Color = Color.White;
TextureCoordinate = t;
}
public VertexPositionNormalColorTexture(Vector3 p, Vector3 n, Color c, Vector2 t)
{
Position = p;
Normal = n;
Color = c;
TextureCoordinate = t;
}
}
}
And the game class:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace WindowsGame2
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
ViewerManager viewer;
List<VertexPositionNormalColorTexture> vertices;
List<short> indices;
Texture2D thumbnail;
VertexBuffer vertexBuf;
IndexBuffer indexBuf;
RasterizerState rasterizerState;
BasicEffect basicEffect;
Matrix worldMatrix;
Matrix viewMatrix;
Matrix projectionMatrix;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
viewer = new ViewerManager(graphics, new Vector3(0.0f, 0.0f, 5.0f), new Vector3(0.0f, 0.0f, 0.0f), 500);
vertices = new List<VertexPositionNormalColorTexture>() {
new VertexPositionNormalColorTexture(new Vector3(-1, -1, 0), Color.Yellow, new Vector2(0, 1)),
new VertexPositionNormalColorTexture(new Vector3(-1, 1, 0), Color.Yellow, new Vector2(0, 0)),
new VertexPositionNormalColorTexture(new Vector3(1, 1, 0), Color.Yellow, new Vector2(1, 0)),
new VertexPositionNormalColorTexture(new Vector3(-1, -1, 0), Color.Yellow, new Vector2(0, 1)),
new VertexPositionNormalColorTexture(new Vector3(1, 1, 0), Color.Yellow, new Vector2(1, 0)),
new VertexPositionNormalColorTexture(new Vector3(1, -1, 0), Color.Yellow, new Vector2(1, 1)),
};
indices = new List<short>() {
0, 1, 2, 3, 4, 5
};
basicEffect = new BasicEffect(graphics.GraphicsDevice);
worldMatrix = Matrix.CreateTranslation(0.0f, 0.0f, 0.0f) * Matrix.CreateScale(3);
viewMatrix = Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 5.0f), new Vector3(0.0f, 0.0f, 0.0f), Vector3.Up);
projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(90), graphics.GraphicsDevice.Viewport.AspectRatio, 1f, 50f);
vertexBuf = new VertexBuffer(graphics.GraphicsDevice, VertexPositionNormalColorTexture.VertexDeclaration, 500, BufferUsage.WriteOnly);
indexBuf = new IndexBuffer(graphics.GraphicsDevice, IndexElementSize.SixteenBits, 500, BufferUsage.WriteOnly);
rasterizerState = new RasterizerState();
rasterizerState.CullMode = CullMode.None;
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
thumbnail = this.Content.Load<Texture2D>("GameThumbnail");
}
protected override void UnloadContent()
{
this.Content.Unload();
}
protected override void Update(GameTime gameTime)
{
if (Keyboard.GetState().IsKeyDown(Keys.Escape))
this.Exit();
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
graphics.GraphicsDevice.RasterizerState = rasterizerState;
basicEffect.World = worldMatrix;
basicEffect.View = viewMatrix;
basicEffect.Projection = projectionMatrix;
basicEffect.VertexColorEnabled = true;
basicEffect.TextureEnabled = true;
basicEffect.Texture = thumbnail;
vertexBuf.SetData<VertexPositionNormalColorTexture>(vertices.ToArray());
indexBuf.SetData<short>(indices.ToArray());
graphics.GraphicsDevice.SetVertexBuffer(vertexBuf);
graphics.GraphicsDevice.Indices = indexBuf;
foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
{
pass.Apply();
graphics.GraphicsDevice.DrawUserIndexedPrimitives(
PrimitiveType.TriangleList,
vertices.ToArray(),
0,
vertices.Count,
indices.ToArray(),
0,
2,
VertexPositionNormalColorTexture.VertexDeclaration);
}
graphics.GraphicsDevice.Indices = null;
graphics.GraphicsDevice.SetVertexBuffer(null);
base.Draw(gameTime);
}
}
}

I found out the problem. I allocated too much memory for a vertex which resulted in weird texturing. It's in this part of the vertex declaration:
new VertexElement((sizeof(float) * 3) * 2, VertexElementFormat.Color, VertexElementUsage.Color, 0),
new VertexElement((sizeof(float) * 3) * 3, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0)
Size of type Color isn't actually float/int but byte. Therefore I had to put it like this:
new VertexElement((sizeof(float) * 3) * 2 + 4, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0)

Related

How should I return a list that was previously set without setting it again?

I have two classes, Main and Grid. Grid simply makes a grid of square pixels. In my Main class, I want to get the list that was create in the Grid class. I managed to figure it out, but I'm wondering if there's a way to optimize the code.
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Diagnostics;
using System.Collections.Generic;
namespace teeeest
{
public class Grid
{
Texture2D image;
Color color;
int rows;
int columns;
float outerThickness;
float innerThickness;
Vector2 size;
Vector2 origin;
Vector2 dotSize;
List<Pixel> pixels = new List<Pixel>(0);
public Grid(Texture2D image, int rows, int columns, float outerThickness, float innerThickness, Vector2 size, Vector2 origin, Vector2 dotSize, Color color)
{
this.dotSize = dotSize;
this.origin = origin;
this.color = color;
this.image = image;
this.rows = rows;
this.columns = columns;
this.outerThickness = outerThickness;
this.innerThickness = innerThickness;
this.size = size;
}
public void Update()
{
float sizeX = size.X / (columns - 1);
float sizeY = size.Y / (rows - 1);
for (int i = 0; i < rows; i++)
{
for (int g = 0; g < columns; g++)
{
Pixel p = new Pixel(image, 3, new Vector2((g * sizeX) + origin.X, sizeY * i + origin.Y), new Vector2(image.Width / 2, image.Height / 2), color);
pixels.Add(p);
}
}
}
public virtual void Draw(SpriteBatch hspritebatch, List<Grid> grids)
{
foreach (Pixel p in pixels)
{
hspritebatch.Draw(
texture: p.getImage(),
position: p.getPosition(),
sourceRectangle: null,
p.getColor(),
rotation: 0,
origin: new Vector2(image.Width / 2, image.Height),
scale: new Vector2(dotSize.X * .02f, dotSize.Y * .02f),
SpriteEffects.None,
0);
}
}
public Texture2D getImage()
{
return image;
}
public Vector2 getPosition()
{
return origin;
}
public Vector2 getOrigin()
{
return new Vector2(image.Width / 2, image.Height);
}
public Color getColor()
{
return color;
}
public List<Pixel> getList()
{
Update(); # This seems unnecessary. Is it?
return pixels;
}
}
}
The problem lies in the getList() function. In order to return the correct pixel list that was edited in the Update function, my solution there is to call that function right before returning the list. However, this seems costly for no reason. Is there a way around this without calling the Update function, or is this the only way?
I realize there's been posts similar to this, but I just don't understand them. I'm very much a beginner at coding. Here is my Main class.
using System;
using System.Diagnostics;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
namespace teeeest
{
public class Game1 : Game
{
private GraphicsDeviceManager _graphics;
private SpriteBatch _spriteBatch;
private SpriteFont font;
private Texture2D ball;
private Texture2D square;
private Color color = Color.White * .1f;
private Vector2 MouseCoords;
private Vector2 winMiddle;
private Vector2 ballOrigin;
private bool leftDown;
private bool eDown;
private int winWidth;
private int winHeight;
List<Line> lines = new List<Line>(0);
List<Grid> grids = new List<Grid>(0);
List<Pixel> pixels = new List<Pixel>(0);
List<Pixel> test = new List<Pixel>(0);
public Game1()
{
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
_graphics.PreferredBackBufferWidth = 800;
_graphics.PreferredBackBufferHeight = 600;
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
ball = Content.Load<Texture2D>("ball");
square = Content.Load<Texture2D>("square");
font = Content.Load<SpriteFont>("File");
ballOrigin = new Vector2(ball.Width / 2, ball.Height / 2);
winWidth = _graphics.PreferredBackBufferWidth;
winHeight = _graphics.PreferredBackBufferHeight;
winMiddle = new Vector2(winWidth / 2, winHeight / 2);
}
protected override void Update(GameTime gameTime)
{
lines.Clear();
grids.Clear();
pixels.Clear();
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
if (Mouse.GetState().LeftButton == ButtonState.Released)
{
leftDown = false;
}
if (Mouse.GetState().LeftButton == ButtonState.Pressed && !leftDown)
{
Pixel g = new Pixel(ball, 5, MouseCoords, new Vector2(ball.Width / 2, ball.Height / 2), Color.Blue);
pixels.Add(g);
}
if (Keyboard.GetState().IsKeyUp(Keys.E))
{
eDown = false;
}
if (Keyboard.GetState().IsKeyDown(Keys.E) && !eDown)
{
color *= 1.1f;
eDown = true;
}
MouseCoords = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);
Grid q = new Grid(ball, 10, 10, 7, 3, new Vector2(500, 500), new Vector2(30, 30), new Vector2(.2f, .2f), Color.White);
grids.Add(q);
# Here is where I'm calling the getList() function.
System.Console.WriteLine(q.getList()[7].getPosition());
# Here is where I'm calling the getList() function.
foreach (Line s in lines)
{
s.Update();
}
foreach (Grid gh in grids)
{
gh.Update();
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
_spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
foreach (Line l in lines)
{
l.Draw(_spriteBatch, lines);
}
foreach (Grid g in grids)
{
g.Draw(_spriteBatch, grids);
}
foreach (Pixel p in pixels)
{
_spriteBatch.Draw(
texture: p.getImage(),
position: p.getPosition(),
sourceRectangle: null,
p.getColor(),
rotation: 0,
origin: p.getOrigin(),
scale: new Vector2(.02f, .02f),
SpriteEffects.None,
0);
}
_spriteBatch.DrawString(font,
MouseCoords.ToString(),
new Vector2 (winWidth - 100, 10),
Color.White,
rotation: 0,
origin: new Vector2(0, 0),
scale: new Vector2(1, 1),
SpriteEffects.None,
0);
_spriteBatch.End();
base.Draw(gameTime);
}
}
}
You could only call Update() when the List is EMPTY?
public List<Pixel> getList()
{
if (pixels.Count == 0)
{
Update(); // now it only gets called when pixels is EMPTY
}
return pixels;
}
This type of check may need to be done in Update() as well if it can be called directly from other places so you don't end up with more Pixel instances in it than you were expecting.

OpenTK textured Cubes show up black?

Im trying to follow this tut here http://neokabuto.blogspot.com/2014/07/opentk-tutorial-6-part-3-putting-it-all.html (backup http://web.archive.org/web/20190125230120/http://neokabuto.blogspot.com/2014/07/opentk-tutorial-6-part-3-putting-it-all.html) But I have been threw the code like a hundred times but I still keep getting black cubes :(.
Heres a download link for my hole project https://mega.nz/folder/t8NAxDRJ#MEIlwc96FZEPi_pUuB2xaA
heres what it looks like
Heres my main script, maby the errors in that?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using OpenTK;
//using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using System.IO;
using OpenTK.Input;
using System.Windows.Media.Imaging;
using System.Drawing.Imaging;
//using System.Windows.Input;
namespace OpenTKTutorial1
{
class Game: GameWindow
{
public Game() : base(1000,500, new OpenTK.Graphics.GraphicsMode(32,24,0,4))
{
}
//Just like we had a Dictionary to allow us to use strings to
//organize our shaders, we'll use another to keep track of our
//texture IDs. Add this to the Game class:
Dictionary<string, int> textures = new Dictionary<string, int>();
Vector2[] texcoorddata;
Camera cam;
Vector2 lastMousePos = new Vector2();
float time = 0.0f;
int ibo_elements;
Dictionary<string, ShaderProgram> shaders = new Dictionary<string, ShaderProgram>();
string activeShader = "default";
Vector3[] vertdata;
Vector3[] coldata;
List<Volume> objects = new List<Volume>();
int[] indicedata;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
cam = new Camera();
initProgram();
Title = "Hello OpenTK!";
GL.ClearColor(Color.CornflowerBlue);
GL.PointSize(5f);
}
void initProgram()
{
lastMousePos = new Vector2(Mouse.X, Mouse.Y);
GL.GenBuffers(1, out ibo_elements);
shaders.Add("default", new ShaderProgram("Shaders/vs.glsl", "Shaders/fs.glsl", true));
shaders.Add("textured", new ShaderProgram("Shaders/vs_tex.glsl", "Shaders/fs_tex.glsl", true));
activeShader = "textured";
textures.Add("pictures/opentksquare.png", loadImage("pictures/opentksquare.png"));
textures.Add("pictures/opentksquare2.png", loadImage("pictures/opentksquare2.png"));
TexturedCube tc = new TexturedCube();
tc.TextureID = textures["pictures/opentksquare.png"];
objects.Add(tc);
TexturedCube tc2 = new TexturedCube();
tc2.Position += new Vector3(1f, 1f, 1f);
tc2.TextureID = textures["pictures/opentksquare2.png"];
objects.Add(tc2);
cam.Position += new Vector3(0f, 0f, 3f);
}
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.Viewport(0, 0, Width, Height);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Enable(EnableCap.DepthTest);
shaders[activeShader].EnableVertexAttribArrays();
int indiceat = 0;
foreach (Volume v in objects)
{
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, v.TextureID);
GL.UniformMatrix4(shaders[activeShader].GetUniform("modelview"), false, ref v.ModelViewProjectionMatrix);
if (shaders[activeShader].GetUniform("maintexture") != -1)
{
GL.Uniform1(shaders[activeShader].GetUniform("maintexture"), 0);
}
GL.DrawElements(BeginMode.Triangles, v.IndiceCount, DrawElementsType.UnsignedInt, indiceat * sizeof(uint));
indiceat += v.IndiceCount;
}
shaders[activeShader].DisableVertexAttribArrays();
GL.Flush();
SwapBuffers();
}
private void ProcessInput()
{
if(OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.Escape))
{
Exit();
}
if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.W))
{
cam.Move(0f, 0.1f, 0f);
}
if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.S))
{
cam.Move(0f, -0.1f, 0f);
}
if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.A))
{
cam.Move(-0.1f, 0f, 0f);
}
if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.D))
{
cam.Move(0.1f, 0f, 0f);
}
if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.Q))
{
cam.Move(0f, 0f, 0.1f);
}
if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.E))
{
cam.Move(0f, 0f, -0.1f);
}
if (Focused)
{
Vector2 delta = lastMousePos - new Vector2(OpenTK.Input.Mouse.GetState().X, OpenTK.Input.Mouse.GetState().Y);
lastMousePos += delta;
cam.AddRotation(delta.X, delta.Y);
lastMousePos = new Vector2(OpenTK.Input.Mouse.GetState().X, OpenTK.Input.Mouse.GetState().Y);
}
}
protected override void OnUpdateFrame (FrameEventArgs e){
time += (float)e.Time;
ProcessInput();
// base.OnUpdateFrame();
Vector2[] texcoorddata;
List<Vector3> verts = new List<Vector3>();
List<int> inds = new List<int>();
List<Vector3> colors = new List<Vector3>();
List<Vector2> texcoords = new List<Vector2>();
int vertcount = 0;
foreach (Volume v in objects)
{
verts.AddRange(v.GetVerts().ToList());
inds.AddRange(v.GetIndices(vertcount).ToList());
colors.AddRange(v.GetColorData().ToList());
texcoords.AddRange(v.GetTextureCoords());
texcoorddata = texcoords.ToArray();
// texcoords.AddRange(v.GetTextureCoords());
vertcount += v.VertCount;
}
vertdata = verts.ToArray();
indicedata = inds.ToArray();
coldata = colors.ToArray();
texcoorddata = texcoords.ToArray();
GL.BindBuffer(BufferTarget.ArrayBuffer, shaders[activeShader].GetBuffer("vPosition"));
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer, (IntPtr)(vertdata.Length * Vector3.SizeInBytes), vertdata, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(shaders[activeShader].GetAttribute("vPosition"), 3, VertexAttribPointerType.Float, false, 0, 0);
if (shaders[activeShader].GetAttribute("vColor") != -1)
{
GL.BindBuffer(BufferTarget.ArrayBuffer, shaders[activeShader].GetBuffer("vColor"));
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer, (IntPtr)(coldata.Length * Vector3.SizeInBytes), coldata, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(shaders[activeShader].GetAttribute("vColor"), 3, VertexAttribPointerType.Float, true, 0, 0);
}
if (shaders[activeShader].GetAttribute("texcoord") != -1)
{
GL.BindBuffer(BufferTarget.ArrayBuffer, shaders[activeShader].GetBuffer("texcoord"));
GL.BufferData<Vector2>(BufferTarget.ArrayBuffer, (IntPtr)(texcoorddata.Length * Vector2.SizeInBytes), texcoorddata, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(shaders[activeShader].GetAttribute("texcoord"), 2, VertexAttribPointerType.Float, true, 0, 0);
}
// objects[0].Position = new Vector3(0.3f, -0.5f + (float) Math.Sin(time), -3.0f);
objects[0].Rotation = new Vector3(0.55f * time, 0.25f * time, 0);
objects[0].Scale = new Vector3(1, 1, 1);
objects[1].Position = new Vector3(-5f, 0.5f + (float)Math.Cos(time), -2.0f);
objects[1].Rotation = new Vector3(-0.25f * time, -0.35f * time, 0);
objects[1].Scale = new Vector3(2, 1, 2);
foreach (Volume v in objects)
{
v.CalculateModelMatrix();
v.ViewProjectionMatrix = cam.GetViewMatrix() * Matrix4.CreatePerspectiveFieldOfView(1.3f, ClientSize.Width / (float)ClientSize.Height, 1.0f, 40.0f);
v.ModelViewProjectionMatrix = v.ModelMatrix * v.ViewProjectionMatrix;
}
//GL.UniformMatrix4(uniform_mview, false, ref mviewdata[0]);
GL.UseProgram(shaders[activeShader].ProgramID);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_elements);
GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indicedata.Length * sizeof(int)), indicedata, BufferUsageHint.StaticDraw);
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);
Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, Width / (float)Height, 1.0f, 64.0f);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadMatrix(ref projection);
}
void loadShader(String filename,ShaderType type, int program, out int address)
{
address = GL.CreateShader(type);
try{
using (StreamReader sr = new StreamReader(filename))
{
GL.ShaderSource(address, sr.ReadToEnd());
}
}
catch (Exception ex){
Console.WriteLine("error loading shader : " + ex);
}
GL.CompileShader(address);
GL.AttachShader(program, address);
Console.WriteLine(GL.GetShaderInfoLog(address));
}
///
///This function will load an image as a bitmap,
/// and then store the data of it in the graphics
/// card's memory. It returns an int, the address
/// of the texture so that we can retrieve the data
/// when we want to draw the texture.
int loadImage(Bitmap image){
int texID = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texID);
BitmapData data = image.LockBits(new System.Drawing.Rectangle(0, 0, image.Width, image.Height),
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
image.UnlockBits(data);
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
return texID;
}
int loadImage(string filename)
{
try
{
Bitmap file = new Bitmap(filename);
return loadImage(file);
}
catch (Exception e)
{
Console.WriteLine(e);
return -1;
}
}
}
}
You can see all my referances for the project in the picture
The mistake is very simple. The attribute TextureID exists twice. Fist it is declared in the class Volume:
public abstract class Volume
{
// [...]
public int TextureID;
// [...]
}
Then an attribute with the same name is declared in the class TexturedCube, which is (indirectly) derived from Volume:
public class TexturedCube : Cube
{
// [...]
public int TextureID;
// [...]
}
Hence the 2nd attribute covers the 1st one. Remove the attribute from the class TexturedCube:
By the way, the same applies to the IsTextured and TextureCoordsCount attribute.

How to draw a 3D Hectogon using OpenTK C#

I have generated a 2D Hectogon in my scene view, however I am now confused as to how to make the shape three dimensional. Any help in the maths or method that is used to calculate this would be greatly appreciated. I have only just started with C# and I feel this is a tall order considering the lack of new relevant content on OpenTk in terms of most of the calls used in most tutorials are now obsolete.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.IO;
using OpenTK;
using OpenTK.Input;
using OpenTK.Graphics.OpenGL;
using OpenTK.Graphics;
namespace SimpleGame
{
class Game : GameWindow
{
public Game() : base(1280, 720, new GraphicsMode(32, 24, 0, 4)) // screen resilotion
{
}
int pgmID;
int vsID;
int fsID;
int attribute_vcol;
int attribute_vpos;
int uniform_mview;
int vbo_position;
int vbo_color;
int vbo_mview;
int ibo_elements;
Vector3[] vertdata;
Vector3[] coldata;
Matrix4[] mviewdata;
int[] indicedata;
float time = 0.0f;
void initProgram()
{
pgmID = GL.CreateProgram();
loadShader("F:/Year 1/Semester 2/Simulation In Games/SimpleGame/SimpleGame/vs.glsl", ShaderType.VertexShader, pgmID, out vsID);
loadShader("F:/Year 1/Semester 2/Simulation In Games/SimpleGame/SimpleGame/fs.glsl", ShaderType.FragmentShader, pgmID, out fsID);
GL.LinkProgram(pgmID);
Console.WriteLine(GL.GetProgramInfoLog(pgmID));
attribute_vpos = GL.GetAttribLocation(pgmID, "vPosition");
attribute_vcol = GL.GetAttribLocation(pgmID, "vColor");
uniform_mview = GL.GetUniformLocation(pgmID, "modelview");
GL.GenBuffers(1, out vbo_position);
GL.GenBuffers(1, out vbo_color);
GL.GenBuffers(1, out vbo_mview);
GL.GenBuffers(1, out ibo_elements);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
initProgram();
vertdata = new Vector3[] {
//new Vector3(0.0f,0.0f,0.0f), // center
//new Vector3(2.0f, 0f,0f), // right hand side
//new Vector3(0f,2f,0f), // up
new Vector3(0.0f,0.0f,-0.8f), // center point
new Vector3(2.0f,0.0f,-0.8f), // right hand side
new Vector3(1.0f,1.7f,-0.8f), // right hand top
new Vector3(-1.0f,1.7f,-0.8f), // right hand top
new Vector3(-2.0f,0.0f,-0.8f), // left hand top
new Vector3(-1.0f,-1.7f,-0.8f),
new Vector3(1.0f,-1.7f,-0.8f), // right hand top
};
indicedata = new int[]{
//front
0, 1, 2,
0, 2, 3,
//back
0, 3, 4,
0, 4, 5,
//left
0, 5, 6,
0, 6, 1,
};
coldata = new Vector3[] { new Vector3(1f, 0f, 0f),
new Vector3( 0f, 0f, 1f),
new Vector3( 0f, 1f, 0f),new Vector3(1f, 0f, 0f),
new Vector3( 0f, 0f, 1f),
new Vector3( 0f, 1f, 0f),new Vector3(1f, 0f, 0f),
new Vector3( 0f, 0f, 1f)};
mviewdata = new Matrix4[]{
Matrix4.Identity
};
Title = "Hello OpenTK!";
GL.ClearColor(Color.DarkTurquoise);
GL.PointSize(5f);
}
void loadShader(String filename, ShaderType type, int program, out int address)
{
address = GL.CreateShader(type);
using (StreamReader sr = new StreamReader(filename))
{
GL.ShaderSource(address, sr.ReadToEnd());
}
GL.CompileShader(address);
GL.AttachShader(program, address);
Console.WriteLine(GL.GetShaderInfoLog(address));
}
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.Viewport(0, 0, Width, Height);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Enable(EnableCap.DepthTest);
GL.EnableVertexAttribArray(attribute_vpos);
GL.EnableVertexAttribArray(attribute_vcol);
GL.DrawElements(BeginMode.Triangles, indicedata.Length, DrawElementsType.UnsignedInt, 0);
GL.DisableVertexAttribArray(attribute_vpos);
GL.DisableVertexAttribArray(attribute_vcol);
GL.Flush();
SwapBuffers();
}
protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_position);
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer, (IntPtr)(vertdata.Length * Vector3.SizeInBytes), vertdata, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(attribute_vpos, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_color);
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer, (IntPtr)(coldata.Length * Vector3.SizeInBytes), coldata, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(attribute_vcol, 3, VertexAttribPointerType.Float, true, 0, 0);
time += (float)e.Time;
mviewdata[0] = Matrix4.CreateRotationY(0.2f time) Matrix4.CreateRotationX(0.0f time) Matrix4.CreateTranslation(0.0f, -1.0f, -4.0f) *
Matrix4.CreatePerspectiveFieldOfView(1.3f, ClientSize.Width / (float)ClientSize.Height, 1.0f, 40.0f); // rotation
GL.UniformMatrix4(uniform_mview, false, ref mviewdata[0]);
GL.UseProgram(pgmID);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_elements);
GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indicedata.Length * sizeof(int)), indicedata, BufferUsageHint.StaticDraw);
}
}
}
I don't think there is a built in method for creating prisms. A prism based on a heptagon (7-sided polygon) is made up from two heptagons (one on the bottom, one on the top) plus 7 vertical 4-sided polygons. So the algorithm for extruding a prism from a horizontal polygon would be (in pseudo code)
create_prism(bottom : polygon, height : float) : body
var top : polygon
top = bottom.Clone()
for all vertices v of top
v.z = v.z + height
end
var b = new body
b.Add(bottom)
b.Add(top)
for i : integer = 0 to bottom.Count - 1
var j : integer
j = (i + 1) modulo bottom.Count
var side = new polygon[4]
side[0] = bottom[i]
side[1] = bottom[j]
side[2] = top[j]
side[3] = top[i]
b.Add(side)
end
return b
end

reusing xna primitives via class

Is there any way to make a primitive and use it over and over again? ex: if I make one cube, can I create 100 and make a 10x10 grid? I've tried using a for loop and updating the x and z coords with each loop thru, but it only moves the one cube thats created in the beginning. My class was created using an example from a book. I know how to move the cube around the area by changing the coords in the PositionCube method. What can I do in my main game class that will allow me to create a simple 10x10 grid?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Cube_Chaser
{
class Cube
{
private GraphicsDevice device;
private Texture2D texture;
public Vector3 location;
private Vector3 position;
private VertexBuffer cubeVertexBuffer;
private List<VertexPositionTexture> vertices = new List<VertexPositionTexture>();
public Cube(GraphicsDevice graphicsDevice, Vector3 playerLocation, float minDistance, Texture2D texture)
{
device = graphicsDevice;
this.texture = texture;
PositionCube(playerLocation, minDistance);
BuildFace(new Vector3(0, 0, 0), new Vector3(0, 1, 1));
BuildFace(new Vector3(0, 0, 1), new Vector3(1, 1, 1));
BuildFace(new Vector3(1, 0, 1), new Vector3(1, 1, 0));
BuildFace(new Vector3(1, 0, 0), new Vector3(0, 1, 0));
BuildFaceHorizontal(new Vector3(0, 1, 0), new Vector3(1, 1, 1));
BuildFaceHorizontal(new Vector3(0, 0, 1), new Vector3(1, 0, 0));
cubeVertexBuffer = new VertexBuffer(device, VertexPositionTexture.VertexDeclaration, vertices.Count, BufferUsage.WriteOnly);
cubeVertexBuffer.SetData<VertexPositionTexture>(vertices.ToArray());
this.position = position;
}
private void BuildFace(Vector3 p1, Vector3 p2)
{
vertices.Add(BuildVertex(p1.X, p1.Y, p1.Z, 1, 0));
vertices.Add(BuildVertex(p1.X, p2.Y, p1.Z, 1, 1));
vertices.Add(BuildVertex(p2.X, p2.Y, p2.Z, 0, 1));
vertices.Add(BuildVertex(p2.X, p2.Y, p2.Z, 0, 1));
vertices.Add(BuildVertex(p2.X, p1.Y, p2.Z, 0, 0));
vertices.Add(BuildVertex(p1.X, p1.Y, p1.Z, 1, 0));
}
private void BuildFaceHorizontal(Vector3 p1, Vector3 p2)
{
vertices.Add(BuildVertex(p1.X, p1.Y, p1.Z, 0, 1));
vertices.Add(BuildVertex(p2.X, p1.Y, p1.Z, 1, 1));
vertices.Add(BuildVertex(p2.X, p2.Y, p2.Z, 1, 0));
vertices.Add(BuildVertex(p1.X, p1.Y, p1.Z, 0, 1));
vertices.Add(BuildVertex(p2.X, p2.Y, p2.Z, 1, 0));
vertices.Add(BuildVertex(p1.X, p1.Y, p2.Z, 0, 0));
}
private VertexPositionTexture BuildVertex(float x, float y, float z, float u, float v)
{
return new VertexPositionTexture(new Vector3(x, y, z), new Vector2(u, v));
}
public void PositionCube(Vector3 playerLocation, float minDistance)
{
location = new Vector3(.5f, .5f, .5f);
}
public void Draw(Camera camera, BasicEffect effect)
{
effect.VertexColorEnabled = false;
effect.TextureEnabled = true;
effect.Texture = texture;
Matrix center = Matrix.CreateTranslation(new Vector3(-0.5f, -0.5f, -0.5f));
Matrix scale = Matrix.CreateScale(0.05f);
Matrix translate = Matrix.CreateTranslation(location);
effect.World = center * scale * translate;
effect.View = camera.View;
effect.Projection = camera.Projection;
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
device.SetVertexBuffer(cubeVertexBuffer);
device.DrawPrimitives(PrimitiveType.TriangleList, 0, cubeVertexBuffer.VertexCount / 3);
}
}
}
}
I took #nico-schetler 's answer and created the classes for you.
Cube.cs
class Cube
{
private GraphicsDevice device;
private VertexBuffer cubeVertexBuffer;
public Cube(GraphicsDevice graphicsDevice)
{
device = graphicsDevice;
var vertices = new List<VertexPositionTexture>();
BuildFace(vertices, new Vector3(0, 0, 0), new Vector3(0, 1, 1));
BuildFace(vertices, new Vector3(0, 0, 1), new Vector3(1, 1, 1));
BuildFace(vertices, new Vector3(1, 0, 1), new Vector3(1, 1, 0));
BuildFace(vertices, new Vector3(1, 0, 0), new Vector3(0, 1, 0));
BuildFaceHorizontal(vertices, new Vector3(0, 1, 0), new Vector3(1, 1, 1));
BuildFaceHorizontal(vertices, new Vector3(0, 0, 1), new Vector3(1, 0, 0));
cubeVertexBuffer = new VertexBuffer(device, VertexPositionTexture.VertexDeclaration, vertices.Count, BufferUsage.WriteOnly);
cubeVertexBuffer.SetData<VertexPositionTexture>(vertices.ToArray());
}
private void BuildFace(List<VertexPositionTexture> vertices, Vector3 p1, Vector3 p2)
{
vertices.Add(BuildVertex(p1.X, p1.Y, p1.Z, 1, 0));
vertices.Add(BuildVertex(p1.X, p2.Y, p1.Z, 1, 1));
vertices.Add(BuildVertex(p2.X, p2.Y, p2.Z, 0, 1));
vertices.Add(BuildVertex(p2.X, p2.Y, p2.Z, 0, 1));
vertices.Add(BuildVertex(p2.X, p1.Y, p2.Z, 0, 0));
vertices.Add(BuildVertex(p1.X, p1.Y, p1.Z, 1, 0));
}
private void BuildFaceHorizontal(List<VertexPositionTexture> vertices, Vector3 p1, Vector3 p2)
{
vertices.Add(BuildVertex(p1.X, p1.Y, p1.Z, 0, 1));
vertices.Add(BuildVertex(p2.X, p1.Y, p1.Z, 1, 1));
vertices.Add(BuildVertex(p2.X, p2.Y, p2.Z, 1, 0));
vertices.Add(BuildVertex(p1.X, p1.Y, p1.Z, 0, 1));
vertices.Add(BuildVertex(p2.X, p2.Y, p2.Z, 1, 0));
vertices.Add(BuildVertex(p1.X, p1.Y, p2.Z, 0, 0));
}
private VertexPositionTexture BuildVertex(float x, float y, float z, float u, float v)
{
return new VertexPositionTexture(new Vector3(x, y, z), new Vector2(u, v));
}
public void Draw( BasicEffect effect)
{
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
device.SetVertexBuffer(cubeVertexBuffer);
device.DrawPrimitives(PrimitiveType.TriangleList, 0, cubeVertexBuffer.VertexCount / 3);
}
}
}
CubeDrawable.cs
public class DrawableList<T> : DrawableGameComponent
{
private BasicEffect effect;
private Camera camera;
private class Entity
{
public Vector3 Position { get; set; }
public Matrix Orientation { get; set; }
public Texture2D Texture { get; set; }
}
private Cube cube;
private List<Entity> entities = new List<Entity>();
public DrawableList (Game game, Camera camera, BasicEffect effect)
: base( game )
{
this.effect = effect;
cube = new Cube (game.GraphicsDevice);
this.camera = camera;
}
public void Add( Vector3 position, Matrix orientation, Texture2D texture )
{
entities.Add (new Entity() {
Position = position,
Orientation = orientation,
Texture = texture
});
}
public override void Draw (GameTime gameTime )
{
base.Draw (gameTime);
foreach (var item in entities) {
effect.VertexColorEnabled = false;
effect.TextureEnabled = true;
effect.Texture = item.Texture;
Matrix center = Matrix.CreateTranslation(new Vector3(-0.5f, -0.5f, -0.5f));
Matrix scale = Matrix.CreateScale(0.05f);
Matrix translate = Matrix.CreateTranslation(item.Position);
effect.World = center * scale * translate;
effect.View = camera.View;
effect.Projection = camera.Projection;
cube.Draw (effect);
}
}
}
Usage
camera = new Camera (graphics.GraphicsDevice);
effect = new BasicEffect (graphics.GraphicsDevice);
cubes = new DrawableList<Cube> (this, camera, effect);
Components.Add (cubes);
for (int i=0 ; i < 50; i++)
{
cubes.Add (new Vector3( i*0.5f, 50.0f, 50.0f), Matrix.Identity, logoTexture);
}
You should separate the logical representation of the cube from the physical one. The physical representation would be the vertex buffer etc. This is the same for every cube. You can affect the rendering through e.g. world transforms (as you already did).
The logical representation is your cube class. You will need 100 instances of them (each with their own position, scale etc.). The logical representation can reference the physical one. So there is no need to have more than one vertex buffer.

Texture2D: SetData doesn't work

I'd like to have a sort of floor with a programmaically created texture on it. I already created the vertices and the indexes needed for the work:
private VertexPositionNormalTexture[] verticiBase;
private short[] indici;
...
verticiBase = new VertexPositionNormalTexture[4];
verticiBase[0] = new VertexPositionNormalTexture(new Vector3(0.0f, 0.0f, 0.0f), Vector3.Up, new Vector2(0, 0));
verticiBase[1] = new VertexPositionNormalTexture(new Vector3(dimensioneVera.X, 0.0f, 0.0f), Vector3.Up, new Vector2(1, 0));
verticiBase[2] = new VertexPositionNormalTexture(new Vector3(0.0f, 0.0f, dimensioneVera.Y), Vector3.Up, new Vector2(0, 1));
verticiBase[3] = new VertexPositionNormalTexture(new Vector3(dimensioneVera.X, 0.0f, dimensioneVera.Y), Vector3.Up, new Vector2(1, 1));
graphics.GraphicsDevice.VertexDeclaration = new
VertexDeclaration(graphics.GraphicsDevice,
VertexPositionNormalTexture.VertexElements);
indici = new short[6];
indici[0] = 0;
indici[1] = 1;
indici[2] = 2;
indici[3] = 1;
indici[4] = 3;
indici[5] = 2;
Then I created the texture and the data which I'd like to show:
private Texture2D texture;
private Color[] textureData;
...
texture = new Texture2D(Game.GraphicsDevice, (int)dimensioneVera.X, (int)dimensioneVera.Y);
textureData = new Color[(int)dimensioneVera.X * (int)dimensioneVera.Y];
for (int x = 0; x < textureData.Length; x++)
textureData[x] = Color.Red;
texture.SetData(textureData);
And this is the code I used to draw:
private BasicEffect effetti;
...
effetti = new BasicEffect(graphics.GraphicsDevice, null);
...
public override void Draw(GameTime gameTime)
{
effetti.World = Matrix.Identity;
effetti.View = camera.view;
effetti.Projection = camera.projection;
effetti.TextureEnabled = true;
effetti.Texture = texture;
effetti.Begin();
effetti.EnableDefaultLighting();
effetti.CurrentTechnique.Passes[0].Begin();
graphics.GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList,
verticiBase, 0, verticiBase.Length, indici, 0, indici.Length / 3);
effetti.CurrentTechnique.Passes[0].End();
effetti.End();
base.Draw(gameTime);
}
The floor is displayed but the texture is all black. What's wrong?
Thanks for your time.
I suspect the problem is not that you've created the texture incorrectly. The problem is your lighting; you've called EnableDefaultLighting() but not provided any lights, so everything is completely dark (black). Try setting effetti.AmbientLightColor = Color.White and see if that helps.

Categories