changing texture for object parts when clicked

Started by Lavender, January 31, 2015, 12:55:00 PM

Previous topic - Next topic

Lavender

Hello,

I have a complex object comprised of multiple square faces, where each face consists of two triangles. When the user touches a face, I want it to change its texture. How can I identify which face has been touched, and how can I change the texture on that face?
Thanks in advance for any help.

EgonOlsen

That's not as easy as one might think, because an object's polygons are batched by texture and sent to the GPU. You can't change them afterwards without triggering a rebatching, which is pretty expensive. It might be feasible to put all the textures in one large texture and change the texture coordinates for certain polygons...but it might be easier to use one object per square face instead. About how many faces are we talking here?

Lavender

I will have 3 objects, 30 to 50 faces each. If there is a way to have one object per face, that would be very convenient. However, the object as a whole should be rotatable, that is if the users sweeps across the object, all faces should move like if they comprised a surface of a rigid body. Is it still possible to accomplish this?

EgonOlsen

Yes. You could place a dummy object at the rotation pivot and make all faces children of that dummy. Creating the single objects might be more difficult, at least if you are loading the object from a file. Are you?

Lavender

Actually, I don't have working code yet - as of now I'm designing the general structure. But I wasn't planning to load from file, instead I want to use getCube to build objects piece by piece (all faces should be square). I will try the trick of making face objects children of a pivot dummy. Thanks for your help.

Lavender

I managed to make a group of objects that move together. Now I need objects to change their texture when clicked. I ran into a problem where I can't create textures from filenames. Below is a minimal code example (edited from one of the samples on this site). The line  Texture texture = new Texture("filename.jpg");  gives compilation error "The constructor Texture(String) is undefined". However, there is such  a constructor according to this http://www.jpct.net/doc/com/threed/jpct/Texture.html#Texture(java.lang.String).
I'm trying to figure out what is going wrong, any help is appreciated. Thank you.
package com.example.mytest;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;

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.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.MotionEvent;

import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Light;
import com.threed.jpct.Logger;
import com.threed.jpct.Object3D;
import com.threed.jpct.PolygonManager;
import com.threed.jpct.Primitives;
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;
import com.threed.jpct.Interact2D;

public class MainActivity extends Activity {

// Used to handle pause and resume...
private static MainActivity master = null;

private GLSurfaceView mGLView;
private MyRenderer renderer = null;

private FrameBuffer fb = null;
private World world = null;
private RGBColor back = new RGBColor(50, 50, 100);
private Camera cam = null;
private float camRotateX = (float)Math.PI/8;
private Light sun = null;
protected void onCreate(Bundle savedInstanceState) {

Logger.log("onCreate");

if (master != null) {
copy(master);
}
super.onCreate(savedInstanceState);
mGLView = new GLSurfaceView(getApplication());

DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);

mGLView.setEGLConfigChooser(new GLSurfaceView.EGLConfigChooser() {
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];
}
});

renderer = new MyRenderer();
mGLView.setRenderer(renderer);
setContentView(mGLView);
}

@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);
}
}

protected boolean isFullscreenOpaque() {
return true;
}

class MyRenderer implements GLSurfaceView.Renderer {
public MyRenderer() {
}

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(20, 20, 20);

sun = new Light(world);
sun.setIntensity(250, 250, 250);
Texture texture = new Texture("filename.jpg");
TextureManager.getInstance().addTexture("myTexture", texture);
cam = world.getCamera();
cam.rotateCameraX(camRotateX);
cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
SimpleVector origin = new SimpleVector(0f, 0f, 0f);
cam.lookAt(origin);

SimpleVector sv = new SimpleVector();
sv.set(origin);
sv.y -= 100;
sv.z -= 100;
sun.setPosition(sv);

System.runFinalization();
System.gc();
MemoryHelper.compact();
}

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


public void onSurfaceCreated(GL10 gl, EGLConfig config) {
}

public void onDrawFrame(GL10 gl) {
fb.clear(back);
world.renderScene(fb);
world.draw(fb);
fb.display();
}
}
}

EgonOlsen

Those are the wrong docs. They are for desktop jPCT. The ones for jPCT-AE can be found here: http://www.jpct.net/jpct-ae/doc
jPCT-AE doesn't have this construtor, because Android doesn't allow you to access files this way. The best way is to put them into the assets directory of your project and access them via an InputStream. Please refer to the Android SDK documentation for more details.