|
|
|
Return to Code Snippets
by chombee » Tue Mar 13, 2007 6:57 am
Path Following: I'm not sure how you would want to implement this. I'd probably pass a list of waypoints to the behavior. Then, pass a variable for whether or not to loop the waypoints or finish at the last one. Once the vehicle got within a certain distance that waypoint could be declared "cleared" and the target could move to the next one. This could be fairly easy. Use "seek" and "obstacle avoid" and cycle through waypoints as the targets.
Yeah that would work, but would not be quite as good as the implementation I linked to. The vehicles would move in a more or less straight line toward each waypoint then turn suddenly as they passed each waypoint. What you need for a better implementation is a Path class with a nearestPointOnPath(Point3) method that returns the nearest point on the path given some point in space. The vehicle makes a prediction of its future position x time units in the future, with x increasing or decreasing depending on vehicle speed (using the already implemented Vehicle.predictFuturePosition()). The vehicle calls path.nearestPointOnPath(futurePos) on the path that it's following. If the distance between the vehicles predicted position and the nearest point on the path from that future position becomes greater than some constant value (the width of the path) then the vehicle corrects by seeking toward a point further down the path (obtained by calling path.pointFurtherAlong()). That would produce a nice smooth sort of path following like here: http://www.red3d.com/cwr/steer/PathFollow.html and any object with a nearestPointOnPath and a pointFurtherAlong method can be used as a path to follow. You could probably implement such a Path class by defining a path as a series of waypoints, and interpolating between waypoints to implement the nearestPointOnPath and pointFurtherAlong methods. That would produce a polyline path just like the one in the demo above. Proper leader following: You've got most of this coded already. The separation is the only thing that really needs to be added. Separation would probably involve having a larger collision sphere and looking for collisions then applying a force normal to the collision surface.
Yeah this one should be really easy picking right now. Separation steering would be needed and I agree with you about how it should be implemented. You'd also need a 'get out of the way' behaviour, where if a follower vehicle finds itself inside the CollisionTube of the leader vehicle it gets out of the way fast. Then I think you just combine steering behaviours with the following priority: 1. Get out of the way 2. Separation 3. Arrival, with the target being a point behind the leader.
-
chombee
-
- Posts: 244
- Joined: Fri Jan 13, 2006 10:09 am
by mavasher » Tue Mar 13, 2007 6:16 pm
maybe you can by-pass the whole function to search for the closest point and go directly to finding the distance between the line and the point. http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
You're still going to have to cycle through the waypoints. If you look at the JAVA applet there are points when the future point is around the corner from the vehicle but still within the path, so for the vehicle to actually travel to that point it would cut through the corner. The applet still checks the point against the correct line segment in the path and not the path in its entirety.
I would have tried to code some of it today but I was busy.
-

mavasher
-
- Posts: 294
- Joined: Thu Feb 08, 2007 10:32 am
- Location: Texas
by ynjh_jo » Mon Mar 19, 2007 9:00 am
Just digged this again.
1. chombee wrote:Worse, if the target is just in front of an obstacle, the character may arrive at the target and stop, but then the CollisionTube may be colliding with the obstacle, which will cause the character to run around needlessly trying to avoid the obstacle. The best way to fix this I think would be to vary the length of the character's CollisionTube frame-by-frame according to the character's speed, so that when the character comes to rest at a target location the CollisionTube will shrink to a sphere around the character and not collide with any obstacles beyond the target. I had trouble implementing this though and have given up for now. There is the issue of the Character's CollisionTube varying in length frame by frame depending on the Character's speed, that should be possible with CollisionTube.setPointB but I haven't got it right yet. That would be a good fix.
OMG, how come ? Tell me, how did you do it ? in Vehicle.step : - Code: Select all
tube=self.tubenp.node().getSolid(0) tube.setPointB(Point3(tube.getPointA()+Point3(0,15.*self._velocity.length(),0)))
Since the tubes' length are not uniform anymore, it looks more natural. The slow char wouldn't steer away excessively before reaching make-sense distance to the obstacle. 2. chombee wrote:collisions seem to occur fairly often with a lot of characters in a small space. Is it possible to collide two CollisionTubes against each other? If so, the characters CollisionTubes could be used to detect character-character collisions also.
It's not possible, since nobody has written tube-tube intersection for Panda yet. There are open source physics engines which have anything-anything intersection algo, if you like to "learn" it. However, you have created a sphere around each char, right ? What is it used for ? Why don't you use it to collide with the tube ? Just need to change it's bit mask. 3. cleanup() the FSM before deleting the actor to prevent exception error 4. there is still memory leakage at vehicle level, around 100 KB for each restart (10/12 chars). It's the neighbors list ! - Code: Select all
for v in self.plugins[self.plugin].vehicles: v.neighbors = None
It's not critical, but kept scratching my head.
-

