3d Mouse Control

Blitz3D Forums/Blitz3D Beginners Area/3d Mouse Control

How can you move a cube around a 3d world by using the mouse? Anyone possibly have any code?

Look at code in the games section that came with blitz.
The tunnel run game uses mouse control.
Unless your talking about Diablo stile where you click on a point and the caracter moves to that point. I think you would use Camerapick() and picked x,y,z to give the object a destination turn the object to face the picked coordinates and moveentity 0,0,1.
I'm sure there are lots of other ways to do these.

You could use a Grid made of a Plane that you can move up and down with the mouse when you press eg. the shift key. Then, without pressing the shift key, you would use CameraPick to determine the 3D Position of the mousepointer on the grid plane. Of course the plane needs to be pickable.
(Kind of like in Maplet)

best way in my opinion is to create a manipulator object with arrows pointing in the X,Y and Z directions, if you click and hold the directional arrow, track mousemove to move the cube

try this- very rough but explains my idea

click and hold the color manipulator to move the cube

Graphics3D 640,480
	Global	midw = GraphicsWidth()/2
	Global  midh =GraphicsHeight()/2

Global cam = CreateCamera() : MoveEntity cam,0,5,-15
light = CreateLight()
Global plane = CreateCube() : ScaleEntity plane,64,.25,64 : EntityAlpha plane,.5
planetex = CreateTexture(256,256) : ScaleTexture planetex,.025,.025 : SetBuffer TextureBuffer(planetex)
	Color 255,255,0 : Rect 0,0,255,255,0
EntityTexture plane,planetex 

Global cube = CreateCube() : EntityColor cube,255,0,0
Global MX#
Global MY#
; manipulator

m = CreatePivot()
Global Xdir = CreateCone(5,1,m) : EntityColor xdir,255,0,0 : ScaleEntity Xdir,.25,1,.25
	RotateEntity xdir,0,0,90 : TranslateEntity xdir,-1.25,0,0
Global Ydir = CreateCone(5,1,m) : EntityColor ydir,0,255,0 : ScaleEntity ydir,.25,1,.25
	RotateEntity ydir,0,0,0 : TranslateEntity ydir,0,1.25,0
Global zdir = CreateCone(5,1,m) : EntityColor zdir,0,0,255 : ScaleEntity zdir,.25,1,.25
	RotateEntity zdir,90,0,0 : TranslateEntity zdir,0,0,1.25


EntityPickMode xdir,2 : EntityPickMode ydir,2 : EntityPickMode zdir,2

MoveEntity m,-2,5,-12




SetBuffer BackBuffer()

Repeat

If MouseDown(1) = 1 Then campick()

	RenderWorld 
		debug() 
	Flip
Until KeyHit(1) = 1
End

;==================================================================================
Function curvevalue#(newvalue#,oldvalue#,increments# )
	If increments>1 Then oldvalue#=oldvalue#-(oldvalue#-newvalue#)/increments
	If increments<=1 Then oldvalue=newvalue
	Return oldvalue#
End Function
;==================================================================================


Function campick()
	pictentity = 0
	mox = MouseX()
	moy = MouseY()
	foo = MouseYSpeed() : foo = MouseXSpeed() ; flush 
	CameraPick(cam,MouseX(),MouseY())
	pictentity = PickedEntity() 
	If Pictentity<>0
		;MY# = MouseYSpeed()/64
		;MY#=curvevalue#(MouseYSpeed(),MY#,128 )
		;MX#=curvevalue#(MouseXSpeed(),MX#,128 )
	
		pcx# = PickedX#()
		pcy# = PickedY#()
		pcz# = PickedZ#()
		If pictentity = xdir
			Repeat
				
				MY#=curvevalue#(MouseYSpeed(),MY#,3 )/16
				MX#=curvevalue#(MouseXSpeed(),MX#,3 )/16

				MoveEntity cube,mx#,0,0
				MoveMouse mox,moy
				RenderWorld : debug() : Flip
			Until MouseDown(1) = 0
		EndIf

		If pictentity = ydir
			Repeat
				
				MY#=curvevalue#(MouseYSpeed(),MY#,3 )/16
				MX#=curvevalue#(MouseXSpeed(),MX#,3 )/16

				MoveEntity cube,0,-MY#,0
				MoveMouse mox,moy
				RenderWorld : debug() : Flip

			Until MouseDown(1) = 0
		EndIf

		If pictentity = zdir
			Repeat
				
				MY#=curvevalue#(MouseYSpeed(),MY#,3 )/16
				MX#=curvevalue#(MouseXSpeed(),MX#,3 )/16

				MoveEntity cube,0,0,MY#
				MoveMouse mox,moy
				RenderWorld : debug() : Flip

			Until MouseDown(1) = 0
		EndIf
	
	EndIf
	

