PDA

View Full Version : Obtaining Positional Data


Plasma
01-28-2004, 04:11 PM
How can I obtain the user's positional data in the virtual environment?

Specifically, I am designing an experiment in which the user will move down a main hallway and then turn right down one of two hallways that lead off it. Proceeding down the second hall, they will see a symbol on the wall and will then return to the starting position. Once at the starting position, they will orient themselves so that they are pointing to the now occluded symbol. (Hopefully this makes sense).

Ideally, the user will use a crosshair to point to the symbol.

I have two questions:

First, is it possible to have a crosshair on the screen at all times (think Quake, or similar).

Second, how do I obtain the user's positional information once they are in position? All I need is rotational information about the Z-Axis (yaw, I think) to see how close the user is to actually pointing to the symbol.

Thanks!

farshizzo
01-28-2004, 04:34 PM
Hi,

To get information about the viewer use the viz.get() command. Take a look in the command reference of the documentation for a more detailed description. Here's an example:
#Get the head position
pos = viz.get(viz.HEAD_POS)

#Get the yaw of the viewer
#Note: yaw refers to rotation about the Y-axis
yaw = viz.get(viz.VIEW_YAW)Take a look at the duckcourt example in the tutorial folder for using crosshairs. Here's the basic idea:
import viz
viz.go()

#Add a texture quad to the screen
crosshair = viz.add(viz.TEXQUAD,viz.SCREEN)

#Apply your crosshair texture to the quad
#Make sure you have an image file with transparency
crosshair.texture(viz.add('crosshair.png'))

#Turn off the mouse cursor
viz.cursor(0)

def mytimer(num):
#Update the crosshair position
crosshair.translate(viz.mousepos()+[0])

viz.callback(viz.TIMER_EVENT,mytimer)
viz.starttimer(0,0.01,viz.FOREVER)Good luck!

Plasma
01-29-2004, 07:10 PM
This seems to be working. Can I get it to give me the information when the joystick trigger is pressed?

Right now I have it printing the data inside a loop so it's giving me a continuous update, but this isn't really what I want.

Also, is it possible to have the user "snap back" to a set position?

Thanks!

Plasma
01-29-2004, 07:13 PM
I just realized I didn't mention that I'd like to be able to trigger the "snap back" with either one of the joystick buttons (except the trigger) or, more ideally, a button on the keyboard. Thanks!

Plasma
01-29-2004, 07:38 PM
I just realized I didn't mention that I'd like to be able to trigger the "snap back" with either one of the joystick buttons (except the trigger) or, more ideally, a button on the keyboard. Thanks!

farshizzo
01-30-2004, 09:58 AM
Hi,

If you want to snap the viewpoint to a certain location when a key is pressed then you will use a KEYBOARD_EVENT. This is an event that is triggered whenever a key is pressed. Here is an example that will place the viewpoint at the position [1,2,3] and reset the orientation whenever the 's' key is pressed:
import viz
viz.go()

def mykey(key):
if key == 's':
viz.reset(viz.HEAD_ORI|viz.BODY_ORI|viz.HEAD_POS)
viz.translate(viz.HEAD_POS,1,2,3)

viz.callback(viz.KEYBOARD_EVENT,mykey)
Good luck!

Plasma
01-31-2004, 08:43 AM
Works beautifully. Thanks!

betancourtb82
02-24-2006, 01:28 PM
I'm using a variation of this duckcourt example, except I increased the speed and shrunk the ball so it looks like a bullet. Unfortunately the crosshair is not too accurate. I don't need pinpoint accuracy, but I would like the "bullet" to "shoot" from the middle of the crosshair. Sometimes when I shoot to the left or right, the bullet comes out from the left or right of the crosshair. I can't think of anyway to adjust this so the bullet comes out from the crosshair no matter what direction I'm shooting. Here is the code for your reference:
def MoveBullet(bullet,elapsed):
hitObject = 0

#check if bullet is colliding with an object
for object in collidables:

#perform the collision check with the object
info = bullet.collidingwith(object,1)
if info.intersected:
#set the bullets new vector to the reflection vector
bullet.vector = viz.Vector(vizmat.ReflectionVector(bullet.vector,i nfo.normalVector))

#create a vector of the normal of the collision
normal = viz.Vector(info.normalVector)

#Check dot product of velocity and normal
if bullet.vector * normal <0:
bullet.vector*= -1

#calculate the rotation vector of the ball
bullet.rotvector = bullet.vector * rotRight

#if object.isTarget and ball.lastHit != object:

hitObject = object

#play ball bounce sound
viz.playsound('bounce.wav')

break
#get the bullet's current position
pos = bullet.get(viz.POSITION)

#calculate the balls future position based on it's velocity
futurePos = pos + (bullet.vector * elapsed)
bullet.translate(futurePos.get())

#rotate the bullet along it's rotation vector
#bullet.rotate(bullet.rotvector[0],bullet.rotvector[1],ball.rotvector[2],90*elapsed,viz.RELATIVE_WORLD)

#Update the bullet's shadow
bullet.shadow.translate(futurePos.x,0,futurePos.z)

def mytimer(num):