ynjh_jo
-
- Posts: 1795
- Joined: Tue Apr 18, 2006 12:41 am
- Location: Malang, Indonesia
-
by chombee » Mon Mar 19, 2007 1:27 pm
Sweet! :D
Thanks alot ynjh_jo, I'll be checking out those suggestions as soon as I'm next at my development machine (tomorrow, probably).
1., I think I was setting both the X and Y values of the CollisionTube's point B according to speed, not just the Y value as you do, and this was causing the tube to vary in a really indescribable but wrong way because I had evidently made some mistake. I may also have been confused about the local<->global transform. I can see how your way would be the correct answer...
Since the tubes' length are not uniform anymore, it looks more natural. The slow char wouldn't steer away excessively before reaching make-sense distance to the obstacle.
I can't wait to see this!
2. I have to look back at the code, but I think you've picked up on an old comment that I should have removed. Collisions don't occur between characters very often any more, since I fixed a bug in the collision avoidance code. Actually before that I did try colliding the CollisionTubes of characters against the CollisionSpheres of characters and then just employing the same steering as used to avoid static obstacles to get moving characters to avoid eachother. This doesn't work very well however, the characters tend to steer into eachother and otherwise do the wrong thing. It turns out collision avoidance steering is quite different from obstacle avoidance steering. Steering to avoid collisions involves comparing the velocities of both characters to find out if they will collide in the future, and if so steering to avoid the point of collision, so comparing one character's velocity (CollisionTube) against the other's position (CollisionSphere) would not achieve the same effect.
3. Cheers!
4. Thanks again. What exactly do you use to spot all these memory leaks by the way? Do you have some utility?
-
chombee
-
- Posts: 244
- Joined: Fri Jan 13, 2006 10:09 am
by ynjh_jo » Mon Mar 19, 2007 2:27 pm
4. In Python, there is built-in garbage collector, and Panda has provided it in showbase.GarbageReport. I tried it, but it keep throwing zero. I haven't used it directly in python, so I still don't know exactly. I just took a look at every __init__ in your classes, and found it hasn't been released during destruction.
-

ynjh_jo
-
- Posts: 1795
- Joined: Tue Apr 18, 2006 12:41 am
- Location: Malang, Indonesia
-
by chombee » Tue Mar 27, 2007 1:31 pm
The download was getting pretty out of date again. I updated it with various visible and refactoring improvements:
Download.
Follow steering behaviour is much nicer now, though still not completely finished. Obstacle avoidance works better (an old bug was still in the download version for some reason). Much refactoring to make the code nicer on the inside has been done but the relationship between Character and Vehicle still needs sorting out.
ynjh_jo: I've incorporated your code for the CollisionTube varying in size over time. Works nicely. And your suggestion to cleanup() the FSM on destroying a Character. I haven't had time to figure out where to put your
- Code: Select all
for v in self.plugins[self.plugin].vehicles: v.neighbors = None
just yet.
I saw some improvements to the terrain generation algorithm from a friend the other night. For hilly terrain, you can run a 'smoothing' function over the heightmap to make it look much nicer, the spikier the terrain the more you smooth it. We also thought of a way to put flat paths and rivers through hilly or mountainous terrain models that we want to try. Update coming soon...
-
chombee
-
- Posts: 244
- Joined: Fri Jan 13, 2006 10:09 am
by ynjh_jo » Tue Mar 27, 2007 2:49 pm
It's in restart, where else...
or in Character.destroy
-

