WorldViz User Forum

WorldViz User Forum (https://forum.worldviz.com/index.php)
-   Vizard (https://forum.worldviz.com/forumdisplay.php?f=17)
-   -   rotating an object (https://forum.worldviz.com/showthread.php?t=2022)

Penguin 05-11-2009 09:39 AM

rotating an object
 
Hi, I want to rotate an object (sphere) similar to the globe in google earth.

The sphere is mapped in front of the main view. With the use of the viz.pick() command I get the intersection position of the mouse pointer on the sphere (intersectionItem.point).

The following code is running in a mouse button down callback function. While dragging the mouse over the sphere the new intersection position is callculated (curIntersectionItem.point)

With this two points and the center of the sphere I get two direction vectors and the angle inbetween.

The rotation of the sphere seems to work until it rolls. Then the mouse movement does not match to the rotation of the sphere any more!

Is there a better way to achieve a stable rotation? While dragging in google earth the same part of the globe always stays under the mouse pointer.

Code:

curIntersectionItem = calcUiIntersection()
rotationMat = vizmat.Transform()
rotationMat.makeVecRotVec(vizmat.VectorToPoint(sphere.getPosition(viz.ABS_GLOBAL),intersectionItem.point),vizmat.VectorToPoint(sphere.getPosition(viz.ABS_GLOBAL),curIntersectionItem.point))

spherePos = sphere.getPosition(viz.ABS_GLOBAL)
sphereMat = sphere.getMatrix(viz.ABS_GLOBAL)
sphereMat.setTrans(0,0,0)

transformMat = vizmat.Transform()
transformMat = rotationMat * sphereMat

transformMat.setTrans(spherePos)
sphere.setMatrix(transformMat,viz.ABS_GLOBAL)

intersectionItem = curIntersectionItem


Gladsomebeast 05-11-2009 04:32 PM

Interesting goal. I whipped up a bit of code that orbits the sphere by telling the sphere to "lookat" the intersection point, then rotating the sphere the initial offset amount.

The code is not quite right yet because sustained clicking on the same point rolls the sphere around that point. Maybe somebody knows whats wrong?

Code:

import viz
import vizmat
import vizshape

viz.go()
viz.mouse.setOverride(viz.ON)

node = vizshape.addSphere(pos=[0, 1.8, 3])
node.texture(viz.add('image2.jpg'))
rotation = None
def onGrab():
        global rotation
        intersectionItem = viz.pick(1)
        if intersectionItem.valid:
                src_ori = vizmat.Quat(node.getQuat(viz.ABS_GLOBAL))
                node.lookat(intersectionItem.point, viz.ABS_GLOBAL)
                dst_ori = vizmat.Quat(node.getQuat(viz.ABS_GLOBAL))
                #D = O * S so O = D * 1/S
                rotation =  src_ori * dst_ori.inverse()
               
vizact.onmousedown(viz.MOUSEBUTTON_LEFT, onGrab)

def moveSphere():
        if rotation:
                intersectionItem = viz.pick(1)
                if intersectionItem.valid:
                        node.lookat(intersectionItem.point)
                        node.setQuat(rotation, viz.ABS_LOCAL)
               
vizact.onupdate(viz.PRIORITY_DEFAULT, moveSphere)
               
def endGrab():
        global rotation
        rotation = None
vizact.onmouseup(viz.MOUSEBUTTON_LEFT, endGrab)


Penguin 05-12-2009 11:21 AM

Except for the slight roll, your code works fine. But here it comes: when I attach the sphere to the main view the rotation doesn't work any longer.

Code:

import viz
import vizmat
import vizshape

viz.go()
viz.mouse.setOverride(viz.ON)

node = vizshape.addSphere(pos=[0, 1.8, 3])
node.texture(viz.add('image2.jpg'))

viewLink = viz.link(viz.MainView,node)
viewLink.preTrans([0,0,3])

rotation = None
def onGrab():
        global rotation
        intersectionItem = viz.pick(1)
        if intersectionItem.valid:
                src_ori = vizmat.Quat(node.getQuat(viz.ABS_GLOBAL))
                node.lookat(intersectionItem.point, viz.ABS_GLOBAL)
                dst_ori = vizmat.Quat(node.getQuat(viz.ABS_GLOBAL))
                #D = O * S so O = D * 1/S
                rotation =  src_ori * dst_ori.inverse()
               
vizact.onmousedown(viz.MOUSEBUTTON_LEFT, onGrab)

def moveSphere():
        if rotation:
                intersectionItem = viz.pick(1)
                if intersectionItem.valid:
                        node.lookat(intersectionItem.point)
                        node.setQuat(rotation, viz.ABS_LOCAL)
               
vizact.onupdate(viz.PRIORITY_DEFAULT, moveSphere)
               
def endGrab():
        global rotation
        rotation = None
vizact.onmouseup(viz.MOUSEBUTTON_LEFT, endGrab)


Gladsomebeast 05-12-2009 11:29 AM

Righto. The link is overriding the rotation we are giving the sphere. To fix we tell the link to only operate on position

Code:

viewLink = viz.link(viz.MainView,node, mask=viz.LINK_POS)

Penguin 05-12-2009 01:09 PM

Step by step I'm able to locate the source of the problem: I use the sphere in a hierarchical group order. The following code reproduces the strange behaviour of rotating.

Code:

import viz
import vizmat
import vizshape

viz.go()
viz.mouse.setOverride(viz.ON)

root = viz.add(viz.GROUP, parent=viz.WORLD)
root.setPosition([0,1.8,3],viz.REL_GLOBAL)

node = vizshape.addSphere(pos=[0,0,0], parent=root)
node.texture(viz.add('image2.jpg'))
rotation = None
def onGrab():
        global rotation
        intersectionItem = viz.pick(1)
        if intersectionItem.valid:
                src_ori = vizmat.Quat(node.getQuat(viz.ABS_GLOBAL))
                node.lookat(intersectionItem.point, viz.ABS_GLOBAL)
                dst_ori = vizmat.Quat(node.getQuat(viz.ABS_GLOBAL))
                #D = O * S so O = D * 1/S
                rotation =  src_ori * dst_ori.inverse()
               
vizact.onmousedown(viz.MOUSEBUTTON_LEFT, onGrab)

def moveSphere():
        if rotation:
                intersectionItem = viz.pick(1)
                if intersectionItem.valid:
                        node.lookat(intersectionItem.point)
                        node.setQuat(rotation, viz.ABS_LOCAL)
                       
vizact.onupdate(viz.PRIORITY_DEFAULT, moveSphere)
               
def endGrab():
        global rotation
        rotation = None
vizact.onmouseup(viz.MOUSEBUTTON_LEFT, endGrab)


Jerry 05-13-2009 10:18 AM

Here's another way to do it.

Code:


from viz import *

go()

clearcolor(.8,.8,.8)
vert = add('ball.wrl')
vert.translate(0,1.8,2)

xang = 0
yang = 0
INCREMENT = .5

mouse(OFF)
restrictmouse(OFF)

def mousemove(x,y):                                       
        global xang,yang
       
        state = buttonstate()

        if state == MOUSEBUTTON_LEFT:
                xang = xang + x*INCREMENT
                yang = yang + y*INCREMENT
                vert.rotate(0,1,0,-x*INCREMENT,RELATIVE_WORLD)
                vert.rotate(1,0,0,y*INCREMENT,RELATIVE_WORLD)
               
mousedata(RELATIVE,RELATIVE)
callback(MOUSEMOVE_EVENT,mousemove)


Gladsomebeast 05-13-2009 12:15 PM

Interesting... I shall dub thee Spinner Metaphor Method and place you in a file of honor.

Penguin 05-14-2009 09:25 AM

Hi Gladsomebeast, the effect of slight roll results in the lookat call. The second argument is a optional roll value. The internal value of viz.ABS_GLOBAL is 4:

Code:

node.lookat(intersectionItem.point, 0, viz.ABS_GLOBAL)
not

Code:

node.lookat(intersectionItem.point,viz.ABS_GLOBAL)
because this is a roll of 4 degree

Code:

node.lookat(intersectionItem.point,4)

Gladsomebeast 05-14-2009 10:50 AM

Of course, of course, the roll parameter =) Thanks for sharing the fix.

Jerry 05-17-2009 12:47 PM

Since spinning balls is so much fun,
Let's try spinning more than one.

Code:

from viz import *

go()

clearcolor(.8,.8,.8)
ball1 = add('ball.wrl')
ball1.translate(.3,1.8,1.5)
ball2 = add('ball.wrl')
ball2.translate(-.3,1.8,1.5)

balls = []
balls.append(ball1)
balls.append(ball2)

INCREMENT = .5

mouse(OFF)
restrictmouse(OFF)

def mousemove(x,y):                                       
       
        object = pick()

        if viz.mouse.getState() == viz.MOUSEBUTTON_LEFT:
                mousedown = 1
        else:
                mousedown = 0
               
        if object in balls and mousedown == 1:
                object.rotate(0,1,0,-x*INCREMENT,RELATIVE_WORLD)
                object.rotate(1,0,0,y*INCREMENT,RELATIVE_WORLD)

               
mousedata(RELATIVE,RELATIVE)
callback(MOUSEMOVE_EVENT,mousemove)


Or if you like the number three,
Let's try to make them all agree.

Code:

from viz import *

go()

clearcolor(.8,.8,.8)
ball1 = add('ball.wrl')
ball1.translate(0,2.1,2)
ball2 = add('ball.wrl')
ball2.translate(.4,1.5,2)
ball3 = add('ball.wrl')
ball3.translate(-.4,1.5,2)

balls = []
balls.append(ball1)
balls.append(ball2)
balls.append(ball3)

INCREMENT = .5

mouse(OFF)
restrictmouse(OFF)

def mousemove(x,y):                                       
       
        object = pick()

        if viz.mouse.getState() == viz.MOUSEBUTTON_LEFT:
                mousedown = 1
        else:
                mousedown = 0
               
        if object in balls and mousedown == 1:
                for b in range(len(balls)):
                        balls[b].rotate(0,1,0,-x*INCREMENT,RELATIVE_WORLD)
                        balls[b].rotate(1,0,0,y*INCREMENT,RELATIVE_WORLD)

               
mousedata(RELATIVE,RELATIVE)
callback(MOUSEMOVE_EVENT,mousemove)


And here's the one you want the most,
Just like iPhone make it coast.

Code:

from viz import *

go()

clearcolor(.8,.8,.8)
ball1 = add('ball.wrl')
ball1.translate(.3,1.8,1.5)
ball2 = add('ball.wrl')
ball2.translate(-.3,1.8,1.5)

balls = []
balls.append(ball1)
balls.append(ball2)

increment = .5
COAST = 1
mx = 0
my = 0
object = []
spinning = 0

mouse(OFF)
restrictmouse(OFF)

def mousemove(x,y):                                       
        global mx,my,object,spinning,increment
       
        if spinning == 0:
                object = pick()

        if mouse.getState() == MOUSEBUTTON_LEFT:
                object = pick()
                mousedown = 1
                killtimer(COAST)
                spinning = 0
        else:
                mousedown = 0
               
        if object in balls and mousedown == 1:
                object.rotate(0,1,0,-x*increment,RELATIVE_WORLD)
                object.rotate(1,0,0,y*increment,RELATIVE_WORLD)
                mx = x
                my = y

        if mousedown == 1 and spinning == 0:
                increment = .5
                spinning = 1
                starttimer(COAST,.01,FOREVER)
               
mousedata(RELATIVE,RELATIVE)
callback(MOUSEMOVE_EVENT,mousemove)

def onTimer(num):
        global spinning,mx,my,object,increment
       
        if num == COAST:
       
                object.rotate(0,1,0,-mx*increment,RELATIVE_WORLD)
                object.rotate(1,0,0,my*increment,RELATIVE_WORLD)

                increment = increment - .01
                if abs(increment) < .01:
                        spinning = 0
                        increment = .5
                        killtimer(COAST)
                                               
viz.callback(viz.TIMER_EVENT,onTimer)


Gladsomebeast 05-18-2009 05:24 PM

Spinning is fun
I do agree.
But rotations be done,
I'm going crazy.


All times are GMT -7. The time now is 07:02 PM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Copyright 2002-2023 WorldViz LLC