if num == ANIMATION:

#Calculate elapsed time since last update
elapsed = viz.elapsed()

#Update each active ball
for bullet in bullets:
if bullet.active:
#Move the ball and check if it has collided with any objects
MoveBullet(bullet,elapsed)

#Update the crosshair position
crosshair.translate(viz.mousepos()+[0])

elif num == START_AVATAR:
global nextAvatar
#Get the next available duck and start it
avatar = avatars[nextAvatar]
walkAvatar(avatar)
nextAvatar = (nextAvatar + 1) % NUM_AVATARS
viz.starttimer(START_AVATAR,TIME_BETWEEN_AVATARS)

#Shoot a ball whenever left mousebutton is clicked
vizact.onmousedown(viz.MOUSEBUTTON_LEFT,shootBulle t)

#Create callbacks for timer events
viz.callback(viz.TIMER_EVENT,mytimer)

##Start a timer which starts the next available duck
viz.starttimer(START_AVATAR,0.1)

#Start the animation timer, which animates the ball and checks for collisions
viz.starttimer(ANIMATION,0.01,-1)

farshizzo
02-24-2006, 02:04 PM
Hi,

Can you provide the code for you shootBullet function, since that is where the relevant code should be. Are you using the viz.screentoworld function similar to the duckcourt example?

betancourtb82
02-27-2006, 11:54 AM
Here you go. Thanks

def shootBullet():
global nextBullet
#find the next available ball to shoot
bullet = bullets[nextBullet]
nextBullet = (nextBullet + 1) % NUM_BULLETS
#Calculate the vector of the ball based on the mouse position
bulletvector = viz.screentoworld(viz.mousepos()+[0])
bullet.vector = viz.Vector(bulletvector[3]-bulletvector[0],bulletvector[4]-bulletvector[1],bulletvector[5]-bulletvector[2])
bullet.vector.normalize()
bullet.vector *= BULLET_SPEED

#translate the bullet to the head position
bullet.translate(viz.get(viz.HEAD_POS))

#make the bullet and it's shadow visible
bullet.visible(viz.ON)
bullet.shadow.visible(viz.ON)

#mark the bullet as active
bullet.active = 1

farshizzo
02-27-2006, 12:18 PM
Hi,

It looks like you pretty much copied the code from the duckcourt example. Do you get this same problem with the duckcourt script?

betancourtb82
02-27-2006, 12:39 PM
Yes I did. It's not as noticeable because of the size of the balls, but I still do get the same effect.

farshizzo
02-27-2006, 01:34 PM
Hi,

Would you mind posting a screenshot of this problem. I don't get this problem when I run the scripts here. Also, which version of Vizard are you using?

betancourtb82
02-28-2006, 09:02 AM
Sure, I have a couple now. How can I go about posting them on this forum? I did notice that when I declared viz.go(viz.HMD |viz.STEREO | viz.TRACKER) it had the problem I had previously described. Once I take off the viz.STEREO, it works fine on my screen, but when I put the HMD on, the image does not display right. I'm not sure if that will help, but I thought I'd mention it.

farshizzo
02-28-2006, 01:57 PM
Hi,

Ok, that makes sense now. When using the screentoworld command you need to account for the stereo mode. So if you are using the mouse with the left eye, then simply multiply the x component of the mouse position by 2.pos = viz.mousepos()
bulletvector = viz.screentoworld(pos[0]*2,pos[1])

betancourtb82
02-28-2006, 04:43 PM
What do you mean if i'm using the mouse with the left eye? I'm using both eyes. The effect occurs as follows. When I'm looking straight ahead, if I shoot to the left, the bullet goes too far left. If I'm shooting to the right, the bullet goes too far right. I tried implementing that code and i still got the same effect. Is there anyway to do this w/o stereo mode?

farshizzo
02-28-2006, 05:10 PM
Hi,

Are you only getting this problem when using STEREO, or do you experience it in non-STEREO mode also? Keep in mind that STEREO mode will offset the position of each eye based on the IPD value. However, the screentoworld command returns coordinates based on the point between both eyes. This is probably why the bullets don't seem to be going straight through the crosshair. There is nothing you can really do about this.

betancourtb82
03-01-2006, 10:10 AM
Yes, it only happens in stereo mode. I think I can take off STEREO mode but the only problem is when I try to do that, the eyes are switched in the HMD. They work fine when I'm looking at the screen (e.g. the Vizard VR toolkit code), but when I actually run the program there is a kind of false projection of an avatar on each eye. I'll close one eye and see one thing, then close the other and see another avatar. I don't know if this is making sense. Please feel free to ask me questions so I can clear this up

farshizzo
03-01-2006, 12:24 PM
Hi,

If you are viewing the world through an HMD then you MUST enable stereo. Otherwise, your left eye will only see the left half of the world and your right eye will see the right half.

betancourtb82
03-01-2006, 01:20 PM
I see, so basically there is no solution to the problem? Thank you for all your help. I know I have asked a lot but I appreciate all that you have helped me with.

farshizzo
03-01-2006, 01:28 PM
Hi,

