I have 9 objects on screen(3D being used).How would I go about picking one with the mouse.I am assuming I could use the raytrace command.
Correct.
Use the X_SCREEN2WORLD to transform your mousepointer to 3D coordinates. Then use X_COLLISIONRAY to test, if you hit it.
Can't get it.Any chance of an example? :)
// --------------------------------- //
// Project:
// Start: Saturday, July 20, 2002
// First we need an object. Here: a simple paper plane
// We assume Z is down, as most 3d programs will export
// The converter should be able to convert this one day...
// Also we assume the x axis (positive) is the direction
// the plane will fly forwards, so in a right hand system
// y will be left side of plane.
// Triangle Strips will be drawn:
//
// 1---2---5
// \ / \ /|
// 3---4 |
// \|
// 6
LOADSPRITE "News.bmp", 0
col = RGB(0xff, 0xff, 0xff)
X_OBJSTART 0 // PlaneID = 0
// Right wing: side updown
X_OBJADDVERTEX -7, 5, 0, 1.0, 1.0, col // Outer point
X_OBJADDVERTEX -7, 1, 0, 1.0, 0.5, col // Inner edge
X_OBJADDVERTEX 7, 0, 0, 0.0, 1.0, col // Top
// Right body:
X_OBJADDVERTEX -7, 0, 3, 0.0, 1.0, col
X_OBJNEWGROUP
// Left wing:
X_OBJADDVERTEX -7, -5, 0, 0.0, 0.0, col
X_OBJADDVERTEX -7, -1, 0, 0.0, 0.5, col
X_OBJADDVERTEX 7, 0, 0, 1.0, 0.0, col
// Left body:
X_OBJADDVERTEX -7, 0, 3, 0.0, 1.0, col
X_OBJEND
X_SAVEOBJ "plane.ddd", 0
X_LOADOBJ "plane.ddd", 0
LIMITFPS -1
WHILE TRUE
MOUSESTATE mx, my, mb1, mb2
DRAWRECT mx-8,my-8,16,16, RGB(255,0,0)
X_MAKE3D 1, 1000, 45 // Turn to 3D Viewport
X_CAMERA 200*SIN(mx*360/640), my*2-100, 200*COS(mx), 0,0,0 // Rotate CAMERA with mouse
dtime = GETTIMER()
psi=psi+(dtime/64); IF psi>=360 THEN psi=0
FOR phi = 0 TO 360 STEP 30
X_DRAWAXES 0,0,0 // Draw global axes (red=x, green=y, blue=z)
alpha = (phi+psi)*4
LOCAL px=200*SIN(phi+psi),py=SIN(alpha)*20,pz=100*COS(phi+psi)
X_MOVEMENT px,py,pz
X_SCALING 2,2,2
X_ROTATION 90,1,0,0 // Make plane body point down global y
X_ROTATION 45*COS(alpha),0,0,1 // make plane look up/down with mouse
X_ROTATION phi+psi, 0,1,0 // Rtoation due to position in circle
X_SETTEXTURE 0, -1
X_DRAWOBJ 0, 0 // Draw Object#0. Frame# is always 0 with user def. objects
// PICKING PART!
LOCAL x,y,z, x2,y2,z2
X_SCREEN2WORLD mx, my, 0, x, y, z
X_SCREEN2WORLD mx, my, -1, x2,y2,z2
IF X_COLLISIONRAY(0,0, x,y,z, x2-x, y2-y, z2-z)<>0
X_PRINT "PICK", px,py,pz, 0
ENDIF
NEXT
fps = ((1000/dtime)+fps)/2
delay=delay+dtime
IF delay>1000 // 1/2 sec
delay=0
showfps=fps
ENDIF
X_MAKE2D
PRINT "FPS: " +INTEGER(showfps), 100, 100 // + dtime, 0,0
SHOWSCREEN
WEND
Move the mouse over a paper plane.
Thanks for that Gernot.I can get it to work in my programme no problem.Can I get the pick command to return the actual world co-ordinates(x,y,z)of the object picked?
uhm... you need the x,y,z position of the object for the x_collisionray test. Thus, uhm... you know them.
How come the following code is only picking one cube
// --------------------------------- //
// Project: 3d test
// Start: Thursday, November 08, 2007
// IDE Version: 5.069
X_LOADOBJ "cube.ddd",1
LOADSPRITE "rub_cube.bmp",1
LOADSPRITE "back.bmp",2
LOADSPRITE "reflect.bmp",3
LOADSPRITE "../../pointers.png",4
leng=50
x=0
y=0
WHILE TRUE
ALPHAMODE -.999
STRETCHSPRITE 2,0,0,640,480
MOUSESTATE mxx,myy,b1,b2
IF b2
mx=mx+MOUSEAXIS(0)
my=my+MOUSEAXIS(1)
ENDIF
X_MAKE3D 1,1000,45
camx=(400*COS(mx))*COS(my)
camy=(400*SIN(mx))*COS(my)
camz=400*SIN(my)
camx1=(300*COS(mx))*COS(my)
camy1=(300*SIN(mx))*COS(my)
camz1=300*SIN(my)
X_CAMERA camx,camz,camy,0,0,0
INC phi,2
INC pi,1
FOR z=0 TO 2
FOR y=0 TO 2
FOR x=0 TO 2
X_MOVEMENT (x*48)-50,(y*48)-50,(z*48)-50
X_SETTEXTURE 1,-1
X_DRAWOBJ 1,0
LOCAL wx,wy,wz, wx2,wy2,wz2
X_SCREEN2WORLD mxx, myy,0, wx, wy, wz
X_SCREEN2WORLD mxx, myy, -1, wx2,wy2,wz2
IF X_COLLISIONRAY(1,0,wx,wy,wz,wx2-wx,wy2-wy,wz2-wz)<>0
picked=1
ELSE
picked=0
ENDIF
NEXT
NEXT
NEXT
X_MAKE2D
DRAWSPRITE 4,mxx,myy
IF picked=1
PRINT "object picked",10,0
ELSE
PRINT "No object picked",10,0
ENDIF
SHOWSCREEN
WEND
I know it's probably something I am doing wrong.
Full programme and media available here
//www.rrae.pwp.blueyonder.co.uk/my%20prog.zip
Hehehe!
Du setzt "picked=0" wenn Du nicht in einem Block bist und überschreibst damit picked=1 von vorherigen Block.
Nimm's vor die Schleife:
picked=0
FOR z=0 TO 2
FOR y=0 TO 2
FOR x=0 TO 2
LOCAL obx=(x*48)-50, oby=(y*48)-50, obz=(z*48)-50
X_MOVEMENT obx, oby, obz
X_SETTEXTURE 1,-1
X_DRAWOBJ 1,0
LOCAL wx,wy,wz, wx2,wy2,wz2
X_SCREEN2WORLD mxx, myy, 0, wx, wy, wz
X_SCREEN2WORLD mxx, myy, -1, wx2,wy2,wz2
IF X_COLLISIONRAY(1,0,wx,wy,wz, (wx2-wx)*1000,(wy2-wy)*1000,(wz2-wz)*1000)<>0
picked=1
ENDIF
NEXT
NEXT
NEXT
Don't understand German !Sorry
Tried the new code and it works fine:)Another question ,If three cubes are in a line one behind the other,all three show as being hit(modified code slightly to use x_print).How can I find which one is the closest to the camera?Thank you for all your help,it is really appreciated.
Oh! Silly me.
Well, if the X_COLLISIONRAY returns <>0, then the object you're just drawing (or would draw at current X_MOVEMENT) is under the mouse.
Sorry for being thick,but what if the one furthest away is drawn first.Won't it be the one under the mouse?I am looking for the one that is closest to the camera.
then also store the distance from camera to the object, and change the picked index, when you're closer. The distance is the retun value from X_COLLISIONRAY
What would be the best way to calculate the point where the ray first hits an object?