WorldViz User Forum

WorldViz User Forum (https://forum.worldviz.com/index.php)
-   Vizard (https://forum.worldviz.com/forumdisplay.php?f=17)
-   -   slow intersect call (https://forum.worldviz.com/showthread.php?t=729)

pbeeson 09-11-2006 01:46 PM

slow intersect call
 
I am having serious slowdowns in my Vizard script. I tracked it down to the fact that I am calling viz.intersect 180 times in a single callback. The 180 iteration loop takes around 0.15 seconds to run. This is werid because pressing F4 twicde shows me that the update is only suppossed to be taking 30-100 milliseconds.

Two things: 1) Is the value shown for Updates when the f4 stats are shown actually in MILLI seconds? 2) Is there a faster call than viz.intersect in Vizard 2.53g?

pbeeson 09-11-2006 02:36 PM

Strange. I was putting the viewpoint inside of an avatar and using that avatar as the body to detect for collisions. I was doing the 180 line intersections because I was simulating a laser range finder which returns distances to objects in a plane. The laser was not inside the mesh of the avatar, but very close to its front. None of the 180 rays ever touched the body enclosing the viewpoint; however, if I make the avatar that the viewpoint is inside of not visible, then this fuction speeds up a bit by a factor of 2 (0.08 seconds). This is weird to me, but I can live with weirdness.

I still think that 0.08 seconds to calculate 180 intersections seems a bit slow, and would like to know if there is a faster way to cast rays and get the locations (or distances) of the intersection points in the world.

farshizzo 09-11-2006 02:50 PM

Hi,

1) The values should be in milliseconds.

2) In 2.53 the viz.intersect() command is pretty much your only option. You might be able to speed up the call by disabling collisions with objects that you are not interested in.
Code:

object.disable(viz.COLLISION)
Another thing you can do is create very low-res versions of your models. These low-res versions will represent the collision mesh of the high-res models. Then disable collisions on the high-res and disable rendering on the low-res. The viz.intersect() command performs the intersection on each triangle in your model, regardless of the collision shape you defined for it using the collide*() functions.

Vizard 3.0 allows you to use the underlying physics engine to perform intersection tests, which will be optimized for the collision shapes defined for each model. I just did a test with a simple scene, and performing 100 intersections per frame caused the update time to be 25 ms using viz.intersect() and 2.5 ms using the physics line intersect command.

farshizzo 09-11-2006 02:54 PM

Quote:

Strange. I was putting the viewpoint inside of an avatar and using that avatar as the body to detect for collisions. I was doing the 180 line intersections because I was simulating a laser range finder which returns distances to objects in a plane. The laser was not inside the mesh of the avatar, but very close to its front. None of the 180 rays ever touched the body enclosing the viewpoint; however, if I make the avatar that the viewpoint is inside of not visible, then this fuction speeds up a bit by a factor of 2 (0.08 seconds). This is weird to me, but I can live with weirdness.
Disabling collisions with the avatar would give you the same result. See my previous post.

Even though the laser line was not inside the mesh of the avatar, it was inside its bounding box. When Vizard is performing intersection tests it will first check if the line intersects with an objects bounding box. If it does, it will proceed to check if the line intersects with each triangle.

pbeeson 09-11-2006 03:16 PM

I am getting 80ms with just my "indoor" environment, which is pretty simple. Maybe I should try to separate the walls from the ceiling and floor and add them both to vizard since I never care about intersecting with the seiling or floor.

farshizzo 09-11-2006 07:22 PM

Unless your floor and ceiling contain a lot of triangles, it's probably not going to make much of a difference. But if you want to try it out, you don't need to create separate models for them. Simply specify the name of the floor/ceiling mesh when disabling collisions. Example:
Code:

room.disable(viz.COLLISION,'ceiling')
room.disable(viz.COLLISION,'floor')

Also, do these intersections tests need to be performed every frame? If not, you can offload the intersection tests onto a thread that performs them at a lower rate.

pbeeson 09-11-2006 08:30 PM

I noticed in version 3 that viz.phys.intersectLine() is much faster than viz.intersect(), but viz.phys.intersectLine seems to have some problems:

1) It returns intersections for non-visible objects (object whose visibility is set to off), which is different that viz.intersect()

2) It ignores the viz.disable(viz.COLLISION) command. Is there a way to get it to ignore certain objects?
I can run viz.phys.intersectLine(begin,end,True) to get a list and then check object IDs, but I don't know if there is an easier way (especially considering that if you have many objects, it might be an optimzation to not check for intersections with particular objects at certain times, e.g. if you are casting rays from within an object).

