Project texture down on ground and objects

Started by cintix, November 18, 2011, 09:26:59 AM

Previous topic - Next topic

EgonOlsen

The Projector is actually a Camera, so the fov is limited by that (stupid...) min/max-Fov setting. Maybe that's one part of the problem?
About losing the base texture...is there any chance that you've called compile() on these objects before setting the new texture? If so, try to move it to a later position.

cintix

I tried adjusting the min/max Fov setting and as said the image looks better in size but still expands 4 corners to the side..
What it looks like

What the textures should look like


What i'm doing now..

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package markedworld;

import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.IRenderer;
import com.threed.jpct.Interact2D;
import com.threed.jpct.Loader;
import com.threed.jpct.Object3D;
import com.threed.jpct.PolygonManager;
import com.threed.jpct.Projector;
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.KeyMapper;
import com.threed.jpct.util.KeyState;
import com.threed.jpct.util.Light;
import com.threed.jpct.util.ShadowHelper;
import java.awt.Color;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
*
* @author migo
*/
class MarkedWorld {

    private World world;
    private FrameBuffer buffer;
    private Object3D ground, object;
    private Camera cam;
    private ShadowHelper sh;
    private Projector projector, markerProjector;
    private MouseMapper mouseMapper;
    private KeyMapper keyMapper;
    private Light sun;
    private boolean doLoop = true;
    private TextureManager tm = TextureManager.getInstance();
    private List<Object3D> model3DManager = new LinkedList<Object3D>();

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

    public MarkedWorld() throws Exception {
        world = new World();
        world.setAmbientLight(50, 50, 50);

        Light light = new Light(world);
        light.setIntensity(255, 255, 255);
        light.setPosition(new SimpleVector(0, 0, -10));



        world.getCamera().setPosition(0, 0, -150);
    }

    private void loop() throws Exception {
        // default world
        world = new World();
        world.setAmbientLight(130, 130, 130);


        // new buffer
        buffer = new FrameBuffer(800, 600, FrameBuffer.SAMPLINGMODE_GL_AA_4X);
        buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
        buffer.enableRenderer(IRenderer.RENDERER_OPENGL, IRenderer.RENDERER_OPENGL);
        projector = new Projector();
        projector.rotateX((float) Math.PI / 2f);
        projector.setFOVLimits(0, 2);
        projector.setFOV(2);

        markerProjector = new Projector();
        markerProjector.rotateX((float) Math.PI / 2f);
        markerProjector.setFOVLimits(0.2f, 0.5f);
        markerProjector.setFOV(0.4f);

        sh = new ShadowHelper(world, buffer, projector, 2048);
        sh.setCullingMode(false);
        sh.setAmbientLight(new Color(130, 130, 130));
        sh.setLightMode(true);
        sh.setBorder(1);

        // Initialize mappers

        mouseMapper = new MouseMapper(buffer);
        mouseMapper.hide();
        keyMapper = new KeyMapper();

        // Setup dynamic light source

        sun = new Light(world);
        sun.setIntensity(250, 250, 250);
        sun.setAttenuation(800);

        cam = world.getCamera();
        cam.moveCamera(Camera.CAMERA_MOVEOUT, 160);
        cam.moveCamera(Camera.CAMERA_MOVEUP, 120);
        cam.setFOV(1.5f);

        addTextures("textures/");
        ground = load3DS("ground.3ds", "models/ground.3ds");
        object = load3DS("object.3ds", "models/object.3ds");

        object.build();
        ground.build();

        model3DManager.add(object);
        model3DManager.add(ground);
       
        Texture cursor = tm.getTexture("cursor.png");

        // setMarker("groundmarker.png");

        for (Object3D md : model3DManager) {
            md.setRotationPivot(new SimpleVector(0, 0, 0));
        }

        ground.setTexture("Grass.JPG");

        world.addObject(ground);
        world.addObject(object);
       

        while (doLoop) {

            poll();
            if (ground != null) {
                projector.lookAt(ground.getTransformedCenter());
                markerProjector.lookAt(getAbsoluteCoordinate(world, world.getCamera(), buffer, mouseMapper.getMouseX(), mouseMapper.getMouseY()));
            }
            projector.moveCamera(ground.getTransformedCenter(), 215);
            sun.setPosition(projector.getPosition());
            sh.updateShadowMap();

            buffer.clear(java.awt.Color.BLACK);
            world.renderScene(buffer);
            world.draw(buffer);
            buffer.blit(cursor, 0, 0, mouseMapper.getMouseX(), mouseMapper.getMouseY(), cursor.getWidth(), cursor.getHeight(), true);
            buffer.update();
            buffer.displayGLOnly();
        }
        buffer.disableRenderer(IRenderer.RENDERER_OPENGL);
        buffer.dispose();
        System.exit(0);
    }

