Author Topic: Terrain and GenericVertexController..  (Read 7860 times)

Offline LowPolyMan

  • byte
  • *
  • Posts: 25
    • View Profile
Terrain and GenericVertexController..
« on: March 21, 2013, 05:33:23 pm »
I'm playing a bit with the terrain example (found on wiki) using a (heightmap) image. I added a cube and simple collisiondetection. It all works ok. Now i wanted to change the height of the terrain in realtime and i added a GenericVertexController, wich also works well. Now i like to change the height of the terrain only arround the location of the cube. The height of the terrain is stored in a float array terrain[][] and the height of the terrain in the GenericVertexController apply method is stored in a Mesh (SimpleVector[].y).

This is what i do now in my apply method:
Code: [Select]
SimpleVector[] d = getDestinationMesh();
int tx = (int) (Cube.getTranslation().x + 640) / 10;  //The + 640, terrain starts at -640 ends at 640
int tz = (int) (Cube.getTranslation().z + 640) / 10;  //In reality it was -560 to 560.. very strange also
int i = 0;
terrain[tx][tz]=-256;
for (int x = 0; x < X_SIZE ; x++) {
for (int z = 0; z < Z_SIZE ; z++) {
d[i].y = terrain[x][z];
i++;
}
}
this.updateMesh();

The above code does change the height on a certain location on the terrain, but not on the location of the cube. And i tried all kind of things. I must be doing something wrong..

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: Terrain and GenericVertexController..
« Reply #1 on: March 21, 2013, 09:02:28 pm »
Have you checked the value for tx and tz and how they differ from the expected values?

Offline LowPolyMan

  • byte
  • *
  • Posts: 25
    • View Profile
Re: Terrain and GenericVertexController..
« Reply #2 on: March 21, 2013, 09:07:41 pm »
Have you checked the value for tx and tz and how they differ from the expected values?

Tnx for the fast reply but i seem to have fixed it, the apply code was correct but when creating the heightmap object i rotated it and add a new matrix. After uncommenting these lines it started to work right.

Offline LowPolyMan

  • byte
  • *
  • Posts: 25
    • View Profile
Re: Terrain and GenericVertexController..
« Reply #3 on: March 22, 2013, 01:00:07 pm »
Another question, about changing the texture at some point on the map, i found this example JPCT applet:

Applet http://www.paulscode.com/source/calcMinDistanceTest/
Code   http://www.paulscode.com/source/calcMinDistanceTest/MapClick.java

I tried this in JPCT AE but the texture never seems to change, mabe i made some error.

Code (from helloworld example):
Code: [Select]
package com.threed.jpct.example;

import java.lang.reflect.Field;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.opengles.GL10;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.ViewGroup.LayoutParams;
import com.threed.jpct.Camera;
import com.threed.jpct.Config;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Interact2D;
import com.threed.jpct.Light;
import com.threed.jpct.Logger;
import com.threed.jpct.Object3D;
import com.threed.jpct.OcTree;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.BitmapHelper;
import com.threed.jpct.util.MemoryHelper;

/**
 * A simple demo. This shows more how to use jPCT-AE than it shows how to write
 * a proper application for Android. It includes basic activity management to
 * handle pause and resume...
 *
 * @author EgonOlsen
 *
 */