Well, I wouldn't really call this a problem. What you are asking is kind of impossible to do. You want the object to appear directly at the center of the crosshair for BOTH the left and right eye. Also, keep in mind that the duckcourt example was not intended to be used in STEREO mode. Having GUI objects, such as the crosshair, won't work correctly in STEREO.

betancourtb82
03-02-2006, 04:07 PM
I think I'm not doing a very good job of communicating what we are trying to do. I spoke to another person that works here in the lab and he said that he remembered hearing that this software was used for military shooting simulations. Our application is similar. I'm thinking that if the military does it, the "gun" should be relatively accurate. For some reason ours isn't. I've attached the entire prototyped code for your reference. Any suggestions? If after looking at this code you still think it's impossible to get proper accuracy, then I'll move on and try something else. As I mentioned before, it works w/o stereo mode, but not with.

Thanks :)

import viz
import vizmat
import math
import time
viz.go(viz.STEREO)

#arrays
avatars = [] #for avatars
collidables = [] #for collidable objects
bullets = [] #for number of balls

#constants
NUM_BULLETS = 3 #number of balls in the array
nextBullet = 0 #index for the next ball in the array
BULLET_SPEED = 250 #speed in meters/secs of the bullet
ANIMATION = 1 #animation ID
NUM_AVATARS = 5 #the number of avatars

court = viz.add('terrain1.wrl')
court.scale(0.5,0.5,0.5)
court.rotate(0,1,0,-90)
court.translate(-5,0,-10)
court.appearance(viz.MODULATE)
court.disable(viz.LIGHT0)

#Add a crosshair
crosshair = viz.add(viz.TEXQUAD,viz.SCREEN)
crosshair.texture(viz.add('crosshair.tif'))


#Create six avatars
def startAvatar(location):
global court
for i in range(NUM_AVATARS):

newX = -math.cos(-2*i+15) * 2
newZ = math.sin(i^2+1) * 2
male = viz.add('male.cfg')
male.translate(newX,0,newZ)
male.rotate(180,0,0)
avatars.append(male) #Save avatar in list
startAvatar(court)
def onmousedown(button):
if button == viz.MOUSEBUTTON_LEFT:
node = viz.pick() #Get object that was clicked
if node in avatars: #Check if object is one of the avatars
node.execute(7) #Execute the "shot" animation
#Create action to wait for the animation duration then freeeze the avatar
WaitThenFreeze = vizact.sequence( vizact.waittime(node.getduration(7)-.1), vizact.speed_node(0) )
node.add(WaitThenFreeze) #Add the action to the avatar
viz.callback(viz.MOUSEDOWN_EVENT,onmousedown)


for x in range(0,NUM_BULLETS):
#create a bullet that is initially hidden
bullet = viz.add('ball.wrl')
bullet.scale(.1,.1,.1)
bullet.visible(viz.OFF)

#add a shadow, To be removed once final program is completed
bullet.shadow = viz.add('shadow.wrl')
bullet.shadow.alpha(0.7)
bullet.shadow.visible(viz.OFF)

#Enable collisions with the ball based on a sphere shape
bullet.collidesphere(0.25)
bullet.isTarget = 0
collidables.append(bullet)

#keep track of the last object the ball hit
bullet.lastHit = 0

#add the ball to the ball list
bullets.append(bullet)
bullet.active = 0
def shootBullet():
global nextBullet
#find the next available ball to shoot
bullet = bullets[nextBullet]
nextBullet = (nextBullet + 1) % NUM_BULLETS
#Calculate the vector of the ball based on the mouse position
bulletvector = viz.screentoworld(viz.mousepos())
bullet.vector = viz.Vector(bulletvector[3]-bulletvector[0],bulletvector[4]-bulletvector[1],bulletvector[5]-bulletvector[2])
bullet.vector.normalize()
bullet.vector *= BULLET_SPEED

#translate the bullet to the head position
bullet.translate(viz.get(viz.HEAD_POS))

#make the bullet and it's shadow visible
bullet.visible(viz.ON)
bullet.shadow.visible(viz.ON)

#mark the bullet as active
bullet.active = 1

def MoveBullet(bullet,elapsed):
hitObject = 0

#check if bullet is colliding with an object
for object in collidables:

#perform the collision check with the object
info = bullet.collidingwith(object,1)
if info.intersected:
#set the bullets new vector to the reflection vector
bullet.vector = viz.Vector(vizmat.ReflectionVector(bullet.vector,i nfo.normalVector))

#create a vector of the normal of the collision
normal = viz.Vector(info.normalVector)

#Check dot product of velocity and normal
if bullet.vector * normal <0:
bullet.vector*= -1

#calculate the rotation vector of the ball
bullet.rotvector = bullet.vector * rotRight

#if object.isTarget and ball.lastHit != object:

hitObject = object

#play ball bounce sound
viz.playsound('bounce.wav')

break
#get the bullet's current position
pos = bullet.get(viz.POSITION)

#calculate the balls future position based on it's velocity
futurePos = pos + (bullet.vector * elapsed)
bullet.translate(futurePos.get())

#rotate the bullet along it's rotation vector
#bullet.rotate(bullet.rotvector[0],bullet.rotvector[1],ball.rotvector[2],90*elapsed,viz.RELATIVE_WORLD)

