Topic: Shaders and Mouse Clicking

Hello,

I have been messing around with Maratis for a while and I've seen different kinds of shaders. Now, the problem is, I have no idea how I can add these to my game. Also, I don't know where to get them.

Is there any possible way to find what object the mouse is clicking?

Many thanks,

Iguana

Re: Shaders and Mouse Clicking

same problem here.
i thought about rayHit(), but i'm not sure if it return name of hited object. and there will be some math to calculate hit vector, using mouse coordinates and camera orientation.
also i think about some ghost object as mouse pointer, but it will require the full list of objects in scene.

Last edited by Felis (2012-09-29 00:51:20)

Re: Shaders and Mouse Clicking

rayHit doesn't return the object but the intersection point,
to know if it hit an object, the object is passed in argument :

point = rayHit(start, end, object)
if point then
    -- there is a hit with object
end

Mikey shared a additional script function (written in c++) :
http://forum.maratis3d.com/viewtopic.php?id=434

Here is the function code :

int pickObject(void)
{
    MEngine * engine = MEngine::getInstance();
    MScriptContext * script = engine->getScriptContext();
    
    if (script->getArgsNumber() == 3)
    {
        MOCamera * camera = (MOCamera *)script->getPointer(0);
        float x = script->getFloat(1);
        float y = script->getFloat(2);

        MPhysicsContext * physics = engine->getPhysicsContext();
        
        unsigned int width, height;
        engine->getSystemContext()->getScreenSize(&width, &height);

        MVector3 rayO = camera->getTransformedPosition();
        MVector3 rayD = camera->getUnProjectedPoint(MVector3(x * float(width), (1 - y) * float(height), 1));
        rayD = rayO + ((rayD - rayO).getNormalized() * (camera->getClippingFar() - camera->getClippingNear()));

        unsigned int objId;
        if (physics->isRayHit(rayO, rayD, &objId))
        {
            MLevel * level = engine->getLevel();
            MScene * scene = level->getCurrentScene();
            unsigned int entCount = scene->getEntitiesNumber();
            for (unsigned int i = 0; i < entCount; ++i)
            {
                MOEntity * entity = scene->getEntityByIndex(i);
                MPhysicsProperties * phyProps = entity->getPhysicsProperties();
                if (phyProps)
                {
                    if (phyProps->getCollisionObjectId() == objId)
                    {
                        script->pushPointer(entity);
                        return 1;
                    }
                }
            }
        }
    }
    
    return 0;
}

Used like that in lua :

obj = pickObject(Camera, x, y)
if obj then
...
end

This is the way to add the function through a game plugin (to do in StartPlugin) :

MEngine* engine = MEngine::getInstance();
MScriptContext* script = engine->getScriptContext();
if(script)
    script->addFunction("pickObject", pickObject);

Re: Shaders and Mouse Clicking

unfortunately i'm not C++ programmer and can make only simple scripts in Lua.
hope to see this function implemented in engine soon.

Re: Shaders and Mouse Clicking

yes, we'll add it by default for next version.

If you want doing something with lua only, if your game is 2d you could use a ghost box and detect it's collision with objects.

For 3d it's a bit more complex, it's possible to use rayHit :
- link an object to the camera, it will act as a cursor (it will stick to the cam)
- move the cursor using the mouse position multiplied by a ratio
- you can find the ray using the cursor position and the camera position :
   beginRay = cameraPosition
   endRay = cameraPosition + (cursorPosition - cameraPosition)*factor

Re: Shaders and Mouse Clicking

i think we can use rayHit() for detecting object's position by directing it to the camera and mouse vector, then put our "cursor" object there and check the object by isCollisionBetween().
of-course we will have to check all the "trigger" object, to find if we hit one of them.

Re: Shaders and Mouse Clicking

trying to test in Jules example project. i've set camera to follow Jules closely. the problem is i cannot detect readable camera rotation.
what axises does getRotation() function returns?
my small code:
           camRot = getRotation(camera)
           camRotX = camRot[1]
           camRotY = camRot[2]
           camRotZ = camRot[3]
           print("camera rotation:", camRotX, camRotY, camRotZ)
it returns this:
camera rotation:    63.430767059326    -8.5377365621753e-07    19.999326705933
camera rotation:    63.430732727051    -8.5377359937411e-06    104.99935150146
camera rotation:    63.430698394775    1.7075473124351e-06    -150.00065612793
camera rotation:    63.430725097656    5.122642050992e-06    -35.000694274902

so i think results are:
camRotX is rotation of camera upward from the direct down (0) to up (180)
camRotY is camera tilt
camRotZ is camera rotation left/right

now to trigonometry...

Re: Shaders and Mouse Clicking

ok. here what i managed to make:

box = getObject("Entity6")
camera = getObject("Camera0")
RAYDIST = 500 -- distance to click the objects in game units
fov = getCameraFov(camera)
    
-- scene update
function onSceneUpdate()
    
    -- mouse click objects
    if onKeyDown("MOUSE_BUTTON1") then
        startPT = getPosition(camera) -- take camera position as start point
        -- now calculate end point by converting 3D vector to coordinates
                   camRot = getRotation(camera)
            camRotX = 180-camRot[1] -- corrected camera rotation from down to up (0-180 deg)
            camRotZ = 90+camRot[3] -- camera rotation left/right
           
            -- calculate angle of mouse cursor relative to camera
            mx = getAxis("MOUSE_X") - 0.5
            my = getAxis("MOUSE_Y") - 0.5
           
             mRotX = math.deg(math.asin(my / fov)) * fov
            mRotY = -math.deg(math.asin(mx / fov)) * fov * 1.75
           
            endPointX = RAYDIST * math.sin(math.rad(camRotX + mRotX)) * math.cos(math.rad(camRotZ + mRotY)) + startPT[1]
            endPointY = RAYDIST * math.sin(math.rad(camRotX + mRotX)) * math.sin(math.rad(camRotZ + mRotY)) + startPT[2]
            endPointZ = RAYDIST * math.cos(math.rad(camRotX + mRotX)) + startPT[3]
           
            endPT = {endPointX, endPointY, endPointZ}
            
            point = rayHit(startPT, endPT) -- trace to any object in given direction
            if point then
                setScale(box, {0.2, 0.2, 0.2})
                setPosition(box, {point[1], point[2], point[3]}) -- send scaled box there
            end

     end

end

but i have problem with mRotX and mRotY variables. it looks like camera have some lens distortion.

anyway, wait for that function. it will make this much easier smile