@SuppressLint("NewApi")
public class HelloWorld extends Activity {

// Used to handle pause and resume...
private static HelloWorld master = null;
private GLSurfaceView mGLView;
private MyRenderer renderer = null;
private FrameBuffer fb = null;
private World world = null;
private Camera camera = null;
private RGBColor back = new RGBColor(50, 50, 100);
private float touchTurn = 0;
private float touchTurnUp = 0;
private float xpos = -1;
private float ypos = -1;
private Object3D terrain;
private int fps = 0;
private Light sun = null;
String status = "Loading..";
boolean status_midx=true;
boolean status_midy=true;
int polyIdOffset;
    private String outputLine1 = "";
    private String outputLine2 = "";
    private String outputLine3 = "";

protected void onCreate(Bundle savedInstanceState) {
Logger.log("onCreate");
if (master != null) {
copy(master);
}
super.onCreate(savedInstanceState);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
mGLView = new GLSurfaceView(getApplication());
mGLView.setEGLConfigChooser(new GLSurfaceView.EGLConfigChooser() {
@SuppressLint("NewApi")
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
// Ensure that we get a 16bit framebuffer. Otherwise, we'll fall
// back to Pixelflinger on some device (read: Samsung I7500)
int[] attributes = new int[] { EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_NONE };
EGLConfig[] configs = new EGLConfig[1];
int[] result = new int[1];
egl.eglChooseConfig(display, attributes, configs, 1, result);
return configs[0];
}
});
requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
renderer = new MyRenderer();
mGLView.setRenderer(renderer);
setContentView(mGLView);
        DrawOnTop mDraw = new DrawOnTop(this);
        addContentView(mDraw, new LayoutParams (LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}

@Override
protected void onPause() {
super.onPause();
mGLView.onPause();
}

@Override
protected void onResume() {
super.onResume();
mGLView.onResume();
}

@Override
protected void onStop() {
super.onStop();
}

private void copy(Object src) {
try {
Logger.log("Copying data from master Activity!");
Field[] fs = src.getClass().getDeclaredFields();
for (Field f : fs) {
f.setAccessible(true);
f.set(this, f.get(src));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public boolean onTouchEvent(MotionEvent me) {
float x,y;
if (me.getAction() == MotionEvent.ACTION_DOWN) {
x = me.getX();
y = me.getY();
// Get the 3D coordinates in Camera space:
SimpleVector position = new SimpleVector(Interact2D.reproject2D3D(camera, fb, (int)x, (int)y));
// Convert the coordinates to World space:
position.matMul(camera.getBack().invert3x3());
position.add(camera.getPosition());
// Determine the direction from the camera position to the click
// point:
SimpleVector direction = position.calcSub(camera.getPosition()).normalize();
// Calculate the distance to whatever was clicked on:
float distance = world.calcMinDistance(position, direction, 10000);
// Check if we clicked on something:
if (distance == Object3D.COLLISION_NONE) {
// Nope, didn't click on anything. Reset the output messages:
outputLine1 = "No Collision";
outputLine2 = "";
outputLine3 = "";
} else {
// Calculate the exact 3D coordinates for the point that was
// clicked:
SimpleVector collisionPoint = new SimpleVector(direction);
collisionPoint.scalarMul(distance);
collisionPoint.add(position);
// Determine what cell of the map was clicked on (cells are
// 5x5):
int mapGridX = (int) collisionPoint.x / 5;
int mapGridY = (int) collisionPoint.z / 5;
// determine the polygon ID of the first triangle in the cell:
int polyId1 = ((32 * mapGridY + mapGridX) * 2) + polyIdOffset;
// Color both polygons in the cell Red:
terrain.getPolygonManager().setPolygonTexture(polyId1,
TextureManager.getInstance().getTextureID("Red"));
terrain.getPolygonManager().setPolygonTexture(polyId1 + 1,
TextureManager.getInstance().getTextureID("Red"));
// Generate the output messages:
outputLine1 = "Collision: " + collisionPoint;
outputLine2 = "    2D Map Coordinates: ( " + collisionPoint.x
+ ", " + collisionPoint.z + " )";
outputLine3 = "    Map Cell: ( " + mapGridX + ", " + mapGridY
+ " )";
}
return true;
}

if (me.getAction() == MotionEvent.ACTION_UP) {
xpos = -1;
ypos = -1;
touchTurn = 0;
touchTurnUp = 0;
return true;
}

if (me.getAction() == MotionEvent.ACTION_MOVE) {
float xd = me.getX() - xpos;
float yd = me.getY() - ypos;
xpos = me.getX();
ypos = me.getY();
touchTurn = xd / -100f;
touchTurnUp = yd / -100f;
return true;
}

try {
Thread.sleep(15);
} catch (Exception e) {
// No need for this...
}

return super.onTouchEvent(me);
}

protected boolean isFullscreenOpaque() {
return true;
}

class MyRenderer implements GLSurfaceView.Renderer {

private long time = System.currentTimeMillis();

public MyRenderer() {
Config.glTransparencyMul = (1.0f / 255);
        Config.glTransparencyOffset = (1.0f / 255);
        Config.farPlane = 10000;
        Config.maxPolysVisible = 10000;
}

public void onSurfaceChanged(GL10 gl, int w, int h) {
if (fb != null) {
fb.dispose();
}
fb = new FrameBuffer(gl, w, h);
if (master == null) {
world = new World();
world.setAmbientLight(50, 50, 50);
sun = new Light(world);
sun.setIntensity(20, 20, 20);
SimpleVector sv = new SimpleVector(80, -160, 80);
sun.setPosition(sv);

status = "Loading textures..";

// create some colorful textures to use on the terrain:
Texture Grey = new Texture(BitmapHelper.rescale(BitmapHelper.convert(getResources().getDrawable(R.drawable.grey)), 256, 256));
TextureManager.getInstance().addTexture("Grey", Grey);
Texture Red = new Texture(BitmapHelper.rescale(BitmapHelper.convert(getResources().getDrawable(R.drawable.red)), 256, 256));
TextureManager.getInstance().addTexture("Red", Red);

status = "Creating object..";
   
// create the terrain object and add it to the world:
        createTerrain();
        world.addObject( terrain );
        // set up the terrain object to receive collisions:
        terrain.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS );
        // make sure all Object3Ds in the world are built:
        world.buildAllObjects();
       
        status = "Add camera and compact memory..";
       
        // set the camera position and orientation:
        camera = world.getCamera();
        camera.setPosition( -80, -160, -80 );
        camera.lookAt( new SimpleVector( 80, 0, 80 ) );

MemoryHelper.compact();

status = "";

if (master == null) {
Logger.log("Saving master Activity!");
master = HelloWorld.this;
}
}
}

// Generate the terrain Object3D:
    public void createTerrain()
    {
        int x, y;
        terrain = new Object3D( 2048 );  // specify the number of polys
        // Create the terrain's vertices (each cell size is 5x5):
        SimpleVector[][] vertices = new SimpleVector[33][33];
        for( y = 0; y < 33; y++ )
        {
            for( x = 0; x < 33; x++ )
            {
                vertices[x][y] = new SimpleVector( x * 5, 0, y * 5 );
            }
        }
        // Create the terrain's polys, set their UV coordinates,
        // and set their initial texture to grey:
        for( y = 0; y < 32; y++ )
        {
            for( x = 0; x < 32; x++ )
            {
                terrain.addTriangle( vertices[x][y+1], 0, 0,
                          vertices[x][y], 0, 1,
                          vertices[x+1][y], 1, 1,
                          TextureManager.getInstance().getTextureID( "Grey" ) );
                terrain.addTriangle( vertices[x+1][y], 1, 1,
                          vertices[x+1][y+1], 1, 0,
                          vertices[x][y+1], 0, 0,
                          TextureManager.getInstance().getTextureID( "Grey" ) );
            }
        }
        // build the Object3D (generates bounding box and normals):
        terrain.build();
        // Create an OcTrea for the terrain's mesh
        // (allows vertices to be changed later and optimizes speed)
        OcTree ocTree = new OcTree( terrain.getMesh(), 2048,
                                    OcTree.MODE_OPTIMIZED );
        // Optimizes collision detection on the OcTree:
        ocTree.setCollisionUse( OcTree.COLLISION_USE );
        // Assign the OcTree to the terrain Object3D:
        terrain.setOcTree( ocTree );
        // Determine the poly ID of the first polygon in the terrain object:
        polyIdOffset = terrain.getPolygonManager().getMaxPolygonID()
                       - terrain.getMesh().getTriangleCount();
    }

public void onSurfaceCreated(GL10 gl, EGLConfig config) {
status_midx=true;
status_midy=true;
status = "";
}

public void onDrawFrame(GL10 gl) {
if (touchTurn != 0) {
//cube.rotateY(touchTurn);
touchTurn = 0;
}
if (touchTurnUp != 0) {
//cube.rotateX(touchTurnUp);
touchTurnUp = 0;
}
status = outputLine1 + ", " + outputLine2 + ", " + outputLine3;
fb.clear(back);
world.renderScene(fb);
world.draw(fb);
fb.display();
if (System.currentTimeMillis() - time >= 1000) {
Logger.log(fps + "fps");
fps = 0;
time = System.currentTimeMillis();
}
fps++;
}
}
class DrawOnTop extends View {
Paint paint = new Paint();
Rect bounds = new Rect();
int x;
int y;
int tmpx;
int tmpy;
public DrawOnTop(Context context) {
super(context);
}
public void drawing(Canvas canvas) {
if (status.length() > 0) {
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLACK);
paint.setTextSize(48);
paint.setAntiAlias(true);
paint.setAlpha(255);
if (status_midx)
{
tmpx = (int) paint.measureText(status);
x = canvas.getWidth()/2 - (tmpx/2);
}
else
{
x = (canvas.getWidth() / 40);
}
if (status_midy)
{
paint.getTextBounds(status, 0, status.length(), bounds);
tmpy = bounds.bottom;
y = canvas.getHeight()/2 - (tmpy/2);
}
else
{
y = 48;
}
canvas.drawText(status, x - 1, y - 1, paint);
canvas.drawText(status, x + 1, y - 1, paint);
canvas.drawText(status, x + 1, y + 1, paint);
canvas.drawText(status, x - 1, y + 1, paint);
paint.setColor(Color.WHITE);
canvas.drawText(status, x, y, paint);
}
}
@Override
protected void onDraw(Canvas canvas) {
drawing(canvas);
super.onDraw(canvas);
this.invalidate();
}
}   

}

Offline LowPolyMan

  • byte
  • *
  • Posts: 25
    • View Profile
Re: Terrain and GenericVertexController..
« Reply #4 on: March 22, 2013, 02:35:04 pm »
Just seen a post from 2010 where i read JPCT AE can't change texture after object is compiled, only the UV's can be changed... I quess this is still the case. :(

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: Terrain and GenericVertexController..
« Reply #5 on: March 22, 2013, 02:38:10 pm »
Yes, that's correct. The reason is that the geometry will be batched/compiled based on texture states.

Offline LowPolyMan

  • byte
  • *
  • Posts: 25
    • View Profile
Re: Terrain and GenericVertexController..
« Reply #6 on: March 23, 2013, 10:07:20 am »
Yes, that's correct. The reason is that the geometry will be batched/compiled based on texture states.

Ok, well then the second option is to include the texture and use UV coords. I made a new texture containing a light texture 256x512 and a dark texture 256x512 horizontal left and right.
( i first did it 512x512 and 512x512, the total texture size is 1024x512 and it loaded well :P)

When i want to map the first texture i just do x 0.0 to 0.4999, but i can't seem to get the second one from 0.5 to 1.0. When i try that i just get the whole texture. I tried a lot of things..

UPDATE:

I found reTexture() code on the forum that works well. It takes a variable tileFactor, when i put that to -0.5 it maps the left upper part of the texture and when i put that to 0.5 it maps the low right part. So i created my texture accordingly. This seems to work for me, i know it's a bit unnecessary memory consumption  not using the upper right and lower left part of the texture pixels.
« Last Edit: March 23, 2013, 11:41:40 am by LowPolyMan »

Offline LowPolyMan

  • byte
  • *
  • Posts: 25
    • View Profile
Re: Terrain and GenericVertexController..
« Reply #7 on: March 23, 2013, 11:23:57 pm »
Yes, that's correct. The reason is that the geometry will be batched/compiled based on texture states.

Ok, well then the second option is to include the texture and use UV coords. I made a new texture containing a light texture 256x512 and a dark texture 256x512 horizontal left and right.
( i first did it 512x512 and 512x512, the total texture size is 1024x512 and it loaded well :P)

When i want to map the first texture i just do x 0.0 to 0.4999, but i can't seem to get the second one from 0.5 to 1.0. When i try that i just get the whole texture. I tried a lot of things..

UPDATE:

I found reTexture() code on the forum that works well. It takes a variable tileFactor, when i put that to -0.5 it maps the left upper part of the texture and when i put that to 0.5 it maps the low right part. So i created my texture accordingly. This seems to work for me, i know it's a bit unnecessary memory consumption  not using the upper right and lower left part of the texture pixels.

I've been busy trying to change the UV coords realtime but i can't seem to get it working like it should.

Stange thing is, i have modified the function reTexture to adjust the UV's how i want them. When Objects are not compiled it works great (i can map -0.5 up left OR 0.5 low right of the texture) but when compiled it works but gives strange results (maps the whole texture no up left or down right).  I must do something wrong.

I also have discovered using octree for my heightmap (for toutch events) works but gives  nullpointers using calcMinDistance sometimes.

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: Terrain and GenericVertexController..
« Reply #8 on: March 23, 2013, 11:45:39 pm »
Stange thing is, i have modified the function reTexture to adjust the UV's how i want them. When Objects are not compiled it works great (i can map -0.5 up left OR 0.5 low right of the texture) but when compiled it works but gives strange results (maps the whole texture no up left or down right).  I must do something wrong.
Make sure to use the proper compile()-call. If you want to change texture coordinates at runtime, you have to use compile(true, false); You might have to call Object3D.touch() after adjusting uv-mapping as well.

I also have discovered using octree for my heightmap (for toutch events) works but gives  nullpointers using calcMinDistance sometimes.
Make sure that you aren't accessing any jPCT related objects in the method that handles the touch events. Set a flag instead and evaluate it in onDrawFrame(). jPCT (and jPCT-AE) aren't thread safe. If the problem persist, please post the exception.

Offline LowPolyMan

  • byte
  • *
  • Posts: 25
    • View Profile
Re: Terrain and GenericVertexController..
« Reply #9 on: March 24, 2013, 02:01:56 pm »
Stange thing is, i have modified the function reTexture to adjust the UV's how i want them. When Objects are not compiled it works great (i can map -0.5 up left OR 0.5 low right of the texture) but when compiled it works but gives strange results (maps the whole texture no up left or down right).  I must do something wrong.
Make sure to use the proper compile()-call. If you want to change texture coordinates at runtime, you have to use compile(true, false); You might have to call Object3D.touch() after adjusting uv-mapping as well.

I also have discovered using octree for my heightmap (for toutch events) works but gives  nullpointers using calcMinDistance sometimes.
Make sure that you aren't accessing any jPCT related objects in the method that handles the touch events. Set a flag instead and evaluate it in onDrawFrame(). jPCT (and jPCT-AE) aren't thread safe. If the problem persist, please post the exception.

Why don't those idiots read the documents first, i hear you think..  :)

Build also has this boolean i seen, or is staticUV default to false with build?

Anyway, tried it all and doesn't help anything. I can't seem to get it working and i know i'm doing something wrong because the second texture is mapped upside down when object is NOT compiled, but doesn't get mapped at all when it is compiled (i still get the whole texture). I made a a screenshot. I also have some example source if you like.

And i leave octree for now, using default object CollisionMode works fine and the app loads much faster also.

(Ohh, the glitch in the screenshot is my mistake, not JPCT ;)



[attachment deleted by admin]

Offline LowPolyMan

  • byte
  • *
  • Posts: 25
    • View Profile
Re: Terrain and GenericVertexController..
« Reply #10 on: March 27, 2013, 07:33:30 pm »
Can anyone provide a working example of how to change the UV's at runtime?

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: Terrain and GenericVertexController..
« Reply #11 on: March 27, 2013, 08:27:06 pm »
What is this? Desktop jPCT? Because in jPCT-AE, there is no "before compile". If something gets rendered, it will be compiled. You can't do anything against it, which is why i don't understand your screen shots...
« Last Edit: March 27, 2013, 08:29:08 pm by EgonOlsen »

Offline LowPolyMan

  • byte
  • *
  • Posts: 25
    • View Profile
Re: Terrain and GenericVertexController..
« Reply #12 on: March 28, 2013, 12:18:26 am »
What is this? Desktop jPCT? Because in jPCT-AE, there is no "before compile". If something gets rendered, it will be compiled. You can't do anything against it, which is why i don't understand your screen shots...

jPCT-AE, and by before compile i mean not at runtime, sorry was a bit unclear.

Example src:
Code: [Select]
package com.threed.jpct.example;

import java.lang.reflect.Field;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.opengles.GL10;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.ViewGroup.LayoutParams;
import com.threed.jpct.Camera;
import com.threed.jpct.Config;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Interact2D;
import com.threed.jpct.Light;
import com.threed.jpct.Logger;
import com.threed.jpct.Object3D;
import com.threed.jpct.OcTree;
import com.threed.jpct.PolygonManager;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureInfo;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.BitmapHelper;
import com.threed.jpct.util.MemoryHelper;

@SuppressLint("NewApi")
public class HelloWorld extends Activity {

private static HelloWorld master = null;
private GLSurfaceView mGLView;
private MyRenderer renderer = null;
private FrameBuffer fb = null;
private World world = null;
private Camera camera = null;
private RGBColor back = new RGBColor(50, 50, 100);
private float touchTurn = 0;
private float touchTurnUp = 0;
private float xpos = -1;
private float ypos = -1;
private Object3D terrain;
private int fps = 0;
private Light sun = null;
String status = "Loading..";
boolean status_midx=true;
boolean status_midy=true;
int polyIdOffset;
    private String outputLine1 = "";
    private String outputLine2 = "";
    private String outputLine3 = "";

protected void onCreate(Bundle savedInstanceState) {
Logger.log("onCreate");
if (master != null) {
copy(master);
}
super.onCreate(savedInstanceState);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
mGLView = new GLSurfaceView(getApplication());
mGLView.setEGLConfigChooser(new GLSurfaceView.EGLConfigChooser() {
@SuppressLint("NewApi")
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
int[] attributes = new int[] { EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_NONE };
EGLConfig[] configs = new EGLConfig[1];
int[] result = new int[1];
egl.eglChooseConfig(display, attributes, configs, 1, result);
return configs[0];
}
});
requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
renderer = new MyRenderer();
mGLView.setRenderer(renderer);
setContentView(mGLView);
        DrawOnTop mDraw = new DrawOnTop(this);
        addContentView(mDraw, new LayoutParams (LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}

@Override
protected void onPause() {
super.onPause();
mGLView.onPause();
}

@Override
protected void onResume() {
super.onResume();
mGLView.onResume();
}

@Override
protected void onStop() {
super.onStop();
}

private void copy(Object src) {
try {
Logger.log("Copying data from master Activity!");
Field[] fs = src.getClass().getDeclaredFields();
for (Field f : fs) {
f.setAccessible(true);
f.set(this, f.get(src));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public boolean onTouchEvent(MotionEvent me) {
float x,y;
if (me.getAction() == MotionEvent.ACTION_DOWN) {
x = me.getX();
y = me.getY();
SimpleVector position = new SimpleVector(Interact2D.reproject2D3D(camera, fb, (int)x, (int)y));
position.matMul(camera.getBack().invert3x3());
position.add(camera.getPosition());
SimpleVector direction = position.calcSub(camera.getPosition()).normalize();
float distance = world.calcMinDistance(position, direction, 10000);
if (distance != Object3D.COLLISION_NONE) {
SimpleVector collisionPoint = new SimpleVector(direction);
collisionPoint.scalarMul(distance);
collisionPoint.add(position);
int mapGridX = (int) collisionPoint.x / 5;
int mapGridY = (int) collisionPoint.z / 5;
int polyId1 = ((32 * mapGridY + mapGridX) * 2) + polyIdOffset;
terrain.getPolygonManager().setPolygonTexture(polyId1,
TextureManager.getInstance().getTextureID("Red"));
terrain.getPolygonManager().setPolygonTexture(polyId1 + 1,
TextureManager.getInstance().getTextureID("Red"));
outputLine1 = "Collision: " + collisionPoint;
outputLine2 = "    2D Map Coordinates: ( " + collisionPoint.x
+ ", " + collisionPoint.z + " )";
outputLine3 = "    Map Cell: ( " + mapGridX + ", " + mapGridY
+ " )";
}
//renderer.reTexture(terrain, "texture", -0.5f);
//terrain.touch();
renderer.reTexture(terrain, "", -0.5f);
//terrain.touch();
return true;
}

if (me.getAction() == MotionEvent.ACTION_UP) {
xpos = -1;
ypos = -1;
touchTurn = 0;
touchTurnUp = 0;
return true;
}

if (me.getAction() == MotionEvent.ACTION_MOVE) {
float xd = me.getX() - xpos;
float yd = me.getY() - ypos;
xpos = me.getX();
ypos = me.getY();
touchTurn = xd / -100f;
touchTurnUp = yd / -100f;
return true;
}

try {
Thread.sleep(15);
} catch (Exception e) {
}

return super.onTouchEvent(me);
}

protected boolean isFullscreenOpaque() {
return true;
}

class MyRenderer implements GLSurfaceView.Renderer {

private long time = System.currentTimeMillis();

public MyRenderer() {
Config.glTransparencyMul = (1.0f / 255);
        Config.glTransparencyOffset = (1.0f / 255);
        Config.farPlane = 10000;
        Config.maxPolysVisible = 10000;
}

public void onSurfaceChanged(GL10 gl, int w, int h) {
if (fb != null) {
fb.dispose();
}
fb = new FrameBuffer(gl, w, h);
if (master == null) {
world = new World();
world.setAmbientLight(50, 50, 50);
sun = new Light(world);
sun.setIntensity(20, 20, 20);
SimpleVector sv = new SimpleVector(80, -160, 80);
sun.setPosition(sv);
status = "Loading textures..";
Texture Grey = new Texture(BitmapHelper.rescale(BitmapHelper.convert(getResources().getDrawable(R.drawable.grey)), 256, 256));
TextureManager.getInstance().addTexture("Grey", Grey);
Texture Red = new Texture(BitmapHelper.rescale(BitmapHelper.convert(getResources().getDrawable(R.drawable.red)), 256, 256));
TextureManager.getInstance().addTexture("Red", Red);
Texture texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(getResources().getDrawable(R.drawable.texture)), 1024, 512));
TextureManager.getInstance().addTexture("texture", texture);
status = "Creating object..";
        createTerrain();
        world.addObject( terrain );
        terrain.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS );
        world.buildAllObjects();
        status = "Add camera and compact memory..";
        camera = world.getCamera();
        camera.setPosition( -80, -160, -80 );
        camera.lookAt( new SimpleVector( 80, 0, 80 ) );
MemoryHelper.compact();
status = "";
if (master == null) {
Logger.log("Saving master Activity!");
master = HelloWorld.this;
}
}
}

public void reTexture(Object3D obj, String t2, float tileFactor) {
PolygonManager pm=obj.getPolygonManager();
int t2Id=TextureManager.getInstance().getTextureID(t2);
int end=pm.getMaxPolygonID();
for (int i=0; i<end; i++) {
int t1=pm.getPolygonTexture(i);
SimpleVector uv0=pm.getTextureUV(i, 0);
SimpleVector uv1=pm.getTextureUV(i, 1);
SimpleVector uv2=pm.getTextureUV(i, 2);
TextureInfo ti=new TextureInfo(t1, uv0.x, uv0.y, uv1.x, uv1.y, uv2.x, uv2.y);
uv0.scalarMul(tileFactor);
uv1.scalarMul(tileFactor);
uv2.scalarMul(tileFactor);
ti.add(t2Id, uv0.x, uv0.y, uv1.x, uv1.y, uv2.x, uv2.y, TextureInfo.MODE_REPLACE);
pm.setPolygonTexture(i, ti);
}
}

    public void createTerrain()
    {
        int x, z, id = TextureManager.getInstance().getTextureID("texture");
        float xSizeF = 33, zSizeF = 33, scalemap = 5, deelx=1;
        TextureInfo ti;
        terrain = new Object3D( 2048 ); 
        for( z = 0; z < 32; z++ )
        {
            for( x = 0; x < 32; x++ )
            {
float xx = x;
ti = new TextureInfo(id, (xx / xSizeF/deelx), (z / zSizeF), ((xx + 1) / xSizeF/deelx), (z / zSizeF), (xx / xSizeF/deelx), ((z + 1) / zSizeF));
terrain.addTriangle(new SimpleVector(x * scalemap, 1, z * scalemap),           
new SimpleVector((x + 1) * scalemap, 1, z * scalemap),
new SimpleVector(x * scalemap, 1, (z + 1) * scalemap), ti);
ti = new TextureInfo(id, (xx / xSizeF/deelx), ((z + 1) / zSizeF), ((xx + 1) / xSizeF/deelx), (z / zSizeF), ((xx + 1) / xSizeF/deelx), ((z + 1) / zSizeF));
terrain.addTriangle(new SimpleVector(x * scalemap, 1, (z + 1) * scalemap),
new SimpleVector((x + 1) * scalemap, 1, z * scalemap),
new SimpleVector((x + 1) * scalemap, 1, (z + 1) * scalemap), ti);
            }
        }
       
        //Retexture RIGHT lower part
        reTexture(terrain, "texture", 0.5f);
       
        //Retexture ONLT left upper part ..
        //reTexture(terrain, "texture", -0.5f);  //Uncomment here..
       
        terrain.calcNormals();
        terrain.setSpecularLighting(true);
       
        terrain.forceGeometryIndices(true);
       
        terrain.build(); //(true);
        OcTree ocTree = new OcTree( terrain.getMesh(), 2048, OcTree.MODE_OPTIMIZED );
        ocTree.setCollisionUse( OcTree.COLLISION_USE );
        terrain.setOcTree( ocTree );
        polyIdOffset = terrain.getPolygonManager().getMaxPolygonID() - terrain.getMesh().getTriangleCount();
        terrain.compile(true, false);
    }

public void onSurfaceCreated(GL10 gl, EGLConfig config) {
status_midx=true;
status_midy=true;
status = "";
}

public void onDrawFrame(GL10 gl) {
if (touchTurn != 0) {
touchTurn = 0;
}
if (touchTurnUp != 0) {
touchTurnUp = 0;
}
status = outputLine1 + ", " + outputLine2 + ", " + outputLine3;
fb.clear(back);
world.renderScene(fb);
world.draw(fb);
fb.display();
if (System.currentTimeMillis() - time >= 1000) {
Logger.log(fps + "fps");
fps = 0;
time = System.currentTimeMillis();
}
fps++;
}
}
class DrawOnTop extends View {
Paint paint = new Paint();
Rect bounds = new Rect();
int x;
int y;
int tmpx;
int tmpy;
public DrawOnTop(Context context) {
super(context);
}
public void drawing(Canvas canvas) {
if (status.length() > 0) {
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLACK);
paint.setTextSize(48);
paint.setAntiAlias(true);
paint.setAlpha(255);
if (status_midx)
{
tmpx = (int) paint.measureText(status);
x = canvas.getWidth()/2 - (tmpx/2);
}
else
{
x = (canvas.getWidth() / 40);
}
if (status_midy)
{
paint.getTextBounds(status, 0, status.length(), bounds);
tmpy = bounds.bottom;
y = canvas.getHeight()/2 - (tmpy/2);
}
else
{
y = 48;
}
canvas.drawText(status, x - 1, y - 1, paint);
canvas.drawText(status, x + 1, y - 1, paint);
canvas.drawText(status, x + 1, y + 1, paint);
canvas.drawText(status, x - 1, y + 1, paint);
paint.setColor(Color.WHITE);
canvas.drawText(status, x, y, paint);
}
}
@Override
protected void onDraw(Canvas canvas) {
drawing(canvas);
super.onDraw(canvas);
this.invalidate();
}
}   

}
 

Where it says 'Uncomment here' works fine and maps the texture right with 'reTexture', but when running and you use 'MotionEvent.ACTION_DOWN' i do the same action 'reTexture' but i suddenly get the whole texture mapped.

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: Terrain and GenericVertexController..
« Reply #13 on: March 28, 2013, 08:01:11 am »
I can't try the code ATM and i won't be able to until after easter, but there are at least two things to consider:

  • Don't do these operations directly on the event listener. While this might not be responsible for your problem, it's bad practice anyway. jPCT-AE isn't thread safe, so you aren't supposed to modify jPCT related stuff from anywhere outside the rendering thread (in this case the onDrawFrame() method) once the scene has been setup. Just set a flag in the listener method and evaluate that in onDrawFrame() instead.
  • Your logic implies that reTexture() always starts from scratch, but that's not the case. It works based on the current coordinates, i.e. if you apply a tileFactor of 0.5 earlier, you'll reTexture with uOrg/vOrg0.5*-0.5 instead of uOrg/vOrg*-0.5
   

Offline LowPolyMan

  • byte
  • *
  • Posts: 25
    • View Profile
Re: Terrain and GenericVertexController..
« Reply #14 on: March 28, 2013, 10:23:21 pm »
I can't try the code ATM and i won't be able to until after easter, but there are at least two things to consider:

  • Don't do these operations directly on the event listener. While this might not be responsible for your problem, it's bad practice anyway. jPCT-AE isn't thread safe, so you aren't supposed to modify jPCT related stuff from anywhere outside the rendering thread (in this case the onDrawFrame() method) once the scene has been setup. Just set a flag in the listener method and evaluate that in onDrawFrame() instead.
  • Your logic implies that reTexture() always starts from scratch, but that's not the case. It works based on the current coordinates, i.e. if you apply a tileFactor of 0.5 earlier, you'll reTexture with uOrg/vOrg0.5*-0.5 instead of uOrg/vOrg*-0.5

Thanks for 2 interesting points.. I will look into this. As soon as i have this working i will create a example for wiki so others can enjoy it too.. :)