#Update the bullet's shadow
bullet.shadow.translate(futurePos.x,0,futurePos.z)

def mytimer(num):

if num == ANIMATION:

#Calculate elapsed time since last update
elapsed = viz.elapsed()

#Update each active ball
for bullet in bullets:
if bullet.active:
#Move the ball and check if it has collided with any objects
MoveBullet(bullet,elapsed)

#Update the crosshair position
crosshair.translate(viz.mousepos()+[0])
#
# elif num == START_DUCK:
# global nextDuck
# #Get the next available duck and start it
# duck = ducks[nextDuck]
# beginDuck(duck)
# nextDuck = (nextDuck + 1) % NUM_DUCKS
# viz.starttimer(START_DUCK,TIME_BETWEEN_DUCKS)
#
#Shoot a ball whenever left mousebutton is clicked
vizact.onmousedown(viz.MOUSEBUTTON_LEFT,shootBulle t)

#Create callbacks for timer events
viz.callback(viz.TIMER_EVENT,mytimer)

##Start a timer which starts the next available duck
#viz.starttimer(START_DUCK,0.01)

#Start the animation timer, which animates the ball and checks for collisions
viz.starttimer(ANIMATION,0.01,-1)

#Move the head position back
viz.translate(viz.HEAD_POS,0,0,-10)

#Disable mouse navigation
viz.mouse(viz.OFF)

farshizzo
03-02-2006, 05:03 PM
Hi,

I've attached a modified version of the script which I hope will point out why you are experiencing this problem. First of all, I removed the crosshair because you shouldn't be using objects attached to the screen when using stereo. Second, I set the ipd value to 0. The ipd is the eye distance value. So both eyes will be at the same location. Third, I multiplied the x value of the mouse position by 2.0 when using the screentoworld command. This should cause the the bullet to come directly from the mouse position, for the left half of the screen. If you set the IPD value back to normal, you will experience your problem again. This is because in stereo mode the eyes are offset from the actual viewpoint position. I've attached an image which shows why the bullet appears to go to the left (excuse my crappy drawing skills :) ). Do you plan on the user using the mouse to aim while wearing the HMD?
import viz
import vizmat
import math

viz.go(viz.STEREO)

#arrays
avatars = [] #for avatars
collidables = [] #for collidable objects
bullets = [] #for number of balls

#constants
NUM_BULLETS = 3 #number of balls in the array
nextBullet = 0 #index for the next ball in the array
BULLET_SPEED = 250 #speed in meters/secs of the bullet
ANIMATION = 1 #animation ID
NUM_AVATARS = 5 #the number of avatars

court = viz.add('terrain1.wrl')
court.scale(0.5,0.5,0.5)
court.rotate(0,1,0,-90)
court.translate(-5,0,-10)
court.appearance(viz.MODULATE)
court.disable(viz.LIGHT0)

#Set eye distance to 0 to show why the bullet goes to the left of the mouse
viz.ipd(0)

#Create six avatars
def startAvatar(location):
global court
for i in range(NUM_AVATARS):

newX = -math.cos(-2*i+15) * 2
newZ = math.sin(i^2+1) * 2
male = viz.add('male.cfg')
male.translate(newX,0,newZ)
male.rotate(180,0,0)
avatars.append(male) #Save avatar in list
startAvatar(court)

for x in range(0,NUM_BULLETS):
#create a bullet that is initially hidden
bullet = viz.add('ball.wrl')
bullet.scale(.1,.1,.1)
bullet.visible(viz.OFF)

#add a shadow, To be removed once final program is completed
bullet.shadow = viz.add('shadow.wrl')
bullet.shadow.alpha(0.7)
bullet.shadow.visible(viz.OFF)

#Enable collisions with the ball based on a sphere shape
bullet.collidesphere(0.25)
bullet.isTarget = 0
collidables.append(bullet)

#keep track of the last object the ball hit
bullet.lastHit = 0

#add the ball to the ball list
bullets.append(bullet)
bullet.active = 0
def shootBullet():
global nextBullet
#find the next available ball to shoot
bullet = bullets[nextBullet]
nextBullet = (nextBullet + 1) % NUM_BULLETS
#Calculate the vector of the ball based on the mouse position
pos = viz.mousepos()
bulletvector = viz.screentoworld(pos[0]*2.0,pos[1]) #Need to account for stereo
bullet.vector = viz.Vector(bulletvector[3]-bulletvector[0],bulletvector[4]-bulletvector[1],bulletvector[5]-bulletvector[2])
bullet.vector.normalize()
bullet.vector *= BULLET_SPEED

#translate the bullet to the head position
bullet.translate(viz.get(viz.HEAD_POS))

#make the bullet and it's shadow visible
bullet.visible(viz.ON)
bullet.shadow.visible(viz.ON)

#mark the bullet as active
bullet.active = 1

def MoveBullet(bullet,elapsed):
hitObject = 0

#check if bullet is colliding with an object
for object in collidables:

