سؤال

I have a class called PointCloud that is a vbo buffer object and I'm rendering a couple of these with different data, one as a sphere and one as a dataset of xyz, the dataset has colors and sphere is without colors. the problem is both seem to share the same colors, instead of having individual sets of colors, the colors for the sphere are actually set as null so I'm confused as to why color is being applied to it.

What I'm trying to do is draw the sphere 'white' while the other pointcloud is it's respective color.

enter image description here

if you can't see the image try this (http://s8.postimg.org/q1j0nlkol/pcerror.png)

http://pastebin.com/3fM9K87A

My question is can anybody explain why this is happening and what I'm doing wrong?

here is the pointcloud class:

using System;
using OpenTK.Graphics.OpenGL;
using OpenTK;

internal class PointCloud : IDisposable
{
    protected int[] vbo_id = new int[2];
    protected int vbo_size;
    public bool HasColor;

    public float[] Vertices = null;
    public int[] Colors = null;

    public float PointSize { get; set; }
    public bool Visible { get; set; }

    ~PointCloud()
    {
        EmptyBuffer();
    }

    private void EmptyBuffer()
    {
        Vertices = (float[])null;
        Colors = (int[])null;
    }

    public void Delete()
    {
        Dispose();
    }

    public PointCloud(float[] points)
    {
        this.vbo_size = points.Length;
        GL.GenBuffers(2, this.vbo_id);
        GL.BindBuffer(BufferTarget.ArrayBuffer, this.vbo_id[0]);
        GL.BufferData<float>(BufferTarget.ArrayBuffer, new IntPtr(points.Length * BlittableValueType.StrideOf<float>(points)), points, BufferUsageHint.StaticDraw);

        Vertices = points;
    }

    public void ApplyColorMap(int[] colors)
    {
        GL.BindBuffer(BufferTarget.ArrayBuffer, this.vbo_id[1]);
        GL.BufferData<int>(BufferTarget.ArrayBuffer, new IntPtr(colors.Length * BlittableValueType.StrideOf<int>(colors)), colors, BufferUsageHint.StaticDraw);

        Colors = colors;

        this.HasColor = true;
    }

    public void Render(FrameEventArgs e)
    {
        GL.EnableClientState(ArrayCap.VertexArray);
        GL.BindBuffer(BufferTarget.ArrayBuffer, this.vbo_id[0]);
        GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, new IntPtr(0));
        GL.DrawArrays(BeginMode.Points, 0, this.vbo_size);
        if (!this.HasColor)
        {
            return;
        }
        GL.BindBuffer(BufferTarget.ArrayBuffer, this.vbo_id[1]);
        GL.ColorPointer(4, ColorPointerType.UnsignedByte, 4, IntPtr.Zero);
        GL.EnableClientState(ArrayCap.ColorArray);
    }

    public void Dispose()
    {
        EmptyBuffer();

        GL.DeleteBuffers(vbo_id.Length, vbo_id);
        this.vbo_id = new int[2];
    }
}

this is my render code:

protected override void OnRenderFrame(FrameEventArgs e)
{
    base.OnRenderFrame(e);
    GL.MatrixMode(MatrixMode.Modelview);
    GL.Clear(ClearBufferMask.DepthBufferBit | ClearBufferMask.ColorBufferBit);
    GL.LoadMatrix(ref this.CameraMatrix);


    GL.PushMatrix();
    this.pointclouds.ForEach((Action<PointCloud>)(i =>
    {
        //blend
        GL.Enable(EnableCap.Blend);

        if (i.Visible)
        {
            GL.PushMatrix();
            GL.PointSize(2.0f);
            if (!i.HasColor)
            {
                GL.Color4(Color.White);
            }
            i.Render(e);
            GL.PopMatrix();
        }
    }));

    GL.PopMatrix();
}
هل كانت مفيدة؟

المحلول

The reason that it is not working is that you never disable clientState(ArrayCap.ColorArray). This will cause OpenGL to reuse this information endlessly. A good approach is before you leave your render method to ALWAYS disable all client states that you enabled at the beginning of your function. In your case you can simplify things by removing your color VBO completely, since your points only have a single color anyway. You already try to do this for !hasColor case anyway

Secondly, and I'm not sure if it was on purpose. In your render function you never set the correct color: When you call drawArrays you sent the information to the GPU, and after that you load the colors. This will cause the next point to have the previous color.

Something like this:

public void Render(FrameEventArgs e)
{
    GL.EnableClientState(ArrayCap.VertexArray);
    GL.BindBuffer(BufferTarget.ArrayBuffer, this.vbo_id[0]);
    GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, new IntPtr(0));
    if (!this.HasColor) GL.Color4f(0,0,0);
    else GL.Color4f(putcolorvalue);
    GL.DrawArrays(BeginMode.Points, 0, this.vbo_size);
    GL.DisableClientState(ArrayCap.VertexArray);
}

نصائح أخرى

I think you have to disable the ArrayCap.ColorArray state, if not the latest applied color array will be used:

GL.DisableClientState(ArrayCap.ColorArray);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top