What's wrong with my instancing below? I'm trying to draw multiple instances of a single box with vertex colors. The examples I adapted this code from used textures and a shader rather than vertex colors. So I suspect that I'm going wrong with VertexPositionColor or my use of BasicEffect. I don't need a texture so I tried to remove the shader. I should also mention this is part of a winforms application.
What I get out of this code is a big red X indicating something went terribly wrong.
What am I missing here? Obviously there's something I'm not understanding.
namespace Die
{
class DieRender
{
VertexDeclaration instanceVertexDeclaration;
VertexBuffer dieGeometryBuffer;
IndexBuffer dieIndexBuffer;
VertexBuffer instanceBuffer;
VertexBufferBinding[] bindings;
InstanceInfo[] instances;
int instanceCount = 3;
struct InstanceInfo
{
public Vector4 World;
};
public void Initialize(GraphicsDevice device) {
GenerateInstanceVertexDeclaration();
GenerateDieGeometry(device, Color.Blue);
GenerateInstanceInformation(device, instanceCount);
bindings = new VertexBufferBinding[2];
bindings[0] = new VertexBufferBinding(dieGeometryBuffer);
bindings[1] = new VertexBufferBinding(instanceBuffer, 0, 1);
}
private void GenerateInstanceVertexDeclaration() {
VertexElement[] instanceStreamElements = new VertexElement[1];
instanceStreamElements[0] =
new VertexElement(0, VertexElementFormat.Vector4,
VertexElementUsage.Position, 1);
instanceVertexDeclaration = new VertexDeclaration(instanceStreamElements);
}
public void GenerateDieGeometry(GraphicsDevice device, Color color) {
VertexPositionColor[] vertices = new VertexPositionColor[4];
int[] indices = new int[6];
vertices[0].Position = new Vector3(-1, 1, 0);
vertices[1].Position = new Vector3(1, 1, 0);
vertices[2].Position = new Vector3(-1, -1, 0);
vertices[3].Position = new Vector3(1, -1, 0);
for (int i = 0; i < vertices.Count(); i++)
vertices[i].Color = color;
dieGeometryBuffer = new VertexBuffer(device,VertexPositionColor.VertexDeclaration,
4, BufferUsage.WriteOnly);
dieGeometryBuffer.SetData(vertices);
indices[0] = 0; indices[1] = 1; indices[2] = 2;
indices[3] = 1; indices[4] = 3; indices[5] = 2;
dieIndexBuffer = new IndexBuffer(device, typeof(int), 6, BufferUsage.WriteOnly);
dieIndexBuffer.SetData(indices);
}
private void GenerateInstanceInformation(GraphicsDevice device, Int32 count) {
instances = new InstanceInfo[count];
Random rnd = new Random();
for (int i = 0; i < count; i++) {
instances[i].World = new Vector4(-rnd.Next(20),
-rnd.Next(20),
-rnd.Next(20), 0);
}
instanceBuffer = new VertexBuffer(device, instanceVertexDeclaration,
count, BufferUsage.WriteOnly);
instanceBuffer.SetData(instances);
}
public void Draw(Matrix world, Matrix view, Matrix projection, GraphicsDevice device) {
device.Clear(Color.White);
BasicEffect effect = new BasicEffect(device);
effect.EnableDefaultLighting();
effect.TextureEnabled = false;
effect.World = world;
effect.View = view;
effect.Projection = projection;
effect.VertexColorEnabled = true;
device.Indices = dieIndexBuffer;
device.SetVertexBuffers(bindings);
foreach (EffectPass pass in effect.CurrentTechnique.Passes) {
pass.Apply();
device.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, 4, 0, 2, instanceCount);
}
}
}
}
Ah! I found it... struggled with this for days and found the problem just as soon as I posted the question.
After enabling the exceptions from the CLR I caught the exception and found this similar question: XNA: The current vertex declaration does not include all the elements required by the current vertex shader. Normal0 is missing
Sorry if I wasted anybody's time.
Now... on to the next bug.
Related
When drawing the number 2 it seems like some lines are thick. It didn't happen when drawing the numbers zero and one.
private void Two()
{
Positions = new Vector3[6] {
new Vector3(0, 0, 0),
new Vector3(1, 0, 0),
new Vector3(1, -1, 0),
new Vector3(0,-1,0),
new Vector3(0,-2,0),
new Vector3(1,-2,0)};
childNumberGameObject = new GameObject(currentNumberIndex.ToString());
CheckIfNumberParentExist("Two");
childNumberGameObject.transform.parent = numberParent.transform;
childNumberGameObject.transform.localPosition = new Vector3(currentNumberIndex * number_Width, 0f, 0f);
LineRendererInstance(6);
InstantiateDots(Positions);
++currentNumberIndex;
}
The LineRendererInstance
private void LineRendererInstance(int PositionCount)
{
LineRenderer lineRendererInstance = childNumberGameObject.AddComponent<LineRenderer>();
lineRendererInstance.positionCount = PositionCount;
lineRendererInstance.SetPositions(Positions);
lineRendererInstance.useWorldSpace = false;
lineRendererInstance.startWidth = 0.10f;
lineRendererInstance.endWidth = 0.10f;
}
The InstantiateDots
private void InstantiateDots(Vector3[] Positions)
{
for (int i = 0; i < Positions.Length; i++)
{
var dot = Instantiate(dotPrefab, childNumberGameObject.transform);
dot.tag = "Dot";
dot.transform.localPosition = Positions[i];
}
}
Screenshot comparison with 0 and 1
It looks like in number 2 the top middle and bottom lines are thickers then the lines on the sides.
After changed the start and end width from 0.10 to 0.20
I'm trying to write simple DirectX 11 app using C# and SharpDX. I wanted to test basic drawing but when i run the program, i will get entire form filled with red color. When i change the vertices its drawing unwanted shapes. Clear color works.
I tried changing some properties but nothing helps.
Here is the code:
private Vector3[] Vertices = new Vector3[]
{
new Vector3(-0.5f, 0.5f, 0), new Vector3(0.5f, 0.5f, 0), new Vector3(0, -0.5f, 0)
};
private D3D11.Buffer VertexBuffer;
public Game()
{
RenderForm = new RenderForm("Test Form");
RenderForm.ClientSize = new Size(Width, Height);
RenderForm.AllowUserResizing = false;
InitDeviceResources();
InitShaders();
InitVertexBuffer();
}
public void Run()
{
RenderLoop.Run(RenderForm, RenderCallback);
}
private void InitVertexBuffer()
{
VertexBuffer = D3D11.Buffer.Create<Vector3>(Device, BindFlags.VertexBuffer, Vertices);
}
private void InitShaders()
{
using (ShaderBytecode vertexShaderBytecode = ShaderBytecode.CompileFromFile("vertexShader.hlsl", "main", "vs_4_0", ShaderFlags.Debug))
{
InputSignature = ShaderSignature.GetInputSignature(vertexShaderBytecode);
VertexShader = new VertexShader(Device, vertexShaderBytecode);
}
using (ShaderBytecode pixelShaderBytecode = ShaderBytecode.CompileFromFile("pixelShader.hlsl", "main", "ps_4_0", ShaderFlags.Debug))
{
PixelShader = new PixelShader(Device, pixelShaderBytecode);
}
Context.VertexShader.Set(VertexShader);
Context.PixelShader.Set(PixelShader);
Context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
InputLayout = new InputLayout(Device, InputSignature, InputElements);
Context.InputAssembler.InputLayout = InputLayout;
}
private void InitDeviceResources()
{
ModeDescription backBufferDesc = new ModeDescription(Width, Height, new Rational(60, 1), Format.B8G8R8A8_UNorm);
SwapChainDescription swapChainDesc = new SwapChainDescription()
{
BufferCount = 1,
IsWindowed = true,
OutputHandle = RenderForm.Handle,
ModeDescription = backBufferDesc,
SampleDescription = new SampleDescription(1, 0),
Usage = Usage.RenderTargetOutput
};
D3D11.Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, swapChainDesc, out Device, out SwapChain);
Context = Device.ImmediateContext;
Viewport = new Viewport(0, 0, Width, Height);
Context.Rasterizer.SetViewport(Viewport);
using (Texture2D backBuffer = SwapChain.GetBackBuffer<Texture2D>(0))
{
RenderTarget = new RenderTargetView(Device, backBuffer);
}
}
private void RenderCallback()
{
Draw();
}
private void Draw()
{
Context.OutputMerger.SetRenderTargets(RenderTarget);
Context.ClearRenderTargetView(RenderTarget, new Color4(0, 0, 1, 1));
Context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(VertexBuffer, Utilities.SizeOf<Vector3>(), 0));
Context.Draw(Vertices.Count(), 0);
SwapChain.Present(1, PresentFlags.None);
}
I finally solved this. There must be Format.R32G32B32_Float instead of Format.R32G32B32A32_Float
How to calculate the actual speed of all moving objects on video using the Lucals-kanade algorithm to calculate the optical flow ?
I need to do this on this video. The camera is fixed in one place (Fig. 1)
I find the key points and track them using the Lucas-Kanade algorithm (Fig. 2)
How to use this algorithm to update the actual speed of each car?
Thank you for your answers!
My code:
public class OpticalFlowLK : BaseFilter
{
private Mat prevFrame;
private Mat nextFrame;
private bool prevFrameEmpty = true;
private GFTTDetector gFTTDetector;
private Stopwatch sWatch;
private double time = 0.04;
public OpticalFlowLK()
{
TAG = "[Optical Flow Lucas Kanade]";
gFTTDetector = new GFTTDetector(500);
sWatch = new Stopwatch();
}
protected override Mat ProcessFrame(ref Mat frame)
{
Mat rez = new Mat();
frame.CopyTo(rez);
nextFrame = new Mat();
Mat gray = new Mat();
var tmpImg = gray.ToImage<Gray, Byte>();
CvInvoke.CvtColor(frame, nextFrame, Emgu.CV.CvEnum.ColorConversion.Bgr2Gray);
if (!prevFrameEmpty)
{
VectorOfKeyPoint prevFeatures = new VectorOfKeyPoint(gFTTDetector.Detect(prevFrame));
//Features2DToolbox.DrawKeypoints(rez, prevFeatures, rez, new Bgr(0, 0, 255));
PointF[] prevPts = new PointF[prevFeatures.Size];
for (int i = 0; i < prevFeatures.Size; i++)
{
prevPts[i] = prevFeatures[i].Point;
}
PointF[] nextPts;
byte[] status;
float[] errors;
sWatch.Start();
CvInvoke.CalcOpticalFlowPyrLK(prevFrame, nextFrame, prevPts, new Size(20, 20), 1, new MCvTermCriteria(20, 0.03), out nextPts, out status, out errors);
sWatch.Stop();
sWatch.Reset();
prevFrame = nextFrame.Clone();
for (int i = 0; i < status.Length; i++)
{
Point prevPt = new Point((int)prevPts[i].X,(int)nextPts[i].Y);
Point nextPt = new Point((int)nextPts[i].X,(int)nextPts[i].Y);
double lenght = Math.Sqrt(Math.Pow(prevPt.X - nextPt.X, 2) + Math.Pow(prevPt.Y - nextPt.Y, 2));
if (lenght > 3)
{
CvInvoke.Circle(rez, nextPt, 1, new MCvScalar(0, 255, 0), 2);
}
}
sWatch.Stop();
prevFrameEmpty = false;
}
else if (prevFrameEmpty)
{
prevFrame = nextFrame.Clone();
prevFrameEmpty = false;
}
return rez;
}
protected override bool InitFilter(ref Mat frame)
{
throw new NotImplementedException();
}
}
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 7 years ago.
I'm currently working on an exercise for my c# class. I am having some trouble with one particular part and would really appreciate some help.
I am working on an exercise in which we are given an incomplete project file.
The project has multiple classes, this class is for controlling squares that are placed on the board.
namespace HareAndTortoise {
public partial class SquareControl : PictureBox {
public const int SQUARE_SIZE = 100;
private Square square; // A reference to the corresponding square object
private BindingList<Player> players; // References the players in the overall game.
private bool[] containsPlayers = new bool[6];//HareAndTortoiseGame.MAX_PLAYERS];
public bool[] ContainsPlayers {
get {
return containsPlayers;
}
set {
containsPlayers = value;
}
}
// Font and brush for displaying text inside the square.
private Font textFont = new Font("Microsoft Sans Serif", 8);
private Brush textBrush = Brushes.White;
public SquareControl(Square square, BindingList<Player> players) {
this.square = square;
this.players = players;
// Set GUI properties of the whole square.
Size = new Size(SQUARE_SIZE, SQUARE_SIZE);
Margin = new Padding(0); // No spacing around the cell. (Default is 3 pixels.)
Dock = DockStyle.Fill;
BorderStyle = BorderStyle.FixedSingle;
BackColor = Color.CornflowerBlue;
SetImageWhenNeeded();
}
private void SetImageWhenNeeded()
{
if (square is Square.Win_Square)
{
LoadImageFromFile("Win.png");
textBrush = Brushes.Black;
}
else if (square is Square.Lose_Square)
{
LoadImageFromFile("Lose.png");
textBrush = Brushes.Red;
}
else if (square is Square.Chance_Square)
{
LoadImageFromFile("monster-green.png");
}
else if (square.Name == "Finish")
{
LoadImageFromFile("checkered-flag.png");
}
else
{
// No image needed.
}
}
private void LoadImageFromFile(string fileName) {
Image image = Image.FromFile(#"Images\" + fileName);
Image = image;
SizeMode = PictureBoxSizeMode.StretchImage; // Zoom is also ok.
}
protected override void OnPaint(PaintEventArgs e) {
// Due to a limitation in WinForms, don't use base.OnPaint(e) here.
if (Image != null)
e.Graphics.DrawImage(Image, e.ClipRectangle);
string name = square.Name;
// Create rectangle for drawing.
float textWidth = textFont.Size * name.Length;
float textHeight = textFont.Height;
float textX = e.ClipRectangle.Right - textWidth;
float textY = e.ClipRectangle.Bottom - textHeight;
RectangleF drawRect = new RectangleF(textX, textY, textWidth, textHeight);
// When debugging this method, show the drawing-rectangle on the screen.
//Pen blackPen = new Pen(Color.Black);
//e.Graphics.DrawRectangle(blackPen, textX, textY, textWidth, textHeight);
// Set format of string.
StringFormat drawFormat = new StringFormat();
drawFormat.Alignment = StringAlignment.Far; // Right-aligned.
// Draw string to screen.
e.Graphics.DrawString(name, textFont, textBrush, drawRect, drawFormat);
// Draw player tokens (when any players are on this square).
const int PLAYER_TOKENS_PER_ROW = 3;
const int PLAYER_TOKEN_SIZE = 30; // pixels.
const int PLAYER_TOKEN_SPACING = (SQUARE_SIZE - (PLAYER_TOKEN_SIZE * PLAYER_TOKENS_PER_ROW)) / (PLAYER_TOKENS_PER_ROW - 1);
for (int i = 0; i < containsPlayers.Length; i++) {
if (containsPlayers[i]) {
int xPosition = i % PLAYER_TOKENS_PER_ROW;
int yPosition = i / PLAYER_TOKENS_PER_ROW;
int xPixels = xPosition * (PLAYER_TOKEN_SIZE + PLAYER_TOKEN_SPACING);
int yPixels = yPosition * (PLAYER_TOKEN_SIZE + PLAYER_TOKEN_SPACING);
Brush playerTokenColour = players[i].PlayerTokenColour;
e.Graphics.FillEllipse(playerTokenColour, xPixels, yPixels, PLAYER_TOKEN_SIZE, PLAYER_TOKEN_SIZE);
}
}//endfor
}
}
}
The program trips up at:
else if (square.Name == "Finish")
{
LoadImageFromFile("checkered-flag.png");
}
I know it is because of square.name but from going through the code, I cant see why square.Name is not recognizable.
Square is passed from another class using this method
private void SetUpGuiGameBoard()
{
for (int i = 0; i <= 55; i++)
{
Square q = Board.GetGameBoardSquare(i);
SquareControl sq = new SquareControl(q, null);
int coloumn;
int row;
if (i == 0)
{
BackColor = Color.BurlyWood;
}
if (i == 55)
{
BackColor = Color.BurlyWood;
}
MapSquareNumToTablePanel(i, out coloumn, out row);
tableLayoutPanel1.Controls.Add(sq, coloumn, row);
}
and Squares are created in this class
private static Square[] gameBoard = new Square[56];
static public void SetUpBoard()
{
for (int i = 1; i == 55; i++)
{
gameBoard[i] = new Square("Ordinary Square", i);
}
gameBoard[0] = new Square("Start", 0);
gameBoard[4] = new Square.Lose_Square("Lose Square", 4);
gameBoard[5] = new Square.Chance_Square("Chance Square", 5);
gameBoard[9] = new Square.Win_Square("Win Square", 9);
gameBoard[11] = new Square.Chance_Square("Chance Square", 11);
gameBoard[14] = new Square.Lose_Square("Lose Square", 14);
gameBoard[17] = new Square.Chance_Square("Chance Square", 17);
gameBoard[19] = new Square.Win_Square("Win Square", 19);
gameBoard[24] = new Square.Lose_Square("Lose Square", 24);
gameBoard[29] = new Square.Win_Square("Win Square", 29);
gameBoard[34] = new Square.Lose_Square("Lose Square", 34);
gameBoard[35] = new Square.Chance_Square("Chance Square", 35);
gameBoard[39] = new Square.Win_Square("Win Square", 39);
gameBoard[44] = new Square.Lose_Square("Lose Square", 44);
gameBoard[47] = new Square.Chance_Square("Chance Square", 47);
gameBoard[49] = new Square.Win_Square("Win Square", 49);
gameBoard[53] = new Square.Chance_Square("Chance Square", 53);
gameBoard[55] = new Square("Finish", 56);
}
public static Square GetGameBoardSquare(int n)
{
return gameBoard[n];
}
public static Square StartSquare()
{
return gameBoard[0];
}
public static Square NextSquare(int n)
{
return gameBoard[(n+1)];
}
}
The answer already provided is the best way for prevention of any null reference exception. For more clarification I can suggest you to check the call stack at the point the debugger reaches the SquareControl constructor. At this point you should check why the Square object being passed in is a 'NULL'. That will lead you to the root cause of the problem. Hope this helps.
How can I play a movie and add a text overlay with DirectX in C#, please specify some references, because I am new in this area.
the specific part of DirectX tused for video playback is called DirectShow, you need a reference on how to use DirectShow from c#, a staring point could be this one:
http://www.codeproject.com/KB/directx/directshowmediaplayer.aspx
see http://www.riemers.net/eng/Tutorials/DirectX/Csharp/Series2/tut18.php for some source code on displaying text on a DirectX surface...
Here is a form that initializes a Direct3D, creates a couple of triangle vertices, and displays the video on them. Because I have no understanding of vertices it isn't quite lined up correctly, but it successfully loads the video and renders it as a texture onto the triangles.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Microsoft.DirectX.Direct3D.Device _device;
private Microsoft.DirectX.Direct3D.Font font;
private Microsoft.DirectX.AudioVideoPlayback.Video _video;
CustomVertex.PositionTextured[] vertices;
public void Init()
{
PresentParameters present_params = new PresentParameters();
present_params.Windowed = true;
present_params.SwapEffect = SwapEffect.Discard;
_device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, present_params);
font = new Microsoft.DirectX.Direct3D.Font(_device, 20, 0, FontWeight.Bold, 0, false, CharacterSet.Default, Precision.Default, FontQuality.Default, PitchAndFamily.DefaultPitch, "Arial");
_video = new Video("clock.avi");
_video.TextureReadyToRender += new TextureRenderEventHandler(_video_TextureReadyToRender);
_video.RenderToTexture(_device);
vertices = new CustomVertex.PositionTextured[6];
vertices[0].Position = new Vector3(1f, 1f, 0f);
vertices[0].Tu = 0;
vertices[0].Tv = 1;
vertices[1].Position = new Vector3(-1f, -1f, 0f);
vertices[1].Tu = 1;
vertices[1].Tv = 1;
vertices[2].Position = new Vector3(1f, -1f, 0f);
vertices[2].Tu = 0;
vertices[2].Tv = 0;
vertices[3].Position = new Vector3(-1.1f, -0.99f, 0f);
vertices[3].Tu = 1;
vertices[3].Tv = 0;
vertices[4].Position = new Vector3(0.99f, 1.1f, 0f);
vertices[4].Tu = 0;
vertices[4].Tv = 0;
vertices[5].Position = new Vector3(-1.1f, 1.1f, 0f);
vertices[5].Tu = 1;
vertices[5].Tv = 1;
}
void _video_TextureReadyToRender(object sender, TextureRenderEventArgs e)
{
_device.BeginScene();
_device.SetTexture(0, e.Texture);
_device.VertexFormat = CustomVertex.PositionTextured.Format;
_device.DrawUserPrimitives(PrimitiveType.TriangleList, 2, vertices);
font.DrawText(null, "test overlay", 5, 5, Color.Red);
_device.EndScene();
_device.Present();
}
protected override void OnPaint(PaintEventArgs e)
{
_device.Clear(ClearFlags.Target, Color.Blue, 0.0F, 0);
}
private void Form1_Load(object sender, EventArgs e)
{
_video.Play();
}
}
You need to put your scene drawing code within the TextureReadyToRender event, otherwise your video will never show up.