[ASK] Object3D max triangles

Started by naldo, November 13, 2014, 09:31:44 AM

Previous topic - Next topic

naldo

I have been using this superb engine for a week.

So, noob question:
My program needs to generate a mesh dynamically.
Any way to change the max triangles of an Object3D at runtime?

If there isn't, which is recommended:
1. Set the 'maxTriangles' to huge number at the initialization time (Object3D constructor). Will this lower the performance?
2. Remove the old Object3D from the world and add the new Object3D (with new max triangles).

Thank you.

EgonOlsen

It depends...what do you want to do exactly?

naldo

My program will calculate & display a path/route based on user inputs.
Kinda like gps software or google maps.
So the mesh will be different for each new route.




Side question:
how to use update(float[], int) on VertexAttributes to update only a fraction of data?

I've tried something like:

float[] data = new float[420];
VertexAttributes attribs = ....;
attribs.setDynamic(true);
....

// then somewhere in code
// modify data
data[6] = 0;
data[7] = 1;
attribs.update(data, 6);



And I got RuntimeException: ERROR: Invalid size: 6/420

But when i use 0 for the start parameter in update(float[] data, int start), i.e. attribs.update(data, 0),
it works fine.

Thanks.

EgonOlsen

You can do such stuff with a VertexController, but the idea is a little different (and a bit hacky...). Basically, you create an Object3D, which is "big enough", move all unused vertices out of the view and update those that should be visible. Here's an example for desktop jPCT:


import java.awt.Color;

import com.threed.jpct.*;
import com.threed.jpct.util.Light;


public class TrailTest
{
  private static int TRAIL_POLYGONS = 1000;

  private World world;
  private FrameBuffer buffer;
  private Object3D sphere;

  private Object3D trail;


  public static void main(String[] args)
    throws Exception
  {
    new TrailTest().loop();
  }


  public TrailTest()
    throws Exception
  {
    world = new World();
    world.setAmbientLight(100, 100, 100);

    sphere = Primitives.getSphere(20, 1f);
    sphere.build();
    sphere.compile();
    sphere.translate(-100, 0, 50);
    world.addObject(sphere);

    Camera cam = world.getCamera();
    cam.setPosition(0, -50, 0);
    cam.lookAt(sphere.getTransformedCenter());

    Light light = new Light(world);
    light.setPosition(new SimpleVector(-100, 0, -150));
    light.setAttenuation(-1);

    trail = createTrailObject(sphere);
    trail.build();
    trail.compile(true);
    world.addObject(trail);
  }


  /**
   * This looks a bit hacky...it creates an object with a defined number of unique polygons that are all out of sight.
   * The vertex controller will then take polygons from this soup that arrange them to form the trail.
   *
   * @param emitter
   * @return
   */
  private Object3D createTrailObject(Object3D emitter)
  {
    Logger.log("Creating trail object...");
    Object3D trail = new Object3D(TRAIL_POLYGONS);
    trail.disableVertexSharing();
    for (int i = 0; i < TRAIL_POLYGONS / 2; i++)
    {
      trail.addTriangle(new SimpleVector(-1100000 + i, -1200000 + i, -1300000 + i), new SimpleVector(-1400000 + i,
          -1500000 + i, -1600000 + i), new SimpleVector(-1700000 + i, -1800000 + i, -1900000 + i));
      trail.addTriangle(new SimpleVector(2000000 + i, 2100000 + i, 2200000 + i), new SimpleVector(2300000 + i,
          2400000 + i, 2500000 + i), new SimpleVector(2600000 + i, 2700000 + i, 2800000 + i));
    }

    trail.calcNormals();
    trail.getMesh().setVertexController(new TrailBlazer(emitter), false);
    trail.forceGeometryIndices(false);
    trail.compile(true);
    trail.build();

    trail.setAdditionalColor(Color.YELLOW);
    trail.setCulling(Object3D.CULLING_DISABLED);
    trail.setTransparency(0);

    return trail;
  }


  private void loop()
    throws Exception
  {
    Config.glUseVBO = true;

    buffer = new FrameBuffer(640, 480, FrameBuffer.SAMPLINGMODE_NORMAL);
    buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
    buffer.enableRenderer(IRenderer.RENDERER_OPENGL);

    float cnt = 0;
    float y = 0;
    float yAdd = -0.1f;

    while (!org.lwjgl.opengl.Display.isCloseRequested())
    {
      SimpleVector lastTrans = sphere.getTranslation();
      sphere.translate((float) Math.sin(cnt), yAdd, (float) Math.cos(cnt));
      SimpleVector newTrans = sphere.getTranslation();
      lastTrans.sub(newTrans);
      sphere.getRotationMatrix().setTo(lastTrans.getRotationMatrix());

      trail.getMesh().applyVertexController();
      trail.touch();

      cnt += 0.05f;

      if (y < -40)
      {
        yAdd = 0.1f;
      }
      else if (y > 40)
      {
        yAdd = -0.1f;
      }
      y += yAdd;

      buffer.clear(java.awt.Color.BLACK);
      world.renderScene(buffer);
      world.draw(buffer);
      buffer.update();
      buffer.displayGLOnly();
      Thread.sleep(10);
    }
    System.exit(0);
  }