ynjh_jo
-
- Posts: 1795
- Joined: Tue Apr 18, 2006 12:41 am
- Location: Malang, Indonesia
-
by chombee » Fri Apr 27, 2007 10:05 am
New release: http://chombee.panda3dprojects.com/Pand ... v51.tar.gz
* New 'containment' steering behaviour, characters will steer to remain within some container shape (shapes implemented: circle and square), combines with any of the other steering behaviours
* New smoothHeightMap function in terrain.py -- after creating a fractal terrain it gets smoothed out so it looks better
* Major refactoring of code, especially character.py and vehicle.py. Doesn't look like I introduced any bugs (!), the code is much more consistent and easier to understand and use now
* When you press 'c' for annotation the characters now have 'speech bubbles' saying what steering they're using. Done with DirectLabel. For some reason they look all flickery. If anyone can fix them and generally make them look better that'd be great. I'd like something like the speech bubbles and labels in toontown: http://www.weirdave.com/images/toontown ... 5-5846.jpg
-
chombee
-
- Posts: 244
- Joined: Fri Jan 13, 2006 10:09 am
by ynjh_jo » Tue May 01, 2007 11:47 am
Nice. just got a chance to DL it.
about the flicker, it's directional light's work, which behaves that way on vertex colored model, e.g. rgbCube. Use setLightOff(1) on the label.
-

ynjh_jo
-
- Posts: 1795
- Joined: Tue Apr 18, 2006 12:41 am
- Location: Malang, Indonesia
-
by chombee » Wed May 02, 2007 6:50 am
Yep, thanks ynjh_jo. That'll be in the next update.
-
chombee
-
- Posts: 244
- Joined: Fri Jan 13, 2006 10:09 am
by chombee » Thu May 03, 2007 8:37 am
Ok, new revision uploaded: download.
* Committed ynjh_jo's above fix for the flickering DirectLabels
Running pandaSteer.py you shouldn't see any other difference, but if you run terrain.py or the new scene.py you will see new stuff. This code is still very rough right now, so any pointers welcome:
* perlin.py module -- contains a couple of utility functions for producing Perlin noise using Panda's Perlin2 class (thanks to Hypnos in this thread: http://panda3d.org/phpbb2/viewtopic.php?t=2648)
* terrain.py module has been revised to be a little more object-oriented (new Terrain class), and now trees can be placed on the terrain using Perlin noise. You pass a parameter (a float from 0 to 1) determining how many trees a terrain model should have, and the exact number and placement of trees is computed using Perlin. Run terrain.py to see a demo with four terrain models each with different hilliness and trees values.
* New scene.py module -- a demo scene with terrain, trees, wandering non-player Ralph characters and a point-and-click controlled player character, and an EdgeScreenTracker camera following the player (camera code is from tiptoe, ynjh_jo and cyan in this thread: http://panda3d.org/phpbb2/viewtopic.php?t=2038 ). The terrain is surrounded by a sea model and skybox (thanks to Mavasher: http://panda3d.org/phpbb2/viewtopic.php?t=2577)
The characters in the scene steer to avoid the trees and to remain on the island. Actually I think the Container object is not even positioned properly so they may wander off the island, but trust me this works if you just position the container right.
Another problem is that the fractal terrain has dips in it as well as hills, so I've had to float the terrain above the sea to prevent too many 'lakes' appearing where the terrain dips below sea level. The characters don't avoid these lakes. Any ideas for how to get rid of unwanted lakes welcome. I'm thinking of trying out Panda's PerlinNoise as a heightmap generator.
Although the characters do a fair job of steering around individual trees, they do not steer to avoid 'forests' (groups of trees). Instead of going round a forest they will thread their way through it, and since they can only really steer to avoid one obstacle at a time, they sometimes hit trees when there are many close together.
Since I'm using a blocky, grid-like terrain map (and you might notice that I place every tree in the centre of one of the maps quads and have only one tree per quad) a good solution to this might be a simple pathfinding algorithm. Simply represent each quad of the terrain in a 2D list as True (you can walk here) or False (for some reason you can't walk here, e.g. there is a tree in this quad). Then run an A* search over this grid to find paths from A to B. You could ofcourse represent other obstacles like buildings or lakes or high hills in the map in the same way.
Does anyone know if Panda has any search algorithms built in? Or can anyone point me to a good implementation of A* in Python? Ideally the search function should be implemented in C for speed though.
To get characters to follow a path a new path-following steering behaviour would be needed, but this would be easy for simple polyline paths and I think it's already been discussed in this thread.
That would more-or-less replace the arrival steering behaviour. But for steering behaviours like pursue, evade, follow and wander it doesn't make much sense to be following a path, so it might be necessary to add a 'no penetration' steering constraint to prevent characters from steering into obstacles. Or just ignore it. For wandering, you could combine path-following and wander and have characters wander along a path (you could, for example, repeatedly compute a path from A to a random quad B then wander along it, or you could use pre-defined paths to wander on).
-
chombee
-
- Posts: 244
- Joined: Fri Jan 13, 2006 10:09 am
by enn0x » Thu May 03, 2007 10:57 am
Or can anyone point me to a good implementation of A* in Python?
I found this in my bookmarks. It claims to be a simple python implementation of A*. The demo required PyGame, but the algorithm itself is vanilla (no dependencies). I never tested the code, only marked it for future interest.
http://arainyday.se/projects/python/AStar/
EDIT: If this algorithms suits your needs I would offer to do (or at least try to do) a quick C++ implementation via Pyrex.
enn0x
-
enn0x
-
- Posts: 1267
- Joined: Wed Nov 08, 2006 1:39 am
- Location: Germany, Munich
by chombee » Fri May 04, 2007 8:50 am
Fixed the filename of the skin in tree1.egg so that trees are now skinned: http://chombee.panda3dprojects.com/Pand ... v54.tar.gz
Think I need to use loadModelCopy and loadTextureCopy or something on the trees. Will do.
P.S. the tree model and texture are from mavasher's island/minimaps et al code linked to above. Thanks mavasher!
-
chombee
-
- Posts: 244
- Joined: Fri Jan 13, 2006 10:09 am
by ynjh_jo » Fri May 04, 2007 1:37 pm
If the assets structure was not changed, could you split the assets-script download ? It's not fun DLing 6 megs over & over again.
Thx.
-