End Function

Function debug()
	cx# = EntityX(cube)
	cy# = EntityY(cube)
	cz# = EntityZ(cube)
	CameraProject(cam,cx#,cy#,cz#)
	dstring$ = "X: "+cx#+" Y: "+cy#+" Z: "+cz#
	p# = (Len(dstring$)*FontWidth())/2
	Text ProjectedX#()-p#,ProjectedY#(),dstring$
	

End Function




Here is a idea I have bin thinking of for a while.
;This code by Matt Anthony aka. Riverratt 
;Graphics3D 640,480
Graphics3D 800,600

AutoMidHandle True
SetBuffer FrontBuffer()
grid_tex=CreateTexture( 32,32,8 )
ScaleTexture grid_tex,10,10
SetBuffer TextureBuffer( grid_tex )
Color 0,0,64:Rect 0,0,32,32
Color 0,0,255:Rect 0,0,32,32,False
SetBuffer BackBuffer()

plane=CreateTerrain(128)
EntityTexture plane,grid_tex
PositionEntity plane,-64,0,0  

light1=CreateLight()
PositionEntity light1,-15,15,-15
light2=CreateLight(3)
LightConeAngles light2,5,30
LightColor light2,255,100,100
PositionEntity light2,100,15,100
 

p_pivot=CreatePivot()
player=CreateCube(p_pivot)
EntityColor player,200,0,0
ScaleEntity player,1,.5,1
p_cam=CreateCamera(p_pivot)
PositionEntity player,0,.55,0
PositionEntity p_pivot,0,0,4
PositionEntity p_cam,0,4,-10
gun=CreateCylinder(16,1,player)
RotateEntity gun,90,0,0
PositionEntity gun,0,0,1
ScaleEntity gun,.5,1,.5

Type buttons
	Field x
	Field y
	Field length
	Field height
	Field image
	Field mesage$
	
End Type

Global rotate.buttons = New buttons
;use this code To relocate the rotation graph down Or change rotatex\rotatey anywhere you want
rotate\x = GraphicsWidth()/2
rotate\y = GraphicsHeight()/2+(GraphicsHeight()/3)
;rotate\x = GraphicsWidth()/2
;rotate\y = GraphicsHeight()/2
rotate\length = 130
rotate\height = 130 
rotate\image = CreateImage(rotate\length,rotate\height)
rotate\mesage$ = "Ship Rotation"
SetBuffer ImageBuffer(rotate\image)
	Color 100,100,255
	Oval 0,0,rotate\length,rotate\height,0
	;message$
	Text 0,0,rotate\mesage$ 
	

Global player_point=CreateImage(20,20)
SetBuffer ImageBuffer(player_point)
	
	Color 0,0,250
	Line 10,1,1,20
	
	Color 0,0,250
	Line 10,1,20,20
	
    Color 200,0,0
	Line 1,19,20,19

;pointrotation data____________________________________________________________________________________
Dim point(359); dimention the array to accomidate the rotations.
For loop=0 To 359
    point(loop)=CopyImage(player_point)
	MidHandle point(loop)
	RotateImage point(loop),loop
	DebugLog loop
Next


Global angle#

;make the imiges to be used for the mouse ,mouseimage is the triangle but just a dot for collision
mouseimage=CreateImage(20,20)
mousepoint=CreateImage(2,2)
makemouse(mouseimage,mousepoint)


speed#=0
mode=1
m=1

SetBuffer BackBuffer()

While Not KeyHit(1)
PointEntity light2,plane

p_angle#=-angle#

If KeyHit(2) mode=mode+1
If mode=4 Then 
	mode=1
	anglereset#=angle#-359
	RotateEntity p_pivot,0,angle#+anglereset#,0 
EndIf 
If mode=1 Then
	PositionEntity p_cam,0,4,-10
 	RotateEntity p_pivot,0,p_angle#,0
EndIf 

If mode=2 Then 
	RotateEntity player,0,p_angle#,0
	;RotateEntity p_pivot,0,p_angle#,0
EndIf

If mode=3 Then 
	PositionEntity p_cam,0,2,-.5
    ;RotateEntity player,0,p_angle#,0
	RotateEntity p_pivot,0,p_angle#,0
EndIf 

If MouseZSpeed()<>0 Then 
	speed#=(MouseZ()+MouseZSpeed())*.1
EndIf 

MoveEntity p_pivot,0,0,speed#

UpdateWorld()
RenderWorld()

drawhud(mouseimage,mousepoint)
If ImagesOverlap(mousepoint,MouseX(),MouseY(),rotate\image,rotate\x,rotate\y) Then 
	update_mouse()
EndIf

If KeyHit(57)=True  m=m+1
If m=2 Then m=0
If m=1 Then 
 	Color 255,0,110
	Text 10,10,"angle"+angle
	Text 10,30 ,speed#
	Text 10,50,mode
	Color 200,200,100
	Text 10,70,"Place the mouse inside the rotation image to rotate cam and player."
	Text 10,90,"Hit 1 to change rotation modes. "+"Use the mousewheel to move."
	Text 10,110,"Hit space to clear these mesages and gain fps."
EndIf 
Flip
Wend
End

Function drawhud(mouseimage,mousepoint)
	DrawImage rotate\image,rotate\x,rotate\y
	DrawImage mouseimage,MouseX(),MouseY()
	DrawImage mousepoint,MouseX(),MouseY()
	DrawImage point(angle),rotate\x,rotate\y
End Function

Function makemouse(mouseimage,mousepoint)
	SetBuffer ImageBuffer(mouseimage)
	Color 100,60,250
	Line 0,0,20,10
	Line 0,0,10,20
	Line 20,10,10,20
	
	SetBuffer ImageBuffer(mousepoint)
	Color 0,255,0
	Plot 0,0
	HandleImage mouseimage,0,0
	HandleImage mousepoint,0,0
End Function

Function update_mouse()
;This code is Thanks to Ross C 
;If MouseDown(2) Then
	angle=ATan2(rotate\y-MouseY(),rotate\x-MouseX()  ) ; the angle between 
	angle=angle-90 ; subtract 90 from the angle to compinsate for the blitz co-ord system
	If angle>359 Then ; check angle is within 0-359 range
		angle=angle-359 ; if not, wrap it round
	ElseIf angle<0 Then
		angle=angle+359
	End If
;EndIf

End Function





very cool RiverRatt.

Very efficient control system RiverRatt. Very nice.

Thank you. Glad you like it. I plan on doing more with it.
The end goal is to get it to control like a stearing wheel.
But it has other possible uses. For instance try comenting out the "If ImagesOverlap(mousepoint,MouseX(),MouseY(),rotate\image,rotate\x,rotate\y) Then" statement and move the rotation graph to the center of the screen. If the camera was set at an orthographic position you have diablo style control. Also the graph does not even have to be drawn for it to work.

I figured it out, though with picking the plane i have to subtract/add the picked x/y positiong to put an entity at that location. However heres my code. This places a cone, sphere or cube on a 3d grid, mouse to wander, hit the up/down arrow keys to move to a diff level, and left clicking the mouse drops the object. I was kind of thinking of a making a "super maplet" level editor thingy, shrug if I will.

Hey quit holding out. Lets see it.

I don't know about a "super maplet" but I have bin thinking of making a Maplet clone for a few months now. I need to study up on how to make custom meshes. I have figured out how to directly move an object on a 3d grid. Next step I think is to make a square surface by storing the marker position when the mouse is hit and scale the surface to where the mouse is released. Anyone want to help? This could be a cool comunity project and we might end up with a great tool, like Maplet but improved texture, movement and more when we get that much done.

; ModifyTerrain Example
; ---------------------

Graphics3D 800,600,16,3
MoveMouse 400,300
;HidePointer()
SetBuffer BackBuffer()
terra_size=128 ; initial size of terrain, and no. of grids segments, along each  side
x_scale=10 ; x scale of terrain
y_scale=10 ; y scale of terrain
z_scale=10 ; z scale of terrain
marker_x=terra_size/2 ; initial x position of marker
marker_z=terra_size/2 ; initial z position of marker
marker_y=0


camera=CreateCamera()
PositionEntity camera,(terra_size*x_scale)/2,50,0 ; position wherever; just  try and get good view of terrain!
RotateEntity camera,30,0,0 ; again, try and get good view of terrain
CameraClsColor camera, 70,70,250
light=CreateLight()
RotateEntity light,90,0,0

; Create terrain
terra=CreateTerrain(terra_size)
ScaleEntity terra,x_scale,y_scale,z_scale
EntityPickMode terra,2,True
EntityFX terra,4
EntityAlpha terra,.5

; Texture terrain
;grid_tex=LoadTexture("Maper_grid.bmp",4)
;EntityTexture terra,grid_tex
;EntityFX terra,1
;EntityAlpha terra,.5

;SetBuffer TextureBuffer()
grid_tex=CreateTexture( 32,32,4+8 )
ScaleTexture grid_tex,1,1
SetBuffer TextureBuffer( grid_tex )
Color 0,0,255:Rect 0,0,32,32
Color 0,0,0:Rect 0,0,32,32,False

SetBuffer BackBuffer()

EntityTexture terra,grid_tex


; Create marker
marker=CreateSphere()
ScaleEntity marker,1,1,1
EntityColor marker,255,0,0

While Not KeyDown(1)
;left\right
If KeyDown( 205 )=True Then TurnEntity camera,0,-1,0
If KeyDown( 203 )=True Then TurnEntity camera,0,1,0
;up\down
If KeyDown( 208 )=True Then TurnEntity camera,-1,0,0
If KeyDown( 200 )=True Then TurnEntity camera,1,0,0

If KeyDown( 30 )=True Then MoveEntity camera,0,0,1
If KeyDown( 44 )=True Then MoveEntity camera,0,0,-1

If MouseHit(3) Then
	PositionEntity camera,marker_x,marker_y+40,marker_z
	
EndIf
 




marker_x=Int(PickedX#())/x_scale*x_scale
marker_y=Int(PickedY#())/y_scale*y_scale
marker_z=Int(PickedZ#())/z_scale*z_scale


CameraPick(camera,MouseX(),MouseY())
 

PositionEntity marker,marker_x,marker_y,marker_z

UpdateWorld 
RenderWorld

Color 250,210,150
Text 0,40,"PickedX: "+PickedX#()
Text 0,60,"PickedY: "+PickedY#()
Text 0,80,"PickedZ: "+PickedZ#()
Text 180,40,"marker_X: "+marker_X
Text 180,60,"marker_Y: "+marker_y
Text 180,80,"marker_Y: "+marker_z

Flip

Wend

End



This is how I started, this is really really ugly and simple, and just places a few things. Can I readjust the x/y/z picks any better?

Graphics3D 800,600,0,2
SetBuffer BackBuffer()

ClsColor 0,0,255
camera=CreateCamera()
PositionEntity camera,0,5,-1
RotateEntity camera,45,0,0
CameraClsColor camera,0,0,128
light=CreateLight()
RotateEntity light,90,0,0
PositionEntity light, 0,0,0
light2=CreateLight()
PositionEntity light,0,50,0
plane=CreateTerrain(128)
PositionEntity plane,-64,0,0
EntityPickMode plane,2 
ground_tex=LoadTexture("c:\gridtex2.bmp")
EntityTexture plane,ground_tex
cube=CreateCube()
cube_tex=LoadTexture("c:\gridtex.bmp")
FitMesh cube,1,0,1,1,.1,1
EntityTexture cube,cube_tex 
PositionEntity cube,0,.1,0
EntityAlpha plane,.1
EntityParent light,cube 
LightMesh CUBE,255,0,0
Const game=1
Const menu=2
image=LoadImage("c:\menua.bmp")
image2=LoadImage("c:\fileimage.bmp")

Dim mObject(3)
mObject(1)=CreateCube()
mObject(2)=CreateSphere()
mObject(3)=CreateCone()
For x=1 To 3 Step 1
FitMesh mobject(x),1,1,1,1,1,1
Next

HideEntity mObject(1)
HideEntity mObject(2)
HideEntity mObject(3)
mtype=1
obj$="cube"
curr_level=-1
EntityParent camera,plane
While Not KeyDown( 1 )
If KeyHit(208)=True Then
MoveEntity plane,0,-1,0
MoveEntity cube,0,-1,0
curr_level=curr_level-1
EndIf
If KeyHit(200)=True Then
MoveEntity plane,0,1,0
MoveEntity cube,0,1,0
curr_level=curr_level+1
EndIf

status=game
If KeyDown( 205 )=True Then TurnEntity camera,0,-1,0
If KeyDown( 203 )=True Then TurnEntity camera,0,1,0
If KeyDown( 208 )=True Then MoveEntity camera,0,0,-0.05
If KeyDown( 200 )=True Then MoveEntity camera,0,0,0.05
newx=MouseX()
newy=MouseY()
If newy<100  status=menu
;a=0
;If newx>oldx+5 Then a=1
;If newx<oldx-5 Then a=1
;If newy<oldy-5 Then a=1
;If newy>oldy+5 Then a=1
;oldx=newx
;oldy=newy
;If a=1
;If MouseHit(1) Then
If status=menu Then
If MouseHit(1) Then
Select True
Case newx<100
	mtype=1
	obj$="cube"
Case newx>100 And newx<320
	mtype=2
	obj$="sphere"
Case newx>320
	mtype=3
	obj$="cone"
End Select
EndIf
EndIf

If status=game Then
CameraPick(camera,MouseX(),MouseY())
x1=Int(PickedX#()-1.25)
y1=Int(PickedY#())
z1=Int(PickedZ#()-1.5)
PositionEntity cube,x1,y1,z1
If MouseHit(1) Then
entity=CopyEntity(mObject(mtype))
UpdateNormals entity
PositionEntity entity,x1,curr_level,z1
EndIf
EndIf
Cls
UpdateNormals cube
RenderWorld
DrawImage image,0,0
DrawImage image2,0,0
Text 10,50,"Current object: "+obj$
Flip
Delay 100
Wend
 
ClearWorld()
End


It would help if you use blitz primatives and a generated grid texture rather than loading media. I can't run it to see what your talking about. Also please describe the problem better.
And the awnser is yes... There is always a better way.

I figured out why i had to readjust the pick coordinates, fitmesh cube,1,1,1,1,1,1 doesn't exactly work right, sorry about the need for the media. Here try this.

Right Click places a 1x1x1 floor tile, right clicking lets you select how big it is.(doesn't work right if you go down/left though). I only made 1 1 color brush *sniff*.
Graphics3D 800,600,0,1
SetBuffer BackBuffer()
ClsColor 255,0,0
Cls

;brush1=CreateBrush(255,0,0)
brush2=CreateBrush(255,0,0)

camera=CreateCamera()
PositionEntity camera,0,5,-1
RotateEntity camera,45,0,0
CameraClsColor camera,0,0,128

light=CreateLight()
RotateEntity light,90,0,0
PositionEntity light, 0,0,0

plane=CreateTerrain(128)
PositionEntity plane,-64,0,0
EntityPickMode plane,2
;PaintEntity plane,brush1

cube=CreateMesh()
surf=CreateSurface(cube)
v1=AddVertex(surf,0,0,0,0,0)
v2=AddVertex(surf,1,0,0,1,0)
v3=AddVertex(surf,1,0,1,1,1)
v4=AddVertex(surf,0,0,1,0,1)
tri=AddTriangle(surf,v4,v3,v1)
tri2=AddTriangle(surf,v3,v2,v1)

PaintEntity cube,brush2
PositionEntity cube,0,.1,0
EntityAlpha plane,.1
EntityParent light,cube 
LightMesh CUBE,255,0,0
obj$="floor"
status=game

sel=0

While Not KeyDown( 1 )
If KeyDown( 205 )=True Then TurnEntity camera,0,-1,0
If KeyDown( 203 )=True Then TurnEntity camera,0,1,0
If KeyDown( 208 )=True Then MoveEntity camera,0,0,-0.05
If KeyDown( 200 )=True Then MoveEntity camera,0,0,0.0

CameraPick(camera,MouseX(),MouseY())
x1=Int(PickedX#())
y1=Int(PickedY#())
z1=Int(PickedZ#())
PositionEntity cube,x1,curr_level,z1

If sel=1 Then
If x1>oldx xd=oldx-x1
If z1>oldz zd=oldz-z1
ScaleEntity ex,xd,1,zd
PositionEntity ex,x1,curr_level,z1
UpdateNormals(ex)
obj$=oldx+","+oldz+","+newx+","+newz
EndIf

If MouseHit(1) Then
entity=CopyEntity(cube)
PositionEntity entity,x1,curr_level,z1
EndIf

If MouseHit(2) Then
Select True
Case sel=0
	oldx=x1
	oldy=y1
	oldz=z1
	sel=1
	sy=1
	sz=1
	sx=1
	ex=CopyEntity(cube)
	UpdateNormals(ex)
	PositionEntity ex,oldx,curr_level,oldz
	HideEntity cube
	LightMesh ex,255,0,0
Case sel=1
	newx=x1
	newy=y1
	newz=z1
	If newx>oldx xd=newx-oldx
	If newz>oldz zd=newz-oldz
	If newx<1 newx=1
	If newz<1 newz=1
	;entity=CopyEntity(cube)
	;ScaleEntity entity,sx,1,sz
	;PositionEntity entity,oldx,curr_level,oldz
	sel=0
	ShowEntity cube
	End Select
EndIf

Cls
FlushMouse

UpdateNormals cube
RenderWorld
Text 10,50,"Current object: "+obj$
Flip
Delay 100
Wend
 
ClearWorld()
End