3) As I said earlier, I am casting 180 "rays" from a virtual laser range finder. When I do this, viz.phys.intersectLine() is much faster than viz.intersect() (Even if I set the all flag to True), but viz.phys.intersectLine actually misses some intersections with the closest objects, while viz.intersect() does not. I'll post two picture to illustrate my point.

pbeeson 09-12-2006 07:25 AM

2 Attachment(s)
Pertaining to point 3 from above posting.

Notice that in the left image, some of the rays cast from the "robot" I have in Vizard (shown as a rectangle) go through the wall (white line in grey space). I believe this is a bug in viz.phys.intersectLine()

When I use viz.intersect() instead of viz.phys.intersectLine(), all rays properly intersect the wall (right image).

(These details don't show up well in the thumbnails, but do in the fuill size images.

Gladsomebeast 09-12-2006 10:05 AM

Is there a collision shape defined for the wall, probably with collideMesh()? viz.phys.intersectLine() only intersects with VizPhysicsShapes, not model geometry.

pbeeson 09-12-2006 12:19 PM

Quote:

Originally Posted by Gladsomebeast
Is there a collision shape defined for the wall, probably with collideMesh()? viz.phys.intersectLine() only intersects with VizPhysicsShapes, not model geometry.

Yes, collidemesh() is used. It's not all the scans, just a few of them.

farshizzo 09-12-2006 12:22 PM

Do these missed intersections occur near a triangle boundary?

farshizzo 09-12-2006 02:42 PM

Quote:

Originally Posted by pbeeson
I noticed in version 3 that viz.phys.intersectLine() is much faster than viz.intersect(), but viz.phys.intersectLine seems to have some problems:

1) It returns intersections for non-visible objects (object whose visibility is set to off), which is different that viz.intersect()

I just fixed this. Setting an object to non-visible will automatically disable physics on it.

Quote:

Originally Posted by pbeeson
2) It ignores the viz.disable(viz.COLLISION) command. Is there a way to get it to ignore certain objects?
I can run viz.phys.intersectLine(begin,end,True) to get a list and then check object IDs, but I don't know if there is an easier way (especially considering that if you have many objects, it might be an optimzation to not check for intersections with particular objects at certain times, e.g. if you are casting rays from within an object).

I just modified the physics intersectLine/Node commands so that they ignore objects which have physics disabled on them. viz.COLLISION will still only pertain to the old viz.intersect() command.

I know this really doesn't help you now, but we will probably release an update within the next few days.

pbeeson 09-12-2006 04:00 PM

Quote:

Originally Posted by farshizzo
I know this really doesn't help you now, but we will probably release an update within the next few days.

It doesn't help me even when I get the update. In 2.53, I could have a body that represented the "viewer". That body could be not visible, so that intersect() would not see it, but collidingwith() still did see it. But, I get by with calling phys.intersect(start,end,True) and then removing points that intersect the viewers own "body".

pbeeson 09-12-2006 04:03 PM

Quote:

Originally Posted by farshizzo
Do these missed intersections occur near a triangle boundary?

No. The thickness of the "wall" is only 0.01, maybe that has something to do with it. I'll try increasing the thickness, and see if that makes a difference.

farshizzo 09-12-2006 04:12 PM

Quote:

Originally Posted by pbeeson
It doesn't help me even when I get the update. In 2.53, I could have a body that represented the "viewer". That body could be not visible, so that intersect() would not see it, but collidingwith() still did see it. But, I get by with calling phys.intersect(start,end,True) and then removing points that intersect the viewers own "body".

So you want an object to be invisible, but still allow phys.intersect to work? Then just disable rendering on the object:
Code:

object.disable(viz.RENDERING)
Sorry if I misunderstood your question.

pbeeson 09-12-2006 04:19 PM

Quote:

Originally Posted by farshizzo
So you want an object to be invisible, but still allow phys.intersect to work? Then just disable rendering on the object:
Code:

object.disable(viz.RENDERING)
Sorry if I misunderstood your question.

I don't care if it is invisible. All I know is that by doing avatar.visible(viz.OFF), in version 2.53, viz.intersect() would never return an intersection with the avatar, but viz.collidingwith() WOULD work if the avatar collided with antoher obstacle.

Maybe THAT was the bug, and now it is fixed. It's just different.

farshizzo 09-12-2006 04:26 PM

Quote:

Originally Posted by pbeeson
Maybe THAT was the bug, and now it is fixed. It's just different.

Correct, that behaviour was a bug. In the next release when an object is set to invisible using the node.visible() command, it will not respond to any intersection queries.

pbeeson 09-12-2006 04:28 PM

1 Attachment(s)
Quote:

Originally Posted by pbeeson
No. The thickness of the "wall" is only 0.01, maybe that has something to do with it. I'll try increasing the thickness, and see if that makes a difference.