ynjh_jo
-
- Posts: 1795
- Joined: Tue Apr 18, 2006 12:41 am
- Location: Malang, Indonesia
-
by chombee » Fri May 11, 2007 1:11 pm
Update: lots of minor tweaking:
http://chombee.panda3dprojects.com/Pand ... v59.tar.gz
http://chombee.panda3dprojects.com/Pand ... v59.tar.gz
As you can see I've split the code from the assets as ynjh_jo requested. The assets download contains a models folder which you must extract into the PandaSteer2 folder from the first download. The assets download has not changed since my previous release (rev54).
* All characters start on the island now and will stay on it :)
* Characters avoid trees better because they have a greater maximum steering force, but optimally they may need even more force. Try fiddling with the maxforce settings in scene.py if you want.
* Camera settings and controls
* Better character-character collision avoidance (Vehicle radius was not being set)
* Tried some efficiency improvements: once all trees have been 'planted' on a terrain object it disables the collision traverser for trees (no longer needed) and calls flattenStrong on the trees (which are all attached to a trees node). Not sure I got much out of it though, and may have introduced a bug (see below).
Run scene.py to see the island scene. You can rotate the camera left/right by moving the mouse to the left/right edges of the window or pressing the left/right arrow keys, rotate it up/down by mousing to the top/bottom edges of the window, zoom it in and out by pressing the up/down arrow keys. You can zoom in close to see your character or far out to see the whole scene. To move your player click on the terrain with the mouse. To toggle annotation of the steering behaviours and collisions press 'C'.
As usual pandaSteer.py and terrain.py can also be run to see other stuff (but they have not been updated in this revision).
If you want to help out, there's now a list of known issues in knownIssues.txt in the download. The main one right now is this, which may have been introduced recently due to my efficiency improvements:
#
Sometimes none of the trees seem to get added to the collision detection system. No collisions between characters' collision tubes and trees' collision spheres occur, characters walk right through trees. Framerate is much better :)
Sometimes only _some_ of the trees get added to the collision system.
Is this something to do with flattenStrong?
If you don't think the characters are steering to avoid the trees, please kill the program and start it again. You can press 'C' to see the collisions visualised, which makes it very obvious when the characters are attempting to steer round trees. If they run right through trees with no collisions being visualised then you are seeing the above bug.
Any contributions that get at the known issues, or efficiency and robustness improvements, or new features, more than welcome.
Where I'm going with this code:
* I'd like the player to be able to right-click on a non-player character to cause the player character and the NPC to walk up to each other and start a 'conversation'.
* The 'conversation' would bring up a simple DirectGUI dialog with which the player can tell the non-player character what to do: wander, go to X, follow Y, flee from Z, etc. Go find A and bring them to C. All the things that can be done with the steering behaviours.
* I'd like some objects to be scattered around the island that the characters can pick up and carry and pass between eachother. One of the Panda3D samples shows how to get actor models to carry other models like teapots, swords etc. attached to their hands.
-
chombee
-
- Posts: 244
- Joined: Fri Jan 13, 2006 10:09 am
by ynjh_jo » Sun May 13, 2007 6:30 am
Sometimes none of the trees seem to get added to the collision detection system. Sometimes only _some_ of the trees get added to the collision system. Is this something to do with flattenStrong?
I believe so. I tried to use forceRecomputeBounds, but didn't work. So I placed each sphere after the trees planted completely. The sphere's size is based on the tree's tight bounds. Sometimes character models fall under the terrain model. Could it be that the CollisionRay used with CollisionHandlerFloor is on rare occasions shooting right through a tiny gap in the terrain model? Though I don't see why there should be gaps in the terrain model, this problem did occur with placing trees, leading to code that 'wiggles' a tree until its ray hits some terrain. Maybe try using the characters collision sphere to detect the height of the terrain and set the Z accordingly? (i.e. don't use collisionhandlerfloor)
You're right. If the ray exactly hits the tri's edge, it wouldn't be considered as collision. You solved it by offsetting each "missed shot" tree randomly. It means you need an extra coll detection pass, at least it costs you 1 frame time. Why not offsetting the collision terrain since the 1st place ? It cost you only 1 pass, with less transform on your bunch of tree nodes. And you can shift it back after flattening the trees, if you like. So shaking the tree method only serves as "spare bullet".
new terrain.py
-

ynjh_jo
-
- Posts: 1795
- Joined: Tue Apr 18, 2006 12:41 am
- Location: Malang, Indonesia
-
by chombee » Mon May 14, 2007 8:10 am
Thanks ynjh_jo, I've commited those. New download (code only): http://chombee.panda3dprojects.com/Pand ... v62.tar.gz
Interesting, I don't find this NodePath.getTightBounds function that you used anywhere in the online documentation on this site, or by running Python's help function on NodePath. I guess you have to look into the C++ source to find that? Could you explain it? I wonder why when I scale the model to a different size the bounding sphere doesn't end up a different size as well.
I searched the source code, and found getTightBounds in NodePath_extensions.py. It seems to just be an accessor for NodePath.calcTightBounds, which is in the API:
Description: Calculates the minimum and maximum vertices of all Geoms at this NodePath's bottom node and below. This is a tight bounding box; it will generally be tighter than the bounding volume returned by get_bounds() (but it is more expensive to compute). The return value is true if any points are within the bounding volume, or false if none are.
I can't help noticing that the scene without characters (run terrain.py) gets 75fps, while the same scene with 10 characters (scene.py) gets 10-15fps. A bit worrying.
Oh, I changed a couple of other things. Tweaked the size of collision spheres on trees and the maximum steering force for characters in scene.py, seems quite good for running around the trees now.
-
chombee
-
- Posts: 244
- Joined: Fri Jan 13, 2006 10:09 am
by Liquid7800 » Mon May 14, 2007 8:59 am
Great work chombee, and thanks for sharing!
Interesting, I don't find this NodePath.getTightBounds function that you used anywhere in the online documentation on this site, or by running Python's help function on NodePath.
I had wondered that myself, when I was working on the eggNbowl physics demo in this forum. ynjh_jo, kindy mentioned that it is: getTightBounds is a method in Panda, find it in pandac\libpandaModules.py. .......getTightBounds returns the tight bounds of a geometry under the given node, by iterating through the vertices to find the outermost vertices. It respects the node's transformation, and the result is in render coordinate space. For example, say you have a cube of 1,1,1 in size. If you change it's heading to 45, you would get (1.41421, 1.41421, 1) bounds, the AABB.
Hope this sends you in the right direction
-

Liquid7800
-
- Posts: 140
- Joined: Mon Feb 19, 2007 1:22 am
by ynjh_jo » Mon May 14, 2007 11:47 am
chombee wrote:I wonder why when I scale the model to a different size the bounding sphere doesn't end up a different size as well.
The stored radius in the Python tag is based on the bounds of the default scale. If you'd like to scale each tree randomly, why didn't you multiply the radius by it's parent's randomized scale ?
- Code: Select all
if models.has_key(path): model = models[path].copyTo(parent) scale=0.75+random.random()/2 model.setScale(scale) model.setPythonTag('radius',model.getPythonTag('radius')*scale)
correction about the result of tight bounds in the quote above :
it's not in render coord space, but in the node's parent's coord space.
about the crawling performance :
it must due to the abundant coll spheres which are packed under a single flat collision node structure. Then they must be spatially splitted apart.
-

ynjh_jo
-
- Posts: 1795
- Joined: Tue Apr 18, 2006 12:41 am
- Location: Malang, Indonesia
-
by chombee » Mon May 14, 2007 3:45 pm
Update (code only, download assets above): http://chombee.panda3dprojects.com/Pand ... v63.tar.gz
Run pandaSteer.py to see the new stuff.
* Added a pathfinding steering behaviour. Characters can follow a pre-defined path and get round obstacles and other characters that intersect the path
* Added a non-penetration constraint. Even if steering fails to avoid an obstacle or collision, characters will never, ever overlap with obstacles or other characters, instead they will slide along each other. It's much less noticeable than overlapping on the rare occasions that steering fails to avoid a collision, and it prevents weird stuff like characters getting stuck inside obstacles. Currently only works with spherical objects.
* Characters now complain or apologise to eachother when they collide!
The pathfinding plugin is using LineSegs to draw the paths so you can see what's happening. But I haven't had time to get it to nicely undraw the paths when you move to another plugin then redraw them when you move back yet.
-
chombee
-
- Posts: 244
- Joined: Fri Jan 13, 2006 10:09 am
by chombee » Tue May 15, 2007 12:58 pm
Another code only revision: http://chombee.panda3dprojects.com/Pand ... v65.tar.gz
* The non-penetration constraint now works in scene.py as well as pandaSteer.py. I realised when I activated it in scene.py that, because it was using my own little sphere-sphere collision detection and looping over every sphere in the scene in Python, it destroyed the framerate. So I had to rewrite the function to use Panda's collision detection instead. Which was more difficult than expected. So many into and from masks flying around. For some reason it sort of vibrates characters along obstacles now instead of smoothly sliding, which is not as nice as before, but at least it doesn't seem to affect the framerate.
* Also totally fixed up the placing of collision spheres over trees of different sizes.
Still haven't done anything about the 10fps framerate in scene.py. I'm thinking that in pandaSteer.py, the plugins with 10-12 actors run at 12-17fps sort of thing. The ones with 2 or 3 actors get 50-75fps. scene.py has 10 actors (I think) plus 4 terrain models instead of one, all those trees, sea and skybox, and it's getting 10fps. Perhaps not so surprising? I have a bad feeling it's the actors that are slowing everything down.
ynjh_jo: I've been thinking about removing the efficient scene graph structuring you built into the terrain generator and instead just saving the whole terrain, trees and collision spheres and all, to an egg, then running it through the egg-octree function someone posted on this forum. Think it would help?
ynjh_jo:
The stored radius in the Python tag is based on the bounds of the default scale
See, I thought that because - Code: Select all
bounds=model.getTightBounds()
comes after - Code: Select all
model.setScale(scale)
, the bounds retrieved would be the bounds of the scaled model. And that does in fact seem to be the case. The problem seems to have been that the block of code that does the setPythonTag is only called once per model. Once the tree model is loaded the first time, another block of code that uses copyTo is executed for every other tree. (the two blocks form an if/else statement in terrain.py/loadModel). Here's the function now (works nicely): - Code: Select all
models = {} # dict of {pathToModel:model}
def setRadiusTag(model): """Set a tag on the given model storing the models XY radius (ignoring how short or tall it is in the Z dimension). This radius tag can be retrieved later to (for example) create a collision sphere that will bound the model Arguments: model -- the model to tag """ # Get the two points (in a list) that define the axis-aligned bounding # box of the scaled model. bounds=model.getTightBounds() # Now subtract the two, giving a vector from one to the other, the # length of which is the diameter of the aabb vector=(bounds[1]-bounds[0]) # Take the greatest of the X and Y components of this vector, ignoring # the Z component, and halve it go get the X/Y radius of the aabb radius=max(vector[0],vector[1])*.5 # Store the radius in a tag attached to the model model.setPythonTag('radius',radius)
def loadModel(path,parent): """Load a model from the file given by path, parent it to the given parent node and return the NodePath to the newly loaded model. Maintains a global dictionary of loaded models and if a model if called twice for the same model the model is instanced instead of being loaded again. """ global models if models.has_key(path): model = models[path].copyTo(parent) scale = 0.75+random.random()/2 model.setScale(scale) setRadiusTag(model) else: modelRoot = loader.loadModelCopy(path) # New models are loaded in a non-standard way to allow flattenStrong # to work effectively over them. model = P.NodePath('model') scale = 0.75+random.random()/2 model.setScale(scale) modelRoot.getChildren().reparentTo(model) model.reparentTo(parent) setRadiusTag(model) models[path] = model return model
-
chombee
-
- Posts: 244
- Joined: Fri Jan 13, 2006 10:09 am
by mavasher » Tue May 15, 2007 7:08 pm
Great work Chombee,
This is coming together nicely. I've been having the same fps problems you describe.
I think it is the Actor class. Could be wrong though.
Also, just a tip, the trees tend to line up in grids. It seems like you could add a tiny random factor for placement of the tree model within the grid cell. This may make it harder for the characters to negotiate the forests though. Maybe that's why you kept them in a strict grid.
But again great work.
-

mavasher
-
- Posts: 294
- Joined: Thu Feb 08, 2007 10:32 am
- Location: Texas
by ynjh_jo » Tue May 15, 2007 8:19 pm
Hey, in my last snippet above, for every (already loaded) tree, I only update the tag to respect the random scale. And now you end up with calculating the bounds for each of them, it means : thousand times for exactly the same model. If your tree is built of a lot more vertices, you'd halt the loading time.
chombee wrote:ynjh_jo: I've been thinking about removing the efficient scene graph structuring you built into the terrain generator and instead just saving the whole terrain, trees and collision spheres and all, to an egg, then running it through the egg-octree function someone posted on this forum. Think it would help?
Sure, try everything possible.
-

ynjh_jo
-
- Posts: 1795
- Joined: Tue Apr 18, 2006 12:41 am
- Location: Malang, Indonesia
-
by chombee » Thu May 17, 2007 9:29 am
This is coming together nicely. I've been having the same fps problems you describe.
I think it is the Actor class. Could be wrong though.
On the other hand, each character in PandaSteer has three CollisionSolids attached: a tube, a sphere, and a ray. And they're colliding with a lot of stuff: the spheres of other characters, the spheres around each of the couple of hundred or so trees, and the many quads of the terrain models. So it may not be the Actor class that is slow, but all the collision detection associated with each actor in PandaSteer.
I'll have a go at improving the collision efficiency, though I don't know much about it, I think the egg-octree code might be good for it, and it might be possible to get rid of the CollisionRays entirely and collide the spheres against the terrain instead.
-
chombee
-
- Posts: 244
- Joined: Fri Jan 13, 2006 10:09 am
by mavasher » Thu May 17, 2007 2:44 pm
That's all true.
The collision against the terrain seems a little overkill to me. Can't you just pass the Z value from the terrain to the character. I used this method in the minimap island. Or do you have a special reason to use collision detection? Using the current system every character collides with the terrain every frame. It's a lot of potential collisions buts it's also just a lot of actual collisions, the characters each have to cycle through all the collisions and find which one is theirs. That's a lot of processing.
-

mavasher
-
- Posts: 294
- Joined: Thu Feb 08, 2007 10:32 am
- Location: Texas
by chombee » Thu May 17, 2007 3:19 pm
Trouble is, I'd have to do some sort of interpolation to get the Z-value at any particular point on the terrain. The terrain is made out of triangles, so I'd need a function that, given an (X,Y), would:
* determine which triangle of the terrain the position lies in
* determine how close to each vertex of the triangle the position is
* interpolate between the three vertices to figure out the height at the position and return it
I didn't know how to do that off the top of my head so I used Panda instead. But yeah if that could be done efficiently it would probably be great, because the terrain could be removed from the collision system entirely. And it'd probably be more robust too -- using a CollisionRay with a CollisionHandlerFloor seems to result in characters falling through the terrain sometimes.
Did you have to solve the same interpolating between three vertices problem in your island demo? Do you have some code for it? I don't suppose it would be too difficult. I would look at your code myself but I have to post this and run right now.
-
chombee
-
- Posts: 244
- Joined: Fri Jan 13, 2006 10:09 am
by mavasher » Thu May 17, 2007 3:58 pm
Well, I was using Panda'a heightfield so there was a function for interpolating. It just did it on its own.
Here's the part of the code I used. I'm sure you have this somewhere:
- Code: Select all
def Elevation(self,objectx,objecty): ele = self.mHeightFieldTesselator.getElevation(objectx/self.scale,-objecty/self.scale) return ele
so every frame the characters just referenced the island's Elevation function and set their Z to the value that Elevation returned.
I think you'd need to write something similar if you wanted to do this.
I think the trick is to make sure you are only using a limited number of lines of code per frame. for loops are killers here because they could potentially be very large especially when every character has it's own task.
-

mavasher
-
- Posts: 294
- Joined: Thu Feb 08, 2007 10:32 am
- Location: Texas
by madprocessor » Wed Jun 06, 2007 2:54 pm
HI there,
just tried pandasteer but i get some errors about models missing:
where can i get them?
greetz
E:\Panda3D-1.3.2\samples\PandaSteer2>ppython pandaSteer.py
DirectStart: Starting the game.
Warning: DirectNotify: category 'Interval' already exists
Known pipe types:
wglGraphicsPipe
(3 aux display modules not yet loaded.)
:util(warning): Adjusting global clock's real time by 0.648984 seconds.
Instantiating plugin from <module '1_seekAndFlee' from 'plugins\1_seekAndFlee.pyc'>
Instantiating plugin from <module '2_pursueAndEvade' from 'plugins\2_pursueAndEvade.pyc'>
Instantiating plugin from <module '3_arrive' from 'plugins\3_arrive.pyc'>
Instantiating plugin from <module '4_wander' from 'plugins\4_wander.pyc'>
Instantiating plugin from <module '5_follow' from 'plugins\5_follow.pyc'>
Instantiating plugin from <module '6_obstacleAvoidance' from 'plugins\6_obstacleAvoidance.pyc'>
Instantiating plugin from <module '7_collisionAvoidance' from 'plugins\7_collisionAvoidance.pyc'>
Instantiating plugin from <module '8_combinedAvoidance' from 'plugins\8_combinedAvoidance.pyc'>
Instantiating plugin from <module '9_pathFollowing' from 'plugins\9_pathFollowing.pyc'>
:loader(error): Couldn't load file models/ralph: not found on model path (which is currently: ".;/e/Panda3D-1.3.2/etc/..;/e/Panda3D-1.3.2/etc/../model
s")
Traceback (most recent call last):
File "pandaSteer.py", line 268, in ?
p = PandaSteer()
File "pandaSteer.py", line 161, in __init__
self.restart()
File "pandaSteer.py", line 219, in restart
avoidObstacles=False,avoidVehicles=False)
File "/home/s0094060/sync/svn-clean/PandaSteer2/character.py", line 75, in __init__
File "E:\Panda3D-1.3.2\direct\src\actor\Actor.py", line 164, in __init__
self.loadModel(models, copy = copy)
File "E:\Panda3D-1.3.2\direct\src\actor\Actor.py", line 1358, in loadModel
raise StandardError, "Could not load Actor model %s" % (modelPath)
StandardError: Could not load Actor model models/ralph
-
madprocessor
-
- Posts: 1
- Joined: Wed Jun 06, 2007 2:47 pm
Return to Code Snippets
Who is online
Users browsing this forum: No registered users and 0 guests
| | |