#perform the collision check with the object
info = bullet.collidingwith(object,1)
if info.intersected:
#set the bullets new vector to the reflection vector
bullet.vector = viz.Vector(vizmat.ReflectionVector(bullet.vector,i nfo.normalVector))

#create a vector of the normal of the collision
normal = viz.Vector(info.normalVector)

#Check dot product of velocity and normal
if bullet.vector * normal <0:
bullet.vector*= -1

#if object.isTarget and ball.lastHit != object:

hitObject = object

#play ball bounce sound
viz.playsound('bounce.wav')

break
#get the bullet's current position
pos = bullet.get(viz.POSITION)

#calculate the balls future position based on it's velocity
futurePos = pos + (bullet.vector * elapsed)
bullet.translate(futurePos.get())

#Update the bullet's shadow
bullet.shadow.translate(futurePos.x,0,futurePos.z)

def mytimer(num):

if num == ANIMATION:

#Calculate elapsed time since last update
elapsed = viz.elapsed()

#Update each active ball
for bullet in bullets:
if bullet.active:
#Move the ball and check if it has collided with any objects
MoveBullet(bullet,elapsed)

#Shoot a ball whenever left mousebutton is clicked
vizact.onmousedown(viz.MOUSEBUTTON_LEFT,shootBulle t)

#Create callbacks for timer events
viz.callback(viz.TIMER_EVENT,mytimer)

##Start a timer which starts the next available duck
#viz.starttimer(START_DUCK,0.01)

#Start the animation timer, which animates the ball and checks for collisions
viz.starttimer(ANIMATION,0.01,-1)

#Move the head position back
viz.translate(viz.HEAD_POS,0,0,-10)

#Disable mouse navigation
viz.mouse(viz.OFF)

betancourtb82
03-06-2006, 01:35 PM
For now we plan to use the mouse, however, when I tried this code, it didn't work for me. When I "shot" the avatars, nothing happened to them. So, now, after looking at this code, are you still sure that there is no way to adjust for the accuracy of the bullet when shooting to the sides? Thanks,

farshizzo
03-08-2006, 10:06 AM
Hi,

The code I posted was made with the latest internal version of Vizard. I realized that it won't work with the version you have. You just need to change the screentoworld command to the following:bulletvector = viz.screentoworld(pos[0]+0.25,pos[1])Also, I made this script to show the bullet coming from the mouse. I didn't add any picking to it, so nothing will happen to the avatars when you click them. As I already mentioned, this will only work when you set IPD to 0. However, having an IPD of 0 will make your HMD useless since you won't be receiving stereo images.

betancourtb82
03-08-2006, 12:41 PM
What do you mean by useless? I tried using the code w/the HMD and the bullet came exactly from the mouse position. Is there a way to make them perform an action when they are hit by a bullet? I wouldn't mind keeping the IPD at zero as long as the avatars would fall when they got hit.

farshizzo
03-08-2006, 01:32 PM
The whole point of wearing an HMD is that each eye gets a different view of the scene. This is what make the image look 3D. Setting IPD to zero will effectively disable stereo since both eyes will be receiving the same view of the scene.

Here is some sample code that will play the hit animation when the avatar is hit by a bullet. Replace the code with whatever action you need:import viz
import vizmat
import math

viz.go(viz.STEREO)

#arrays
avatars = [] #for avatars
bullets = [] #for number of balls

#constants
NUM_BULLETS = 3 #number of balls in the array
nextBullet = 0 #index for the next ball in the array
BULLET_SPEED = 250 #speed in meters/secs of the bullet
ANIMATION = 1 #animation ID
NUM_AVATARS = 5 #the number of avatars

court = viz.add('terrain1.wrl')
court.scale(0.5,0.5,0.5)
court.rotate(0,1,0,-90)
court.translate(-5,0,-10)
court.appearance(viz.MODULATE)
court.disable(viz.LIGHT0)

#Set eye distance to 0 to show why the bullet goes to the left of the mouse
viz.ipd(0)

#Create six avatars
def startAvatar(location):
global court
for i in range(NUM_AVATARS):

newX = -math.cos(-2*i+15) * 2
newZ = math.sin(i^2+1) * 2
male = viz.add('male.cfg')
male.translate(newX,0,newZ)
male.rotate(180,0,0)
avatars.append(male) #Save avatar in list
startAvatar(court)

for x in range(0,NUM_BULLETS):
#create a bullet that is initially hidden
bullet = viz.add('ball.wrl')
bullet.scale(.1,.1,.1)
bullet.visible(viz.OFF)
bullet.disable(viz.COLLISION)
bullet.active = 0

#add the ball to the ball list
bullets.append(bullet)

def shootBullet():
global nextBullet
#find the next available ball to shoot
bullet = bullets[nextBullet]
nextBullet = (nextBullet + 1) % NUM_BULLETS
#Calculate the vector of the ball based on the mouse position
pos = viz.mousepos()
bulletvector = viz.screentoworld(pos[0]+0.25,pos[1]) #Need to account for stereo
bullet.vector = viz.Vector(bulletvector[3]-bulletvector[0],bulletvector[4]-bulletvector[1],bulletvector[5]-bulletvector[2])
bullet.vector.normalize()
bullet.vector *= BULLET_SPEED