Oddly, increasing the thickness of the wall made more rays NOT intersect the wall, while decreasing the thickness of the wall made more rays intersect the wall. By setting the wall thickness to 0, all rays properly see the wall, and the map I get looks like the right figure (see above thumbnails) which is correct. As I increase the thickness of the wall, more white rays go through the wall in the map I make, showing improper intersections with viz.phys.intersectLine()

Attached is the .wrl file of the environment I am using (I changed it to .txt to get it to upload). If you search and replace 0.01, you can change the thickness of walls. I start at (10.5,1.3,-21.0) with an orientation of 0.0. The rays you see in the left image that go through the wall are at about 12.25, 1.3, -17.5 (the thing in the middle in the picture is an avatar).

Hope this helps.

farshizzo 09-12-2006 06:52 PM

I can't replicate your problem. I downloaded your model and made the thickness of the wall to 1.0. I then setup a timer that would perform a 180 degree sweep of intersection tests based on the current view position/orientation. I spent a minute navigating through the maze and never got a missed intersection. Here's the script I used to test it out:
Code:

import viz
import math
viz.go()

wall = viz.add('wall_thick.wrl')
wall.collideMesh()
wall.disable(viz.DYNAMICS)

viz.MainView.translate(10.5,1.3,-21.0)

def SweepIntersection():

        #Get begin point for intersection test
        begin = viz.MainView.getPosition()
        bx = begin[0]
        by = begin[1]
        bz = begin[2]
       
        #Get point 100 units ahead of viewpoint
        forward = viz.Vector(viz.MainView.getMatrix().getForward(),length=100)
        px = forward[0]
        pz = forward[2]
       
        for deg in range(-90,90):
               
                #Rotate ahead point by deg (Assume no pitch/roll)
                rad = viz.radians(deg)
                x = math.cos(rad)*px - math.sin(rad)*pz
                z = math.sin(rad)*px + math.cos(rad)*pz
               
                #Calculate end point
                ex = bx + x
                ez = bz + z
               
                #Perform intersection
                info = viz.phys.intersectLine(begin,(ex,by,ez))
               
                #Check if intersection is not valid
                if not info.valid:
                        print 'NO INTERSECTION'

vizact.ontimer(0,SweepIntersection)

Does this problem only occur under certain conditions or is it pretty much random?

pbeeson 09-12-2006 08:34 PM

Here is code that works with the Test.wrl I posted earlier. The view is at an angle to the hallway, so a line straight ahead should intersect the wall which is 4.3 meters away. But, this particular line misses the intersection with the closest wall and intersects another wall in the environment (> 10 meters away).

This shows the different results sometimes returned by viz.phys.intersectLine() and viz.intersect().

Code:

import viz, math

viz.go()

env = viz.add('Test.wrl')
env.collidemesh()
env.disable(viz.DYNAMICS)

start_pos=[10.5, 1.3, -21.43391, 23.975]

view=viz.get(viz.MAIN_VIEWPOINT)
view.translate(start_pos[0], start_pos[1], start_pos[2])
view.rotate(0,1,0,start_pos[3], viz.BODY_ORI,viz.ABSOLUTE)

def dist(x1,y1,x2,y2):
    return math.sqrt(pow(x1-x2,2)+pow(y1-y2,2))

def timerCallback(num):
    end_pos=[start_pos[0]+100*math.sin(start_pos[3]*math.pi/180),
            start_pos[1],
            start_pos[2]+100*math.cos(start_pos[3]*math.pi/180)]
    inters_obj = viz.phys.intersectLine(start_pos[0:3], end_pos)
    print inters_obj.intersectPoint
    print dist(inters_obj.intersectPoint[0],inters_obj.intersectPoint[2],
              start_pos[0],start_pos[2])
    inters_obj = viz.intersect(start_pos[0:3], end_pos)
    print ''
    print inters_obj.intersectPoint
    print dist(inters_obj.intersectPoint[0],inters_obj.intersectPoint[2],
              start_pos[0],start_pos[2])
    print '\n\n'

   

viz.callback(viz.TIMER_EVENT, timerCallback)
viz.starttimer(1, 1, -1)


farshizzo 09-13-2006 09:33 AM

I see now, at first I thought the problem was that no intersections were being reported, but the problem is that it doesn't return the closest intersection. Thanks for the test script, the problem should be fixed now.

pbeeson 09-13-2006 09:51 AM

Quote:

Originally Posted by farshizzo
I see now, at first I thought the problem was that no intersections were being reported, but the problem is that it doesn't return the closest intersection. Thanks for the test script, the problem should be fixed now.

Any way I can get my hands on the fixed code. For "testing" purposes.


All times are GMT -7. The time now is 07:28 AM.

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