I am trying Rajawali library for Android to draw some basic 3d objects on the scene.
There is a sample 2000 planes, which show how to render huge amount of vertexes very "cheaply" with one shader. I can pass array of vertexes to the shader and draw them.
I want to upgrade this sample and move some vertexes independently from each other.
I've tried glBufferSubData, but i cant change anything on the scene. The one way i've found is to change data and recreate buffer, but i hope there is a simpler way to only change the necessary data.
For example, I only want to change some positions from already created and binded buffer.
initialize positions
float[] planePositions = new float[numVertices * 3];
....
create buffer
mGeometry.createBuffer(mPlanePositionsBufferInfo, BufferType.FLOAT_BUFFER, mPlanePositions, GLES20.GL_ARRAY_BUFFER);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
set positions
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, planePosBufferHandle);
GLES20.glEnableVertexAttribArray(maPlanePositionHandle);
fix.android.opengl.GLES20.glVertexAttribPointer(maPlanePositionHandle, 3, GLES20.GL_FLOAT,
false, 0, 0);
and how can i modify position of, for example, the first vertex of the first plane ? (planePositions[0] = a;planePositions[1] = b; planePositions[1] = c... and now i have to pass this modified array to opengl but don't know how).
All you need to do is modify the buffer data then call mGeometry.changeBufferData() from the PlanesGalore class. I put the following code in an update method which is called during the onDrawFrame() event of my Renderer class.
for (int i = 0; i < vertices.length; i += 3) {
mPlanePositions= mPlanePositions.put(i, mPlanePositions.get(i) - 0.01f);
}
mGeometry.changeBufferData(mCubePositionsBufferInfo, mPlanePositions, 0);
This is the best way I could find for accomplishing the movements. Additionally, I have proposed a change in this issue that would let you specify what part of the buffer changed which should provide increased performance.
EDIT
My change to the engine has been approved so you can now optimize this even further like so.
// The offset position should be vertices.length * object #. In my use case this is 72*x
// allowing me to update the XYZ coordinates of all 24 vertices of a cube.
int offsetPosition = 0;
mGeometry.changeBufferData(mCubePositionsBufferInfo, mPlanePositions, offsetPosition, offsetPosition + vertices.length);
Related
I create little sprites of sheeps on the top of my screen, then they should go down and after crossing bottom line they disappear. Problem is that when they are going across the screen it is very noticable that sometimes they lag. For milliseconds but its possible to see it. It happens absolutely randomly. They change their position with Gdx.graphics.getDeltaTime();
public void update (float deltaTime) {
updateMotionX(deltaTime);
updateMotionY(deltaTime);
// Move to new position
position.x += velocity.x * deltaTime;
position.y += velocity.y * deltaTime;
}
Here is the code of spawing them:
private Sheep spawnSheep(){
Sheep sheep = new Sheep();
sheep.dimension.set(dimension);
// select random cloud image
sheep.setRegion(regSheeps.random());
// position
Vector2 pos = new Vector2();
pos.x = -0.19f; // position after end of level
pos.y = 5;
sheep.position.set(pos);
//speed
Vector2 speed = new Vector2();
speed.y = 3.5f;
sheep.terminalVelocity.set(speed);
speed.y *= -1;
sheep.velocity.set(speed);
return sheep;
}
Maybe somebody already had that problem, i have no idea why it happens,
The lagging is most likely caused by garbage collection because you're continuously allocating memory within your game loop.
You want to avoid calling new whenever possible in the game loop, and if you do call new you want to reuse those objects whenever possible.
Look at pools in libgdx
http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/utils/Pool.html
If you're returning an object from a method, such as a Vector2, then create a static instance and reuse that object for return values. Be aware that this is not thread safe and calling the method again will overwrite the value from the first call.
If I was you I'd search for any instances of the word 'new' in your code, and make sure none of them are called frequently within the game loop. You also want to be aware of calling methods that will create instances of objects. Simple things like converting an integer to a string will waste memory, as well as more obvious things like creating a copy of an array.
You should find this useful for tracking memory allocation.
https://visualvm.java.net/
I have 2 classes; A and B.
A is the character class, it contains every character detail (position...)
B is the class which get the A class and render. I need to create another object when I touch the screen. I got it, the class seems containing the new values but it doesn't renderize them.
for (A a: aa) {
shapeRenderer.begin(ShapeType.Filled);
shapeRenderer.setColor(Color.RED);
shapeRenderer.circle(a.getBoundingCircle().x, a.getBoundingCircle().y, a.getBoundingCircle().radius);
shapeRenderer.end();
}
is recommended use best names.
are you sure a.getBoundingCircle() cotains the correct data, and are you sure had objects A in aa and your program join inside the for?
and i dont look b
Ok, your problem is the new values dont be renderized.
Two options:
You not are running the loop for render the objects.
Your new values are out of the screen.
When you get the position of the touch events you get the screenx and the screeny, not the game camera coordenates, and you need convert it with unproject.
For example:
Vector3 touchPos = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touchPos);
touchPos now is in the game coordenates.
I'm using LibGDX for my Android app. I need to move and orient 3D object(ModelInstance) along a spline.In my case it's CatmullRomSpline. I got the movement working but having problem with orienting the ModelInstance along the spline.
My Code:
public void update() {
float t = SPEED * Gdx.graphics.getDeltaTime();
elapsedTime = elapsedTime + SPEED * Gdx.graphics.getDeltaTime();
//Movement
catmull.valueAt(value, elapsedTime);
myObject3d.transform.setTranslation(value);
//Rotation
derivative = catmull.derivativeAt(derivative, t);
derivative = derivative.nor();
//Tried to bring object into default position before rotating
//Vector.X - is the default direction of my Object - facing right
//myObject3d.transform.rotate(Vector3.X, Vector3.X);
myObject3d.transform.rotate(derivative, Vector3.X);
}
The Matrix4#rotate method has two arguments, base and target. In your case the base vector should be Vector3.X, while the target is derivative. You need to swap the arguments for this. Also, the Matrix4#rotate method post-multiplies the rotation on top the existing rotation. Or in other words: this will accumulate the absolute rotation on every call. You probably want to use the Matrix4#setToRotation method instead, which resets the rotation on every call (clears the matrix).
myObject3d.transform.setToRotation(Vector3.X, derivative);
myObject3d.transform.setTranslation(value);
While this probably will work in most cases, you might get unexpected results depending on the path. Like said, there are infinite possible rotations that will result in this direction. Therefor it's better to use two additional vectors to specify the up (Y) and right (Z) vector.
right.set(Vector3.Y).crs(derivative).nor();
up.set(right).crs(derivative).nor();
myObject3d.transform.set(derivative, up, right, position).rotate(Vector3.X, 180);
Here the cross product is used to calculate the right and up vectors, where it is assumed that Vector3.Y is usually close to the up vector. Then the Matrix4#set method is used to set the matrix to reflect these values. The first argument specifies the "new" X-axis, the second the "new" Y-axis, the third the "new" Z-axis and the last argument specifies the translation (location).
Here's a working example: https://gist.github.com/xoppa/7558c0c75e9534795e9f
Although unrelated, keep in mind that path.valueAt method uses 0 <= t <= 1. Or in other words, t (elapsedTime in your code) should not be below 0 or above 1.
I can set a value in my shader like so:
public void setOpacity(float op){
GLES20.glUseProgram(iProgId);
// get handle to transformation matrix
mOpacityHandle = GLES20.glGetUniformLocation(iProgId, "opValue");
//Apply the opacity value
GLES20.glUniform1f(mOpacityHandle, op);
}
This works fine (in this particular instance, I am using this code to set the opacity of my quad)
However, how would I be able to query the value that I just set from the shader? For example to use in a getOpacity method?
OpenGL ES has no provision for reading values back from any shader. This is why shader code can be really difficult to debug.
It is possible to read back what the fragment shader renders into the framebuffer with glReadPixels(), but this is so slow that it's really only practical as a debugging technique.
You can't read back values written by the shader, but you can read back the value of a uniform from the program state using glGetUniformfv.
So the getter corresponding to your setter would be something like:
public float getOpacity(void){
float value;
mOpacityHandle = GLES20.glGetUniformLocation(iProgId, "opValue");
GLES20.glGetUniformfv(iProgId, mOpacityHandle, &value);
return value;
}
See the Khronos man pages for further info.
I have a scene that contains a bunch of objects, for example lets say it's a simple grid of tiles. So there's a main "border" object, and then (rows x columns) cells.
For simplicity, assume each cell is a simple four-segment line consisting of a four-node GL_LINE_LOOP.
Currently, my frame rate is awefull, and it seems to sit in all the glVertexBuffer() calls that I'm making, as each cell has it's own set of vertices, so it's own call to glVertexPointer:
class MyModel extends Model {
...
public void onDrawFrame(GL10 gl) {
gl.glVertexPointer(0, GL10.GL_FLOAT, 0, mBuffer);
gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, 4);
}
}
Should I instead track all of my distinct primitive models in a world super-object, and keep a copy of all the vertices in memory? I could then perform a single glVertexPointer call at the start of each frame, and use offsets for the DrawArrays.
class MyModel extends Model {
public MyModel() {
// do something clever in parent Model class to track total verts
this.offsetId = somethingFromSuper();
}
public void onDrawFrame(GL10 gl) {
// super's vertices should all have been already sent to GL
gl.glDrawArrays(GL10.GL_LINE_LOOP, this.offsetId, 4);
}
}
I don't think that would make a big difference: you are still calling separate gl draw commands for each model. Instead, you probably want to have the drawing taken care of by the 'world' class that will combine all model vertices into one big array, and draw that with one call. Other than iterating through the models to get their vertex info and constructing the 'world' array, instead of calling a draw on each model, it is pretty much the same.
This approach is absolutely necessary if the render commands draw less than 30 vertices, according to this article from Qualcomm (bit old, but probably still relevant): http://www.cin.ufpe.br/~mact/graduacao/so/dia1/progpc21_dorbie_3dgraphics.pdf
You wouldn't be able to use GL_LINE_LOOP in this case, but would need to use GL_LINES instead. If you are drawing tris, you can use GL_TRIANGLES or GL_TRIANGLE_STRIP with degenerate triangles inserted to detach the models.
Cheers, Aert.