    /**
     * get 3d coordinate of srcPoint on object's surface from 2d coordinates.
     *
     * @param camera scene camera
     * @param buffer
     * @param x      screen (mouse) X coordinate
     * @param y      screen (mouse) Y coordinate
     * @return
     */
    public static SimpleVector getAbsoluteCoordinate(World world, Camera camera, FrameBuffer buffer, int x, int y) {
        SimpleVector rezult = null;
        if (camera != null && buffer != null) {
            SimpleVector rayTemp = Interact2D.reproject2D3DWS(camera, buffer, x, y).normalize();
            float distance = world.calcMinDistance(camera.getPosition(), rayTemp, 10000);
            rezult = new SimpleVector(camera.getPosition());
            rayTemp.scalarMul(distance);
            rezult.add(rayTemp);
        }
        return rezult;
    }

    public void poll() {
        KeyState ks = null;
        while ((ks = keyMapper.poll()) != KeyState.NONE) {
            if (ks.getKeyCode() == KeyEvent.VK_ESCAPE) {
                doLoop = false;
            }
        }
    }

    /**
     *
     * @param path
     */
    public void addTextures(String path) {
        File dir = new File(path);
        for (File file : dir.listFiles()) {
            System.out.println("Loading Textures! " + file.getName());
            if (file.isFile() && (file.getName().toLowerCase().endsWith(".jpg") || file.getName().toLowerCase().endsWith(".gif"))) {
                tm.addTexture(file.getName(), new Texture(file.getAbsoluteFile().toString()));
            }
            if (file.isFile() && file.getName().toLowerCase().endsWith(".png")) {
                tm.addTexture(file.getName(), new Texture(file.getAbsoluteFile().toString(), true));
            }
        }
    }

    private Object3D load3DS(String name, String modelPath) {
        Object3D object3D;
        object3D = Object3D.mergeAll(Loader.load3DS(modelPath, 0.3f));
        object3D.translate(0, -70, 0);
        object3D.setCulling(false);
        object3D.rotateX(-(float) Math.PI / 2);
        object3D.setSpecularLighting(true);
        object3D.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
        object3D.setName(name);
        return object3D;
    }

    public void setMarker(String markerTextureName) {
        Enumeration e = tm.getNames();
        Map<Integer, TextureInfo> textureMap = new TreeMap<Integer, TextureInfo>();
        int maxID, textureIndex;
        PolygonManager manager;

        tm.getTexture(markerTextureName).setEnabled(true);
        tm.getTexture(markerTextureName).setProjector(markerProjector, true);

        while (e.hasMoreElements()) {
            String textureName = e.nextElement().toString();
            if (textureName.equals(markerTextureName)) {
                continue;
            }
            TextureInfo info = new TextureInfo(tm.getTextureID(textureName));
            info.add(tm.getTextureID(markerTextureName), TextureInfo.MODE_ADD);
            textureMap.put(tm.getTextureID(textureName), info);
        }



        for (Object3D md : model3DManager) {
            if (md != null) {
                manager = md.getPolygonManager();
                maxID = manager.getMaxPolygonID();
                for (int idx = 0; idx < maxID; idx++) {
                    textureIndex = manager.getPolygonTexture(idx);
                    manager.setPolygonTexture(idx, textureMap.get(textureIndex));
                }
            }
        }
    }
}



No dought this is my mistake somehow, but its just not obvious to me.
Faith is for the weak...

EgonOlsen

That's normal behaviour. You have to leave a one pixel border at the edges and all will be fine. Your textures are not gone, just the coordinates are. You have to read the set the u/v-mapping too. The PolygonManager supports reading them too by using getTextureUV(). They can be set when creating the TextureInfo. You don't have to do this for the projective texture, just for the base map.

cintix

It worked like a charm!
I would say I love you Egon, but I'm sure you would ban me for declaring you a big a love statement..  ;-)

One last thing..
To get a really nice marking on the ground, would the right way not be to center the markerProjector over where the user is pointing with the mouse ?? I cant getting it to look really great.

I use this for the mouse


    /**
     *
     * @param world
     * @param cam
     * @param buffer
     * @return
     */
    public SimpleVector get3DCoordinate(World world, Camera cam, FrameBuffer buffer) {
        SimpleVector rezult = null;
        if (cam != null && buffer != null) {
            SimpleVector rayTemp = Interact2D.reproject2D3DWS(cam, buffer, getMouseX(), getMouseY()).normalize();
            float distance = world.calcMinDistance(cam.getPosition(), rayTemp, 20000);
            rezult = new SimpleVector(cam.getPosition());
            rayTemp.scalarMul(distance);
            rezult.add(rayTemp);
        }
        return rezult;
    }


It seems to work great, I tried setting the projector to the location and then moving the camera up.. not really working like i thought it would :(
Faith is for the weak...

EgonOlsen

Not sure why your approach shouldn't work...seems fine to me at first glance assuming that the plane you want to mark is orthogonal to the camera's up movement. Maybe adding a call to camera.lookAt(...) with that particular point solves it?