  private static class TrailBlazer
    extends GenericVertexController
  {
    private int maxPos = TRAIL_POLYGONS / 2;
    private int pos = 0;
    private Object3D emitter = null;
    private SimpleVector p0 = new SimpleVector();
    private SimpleVector p1 = new SimpleVector();
    private SimpleVector p2 = new SimpleVector();
    private SimpleVector p3 = new SimpleVector();
    private SimpleVector center = new SimpleVector();
    private SimpleVector lastP2 = null;
    private SimpleVector lastP3 = null;
    private SimpleVector z = new SimpleVector();
    private SimpleVector x = new SimpleVector();
    private SimpleVector tmp = new SimpleVector();

    private static final long serialVersionUID = 1L;


    public TrailBlazer(Object3D emitter)
    {
      this.emitter = emitter;
    }


    public void apply()
    {
      center = emitter.getTransformedCenter(center);
      SimpleVector[] dest = this.getDestinationMesh();

      z = emitter.getRotationMatrix().getZAxis(z);
      x = emitter.getRotationMatrix().getXAxis(z);

      if (lastP2 == null)
      {
        tmp.set(center);
        tmp.sub(x);
        lastP2 = new SimpleVector(tmp);
        tmp.add(x);
        tmp.add(x);
        lastP3 = new SimpleVector(tmp);
      }

      p0.set(lastP2);
      p1.set(lastP3);

      int cPos = pos * 6;

      tmp.set(center);
      tmp.sub(z);
      tmp.sub(x);
      p2.set(tmp);
      tmp.add(x);
      tmp.add(x);
      p3.set(tmp);

      dest[cPos++].set(p0);
      dest[cPos++].set(p1);
      dest[cPos++].set(p3);

      dest[cPos++].set(p2);
      dest[cPos++].set(p0);
      dest[cPos].set(p3);

      pos++;
      if (pos >= maxPos)
      {
        pos = 0;
      }
      lastP2.set(p2);
      lastP3.set(p3);
    }
  }
}


naldo

#4
Quote from: EgonOlsen on November 13, 2014, 01:08:53 PM
You can do such stuff with a VertexController, but the idea is a little different (and a bit hacky...). Basically, you create an Object3D, which is "big enough", move all unused vertices out of the view and update those that should be visible.

oh right.
With VertexController, i don't need to recreate the vertices nor the Object3D instances.
I just need to modify the vertices directly.

I will use this for my final program if my previous method starting to get "ugly" in the future.
Many thanks.


for the side question:
how to update only a fraction of data in VertexAttribute?
Say i just want to update data at index 100 to 200.
Does this do-able?

EgonOlsen

To update a part of the attributes, you have an array with a fitting size. In your example, you are trying to stuff an array with the size of 420 into VAs with the size of 420, starting at index 6. It doesn't work that way. Your array should be 414 in size and the data has to start at index 0, not 6 in that array.

naldo

Quote from: EgonOlsen on November 13, 2014, 06:50:07 PM
To update a part of the attributes, you have an array with a fitting size. In your example, you are trying to stuff an array with the size of 420 into VAs with the size of 420, starting at index 6. It doesn't work that way. Your array should be 414 in size and the data has to start at index 0, not 6 in that array.

Does it mean 'start' parameter always has to be zero?
'start' parameter is the index for updatedData right?
With same vertex attribute data above (length 420),  I've tried:


float[] updatedData = { 1, 2, 3, 4 };
attribs.update(updatedData, 1);

with same Exception, Invalid size: 1/4.

Now, I'm just curious why it doesn't work when 'start' parameter has a value larger than zero.


And,
when I update VertexAttributes data, the order of the vertex is often change between each run.
Is this the expected behaviour when vertex sharing is enabled?

Thanks.

EgonOlsen

That index stuff is a bug. I'll fix it later and upload a new version. About the second question: I'm not sure what you mean by that... ???

naldo

#8
Quote from: EgonOlsen on November 14, 2014, 09:56:25 AM
That index stuff is a bug. I'll fix it later and upload a new version. About the second question: I'm not sure what you mean by that... ???

Ok, thanks.

For my second question,
suppose i have these vertices  to make 4 quads.

b d f h j
a c e g i


I add it with:

addTriangle (a, c, b);
addTriangle (b, c, d);

addTriangle (c, e, d);
addTriangle (d, e, f);

addTriangle (e, g, f);
addTriangle (f, g, h);

addTriangle (g, i, h);
addTriangle (h, i, j);


What is the order of the vertex with vertex sharing enabled?
When i update my VertexAttributes data, the order of vertex sometimes becomes "ab-cd-ef-gh-ij", and sometimes in another run it becomes "ac-bd-eg-fh-ij".

Thanks

EgonOlsen

Once created, the vertex order doesn't change. I'm not sure what you mean by 'run'?! A new app start or a new attribute update?

naldo

Quote from: EgonOlsen on November 14, 2014, 10:44:59 AM
Once created, the vertex order doesn't change. I'm not sure what you mean by 'run'?! A new app start or a new attribute update?

sorry, what i mean with 'run' is start/launch the app.

EgonOlsen

Which order changes? The one of the created Object3D or the one of the object on the GPU?

naldo

Sry.
Can't really check now. I'm away from my computer that containing the code.
But I think it's from the Object3D (or Mesh?).
I remember that i had logged the vertices position days ago.
Sometimes the order is different, even though the add-order is always the same.
The last time I'm sure the order is changing is when I add the vertex attributes data, especially with color information.

Currently i'm using Object(float[] coordinates, float[] uvs, int[] indices, int textureId) to ensure the order.
And it works flawlessly.

Thanks.


EgonOlsen

The vertex sharing internally uses a HashMap. I would think that it will create the same order as long as the input values are deterministic. But maybe that's not the case. Anyway, if the bulk constructor works fine, then just use that.

EgonOlsen