#translate the bullet to the head position
bullet.translate(viz.get(viz.HEAD_POS))

#make the bullet visible
bullet.visible(viz.ON)

#mark the bullet as active
bullet.active = 1

def MoveBullet(bullet,elapsed):

#get the bullet's current position
pos = bullet.get(viz.POSITION)

#calculate the balls future position based on it's velocity
futurePos = pos + (bullet.vector * elapsed)

#Check if bullet intersected with anything
info = viz.intersect(pos,futurePos)
if info.intersected:
if info.object in avatars:
info.object.add(vizact.animation(7))
bullet.visible(0)
bullet.active = 0

#Update balls positions
bullet.translate(futurePos.get())

def mytimer(num):

if num == ANIMATION:

#Calculate elapsed time since last update
elapsed = viz.elapsed()

#Update each active ball
for bullet in bullets:
if bullet.active:
#Move the ball and check if it has collided with any objects
MoveBullet(bullet,elapsed)

#Shoot a ball whenever left mousebutton is clicked
vizact.onmousedown(viz.MOUSEBUTTON_LEFT,shootBulle t)

#Create callbacks for timer events
viz.callback(viz.TIMER_EVENT,mytimer)

#Start the animation timer, which animates the ball and checks for collisions
viz.starttimer(ANIMATION,0.01,-1)

#Move the head position back
viz.translate(viz.HEAD_POS,0,0,-10)

#Disable mouse navigation
viz.mouse(viz.OFF)

betancourtb82
03-08-2006, 02:03 PM
Thank you very much!

betancourtb82
03-09-2006, 02:26 PM
Ok, I tried adding the wait then freeze, instead of just having the avatar fall and get back up, but for some reason, it's not working. What does the underscore in speed_node(0) mean?

info = viz.intersect(pos,futurePos)
if info.intersected:
if info.object in avatars:
#viz.starttimer(FREEZE_AVATAR,info.object.getdurat ion(7)-0.1)
WaitThenFreeze = vizact.sequence( vizact.waittime(info.object.getduration(7)-0.2), vizact.speed_node(0) )
info.object.add(WaitThenFreeze) #Add the action to the avatar
#info.object.add(vizact.sequence(vizact.waittime(n o
bullet.visible(0)
bullet.active = 0

farshizzo
03-09-2006, 03:08 PM
Hi,

You are not actually executing any animations on the avatar. You should add the following line before adding the WaitThenFreeze action:info.object.execute(7)

betancourtb82
03-20-2006, 01:22 PM
Ok, everything works great so far. The only problem is that I am getting some kind of traceback error.

Traceback (most recent call last):
File "Test2WithEyeAdjustment.py", line 185, in mytimer
avatar = avatars[nextAvatar]
IndexError: list index out of range

This occurs whenever I shoot an avatar and he disappears. When I double click on the error it highlights:
def mytimer(num):
global avatars
if num == ANIMATION:

#Calculate elapsed time since last update
elapsed = viz.elapsed()

#Update each active ball
for bullet in bullets:
if bullet.active:
#Move the ball and check if it has collided with any objects
MoveBullet(bullet,elapsed)

elif num == START_AVATAR:
global nextAvatar
#Get the next available avatar and start it
avatar = avatars[nextAvatar]
#favatar = favatars[nextAvatar]
walkAvatar(avatar)
#walkAvatar(favatar)
nextAvatar = (nextAvatar + 1) % NUM_AVATARS
viz.starttimer(START_AVATAR,TIME_BETWEEN_AVATARS)
#Create callbacks for timer events
viz.callback(viz.TIMER_EVENT,mytimer)


When I shoot the avatars, this function is called:
def shootBullet():
global nextBullet
#find the next available ball to shoot
bullet = bullets[nextBullet]
nextBullet = (nextBullet + 1) % NUM_BULLETS
#Calculate the vector of the ball based on the mouse position
pos = viz.mousepos()
bulletvector = viz.screentoworld(pos[0]+0.25,pos[1]) #Need to account for stereo
bullet.vector = viz.Vector(bulletvector[3]-bulletvector[0],bulletvector[4]-bulletvector[1],bulletvector[5]-bulletvector[2])
bullet.vector.normalize()
bullet.vector *= BULLET_SPEED

#translate the bullet to the head position
bullet.translate(viz.get(viz.HEAD_POS))

#make the bullet visible
bullet.visible(viz.ON)

#mark the bullet as active
bullet.active = 1

def MoveBullet(bullet,elapsed):
#get the bullet's current position
pos = bullet.get(viz.POSITION)

#calculate the balls future position based on it's velocity
futurePos = pos + (bullet.vector * elapsed)

#Check if bullet intersected with anything
info = viz.intersect(pos,futurePos)
if info.intersected:
if info.object in avatars:
#viz.starttimer(FREEZE_AVATAR,info.object.getdurat ion(7)-0.1)
WaitThenFreeze = vizact.sequence( vizact.waittime(info.object.getduration(7)-0.05), vizact.speed_node(0) )
info.object.execute(7)
info.object.clear(viz.ALL)
info.object.clear(viz.CURRENT_ACTION)
info.object.add(WaitThenFreeze) #Add the action to the avatar
RemoveAvatarAction = vizact.call(RemoveAvatar,info.object)
info.object.add(RemoveAvatarAction) #Add action to remove avatar

bullet.visible(0)
bullet.active = 0

#Update balls positions
bullet.translate(futurePos.get())
#Shoot a ball whenever left mousebutton is clicked
vizact.onmousedown(viz.MOUSEBUTTON_LEFT,shootBulle t)

What does the error mean? Can it be fixed

farshizzo
03-20-2006, 02:17 PM
Hi,

That means you are trying to index into the avatar list with a value greater than the size of the list. Are you deleting items from the avatar list after you create it? If so then you need to change the way you increment to the next avatar:nextAvatar = (nextAvatar + 1) % len(avatars)

betancourtb82
03-21-2006, 09:26 AM
I'm still getting the same error. I'm not sure what is causing it. When a bullet "hits" or intersects an avatar, the following code is called:

if info.intersected:
if info.object in avatars:
WaitThenFreeze = vizact.sequence( vizact.waittime(info.object.getduration(7)-0.005), vizact.speed_node(0) )
info.object.execute(7)
info.object.clear(viz.ALL)
info.object.clear(viz.CURRENT_ACTION)
info.object.add(WaitThenFreeze) #Add the action to the avatar
RemoveAvatarAction = vizact.call(RemoveAvatar,info.object)
info.object.add(RemoveAvatarAction) #Add action to remove avatar

The RemoveAvatar function is:
def RemoveAvatar(avatar):

avatar.visible(0) #Hide avatar
avatar.speed(1) #Restore speed
avatars.remove(avatar) #Remove from list
dead_list.append(avatar) #Add to dead list
I tried using the len(avatars) modulus division but it still gives me the same traceback error.

I also tried:
if len(avatars) != NUM_AVATARS:
avatar = dead_list[nextAvatar]
nextAvatar = nextAvatar + 1 % len(dead_list)
else:
avatar = avatars[nextAvatar]
nextAvatar = (nextAvatar + 1) % len(avatars)
walkAvatar(avatar)

but that didn't work either.

betancourtb82
03-21-2006, 10:47 AM
New question, similar problem. I have now been told that the avatars must appear with different faces, based on an input. Here is what I have done so far:

#define a choice variable
choice = viz.input("Please input the condition:")
global facepic
if choice == 1:
facepic = 'biohead_talk.vzf'
else:
facepic = 'morph_head.vzf'

#Create six avatars
for i in range(NUM_AVATARS):
newX = -10 * math.sin(theta * i)
newZ = 10 * math.tan(theta * i)
if newZ <=10:
newZ = -15
else:
newZ = 10 * math.tan(theta * i)
#print i,"\t\t\t\t\t",newX,"\t",newZ
male = viz.add('male.cfg')
male.face(facepic)
male.scale(1.25,1.25,1.25)
male.translate(newX,-10,newZ)
avPos = male.get(viz.POSITION)
print 'original avatar position', avPos
male.rotate(180,0,0)
avatars.append(male) #Save avatar in list

Now, when I shoot the avatars, they fall and disappear, as planned. The problem I'm having is that the face still stays on the screen.

Here is the code for removing the avatars once shot:
#Check if bullet intersected with anything
info = viz.intersect(pos,futurePos)
if info.intersected:
print 'intersect point is',info.intersectPoint
if info.object in avatars:
WaitThenFreeze = vizact.sequence( vizact.waittime(info.object.getduration(7)-0.005), vizact.speed_node(0) )
info.object.execute(7)
info.object.clear(viz.ALL)
info.object.clear(viz.CURRENT_ACTION)
info.object.add(WaitThenFreeze) #Add the action to the avatar
RemoveAvatarAction = vizact.call(RemoveAvatar,info.object)
info.object.add(RemoveAvatarAction) #Add action to remove avatar
Is there a reason why the face stays floating in the air. I'm assuming it should disappear with the body. Please help.

Thanks

farshizzo
03-21-2006, 10:57 AM
Try incrementing the to the next avatar before you access it:nextAvatar = (nextAvatar + 1) % len(avatars)
avatar = avatars[nextAvatar]The face and body of the avatar are two separate objects, so you need to also hide the face when you hide the avatar.

betancourtb82
03-30-2006, 01:07 PM
Earilier in this forum, when we discussed the crosshair, you mentioned that we shouldn't be using objects that are attached to the screen when using stereo. I spoke to Mattias this weekend at the VR conference in Alexandria, VA and he mentioned that if we use a 3d object, we would probably be able to fix the problem of the bullets (mentioned in above posts) without having to change the IPD. Is this the case. Is there some way of making a "3d crosshair" that will accurately point to where the bullet would go? If so, do you have any ideas on how this can be implemented? I was thinking of making a vector that would match the vector of the bullet and place an icon (crosshair) at some point on the vector, in 3d, to show an aiming point. How does this idea sound? Can it be done? Please help.

Below is the code I have for the bullet so far.
def shootBullet():
global nextBullet
#find the next available ball to shoot
bullet = bullets[nextBullet]
nextBullet = (nextBullet + 1) % NUM_BULLETS
#Calculate the vector of the ball based on the mouse position
pos = viz.mousepos()
bulletvector = viz.screentoworld(pos[0]+0.25,pos[1]) #Need to account for stereo
bullet.vector = viz.Vector(bulletvector[3]-bulletvector[0],bulletvector[4]-bulletvector[1],bulletvector[5]-bulletvector[2])
bullet.vector.normalize()
bullet.vector *= BULLET_SPEED

#translate the bullet to the head position
bullet.translate(viz.get(viz.HEAD_POS))

#make the bullet visible
bullet.visible(viz.ON)

#mark the bullet as active
bullet.active = 1

def MoveBullet(bullet,elapsed):
global avatarsHit
#get the bullet's current position
pos = bullet.get(viz.POSITION)

#calculate the balls future position based on it's velocity
futurePos = pos + (bullet.vector * elapsed)

#Check if bullet intersected with anything
info = viz.intersect(pos,futurePos)
if info.intersected:
avatarsHit = avatarsHit + 1
print 'Avatars hit: ', avatarsHit
print 'intersect point is',info.intersectPoint
if info.object in avatars:
WaitThenFreeze = vizact.sequence( vizact.waittime(info.object.getduration(7)-0.005), vizact.speed_node(0) )
info.object.execute(7)
info.object.clear(viz.ALL)
info.object.clear(viz.CURRENT_ACTION)
info.object.add(WaitThenFreeze) #Add the action to the avatar
RemoveAvatarAction = vizact.call(RemoveAvatar,info.object)
info.object.add(RemoveAvatarAction) #Add action to remove avatar

bullet.visible(0)
bullet.active = 0

#Update balls positions
bullet.translate(futurePos.get())

farshizzo
03-30-2006, 01:19 PM
Yes, this is how most people implement crosshairs for stereo viewing. Here is a sample script that will place a crosshair 0.1 meters in front of the user.import viz
viz.go(viz.STEREO)

viz.add('tut_ground.wrl')
viz.clearcolor(viz.GRAY)

crosshair = viz.add(viz.TEXQUAD)
crosshair.texture(viz.add('crosshair.png'))
crosshair.scale(0.01,0.01,0.01)

viz.mouse(viz.OFF)

def ontimer(num):
line = viz.screentoworld(viz.mousepos())
v = viz.Vector(viz.get(viz.HEAD_POS))
dir = viz.Vector(line[3:]) - viz.Vector(line[:3])
dir.normalize()
dir *= 0.1 #Place crosshair 1/10th meter in front of user
v += dir
crosshair.translate(v.get())
crosshair.rotatequat(viz.get(viz.VIEW_QUAT))

viz.callback(viz.TIMER_EVENT,ontimer)
viz.starttimer(0,0,viz.FOREVER)

betancourtb82
04-04-2006, 09:40 AM
Ok, I implemented the crosshair as you said, however I'm still getting an offset between the bullet and the crosshair. Is there anyway to correct this now that I am using the "3d" version of the crosshair? I've attached a copy of the code.

farshizzo
04-04-2006, 10:14 AM
I tried your script but I didn't see any bullet. I've modified my previous code so that it shoots a bullet from the center of the viewpoint towards the direction of the crosshair. There will always be an apparent offset between the crosshair and the bullet due to binocular vision.import viz
viz.go(viz.STEREO)

viz.add('tut_ground.wrl')
viz.clearcolor(viz.GRAY)

crosshair = viz.add(viz.TEXQUAD)
crosshair.texture(viz.add('crosshair.png'))
crosshair.scale(0.01,0.01,0.01)

viz.mouse(viz.OFF)

def ontimer(num):
line = viz.screentoworld(viz.mousepos())
v = viz.Vector(viz.get(viz.HEAD_POS))
dir = viz.Vector(line[3:]) - viz.Vector(line[:3])
dir.normalize()
dir *= 0.1 #Place crosshair 1/10th meter in front of user
v += dir
crosshair.translate(v.get())
crosshair.rotatequat(viz.get(viz.VIEW_QUAT))

viz.callback(viz.TIMER_EVENT,ontimer)
viz.starttimer(0,0,viz.FOREVER)

bullet = viz.add('white_ball.wrl')

def shoot():
pos = viz.Vector(viz.get(viz.HEAD_POS))
dir = viz.Vector(crosshair.get(viz.POSITION)) - pos
dir.normalize()
dir *= 10
bullet.translate(pos.get())
bullet.goto((pos+dir).get(),3)
vizact.onmousedown(viz.MOUSEBUTTON_LEFT,shoot)

betancourtb82
04-04-2006, 10:46 AM
I apologize. I think I sent you something I was working on earlier but I corrected it. I still get the same behavior. Would you mind taking a look at this one and let me know if there is something wrong? Thanks

farshizzo
04-04-2006, 11:31 AM
In both calls to viz.screentoworld you are adding an offset to the x position. You don't need to do this when using a 3D cursor. Also, after adding the cursor you should disable collisions on it so the bullet does not hit it.crosshair.disable(viz.COLLISION)