procedural terrain collision requires vertex normals?

is necessary to manualy setup each normal for a procedural created terrain in order to be able to assign collisions to it?

i’ve been trying hard but there’s no way to succeed in the terrain i created.
you can see the code or download the app in:

https://discourse.panda3d.org/viewtopic.php?t=4408

the only thing this terrain does not have assigned in its vertices are normals, has to be that isnt it?

ufff thanks!
c

No, you don’t specifically need normals. As I recall, my geoMipTerrain worked good with collisions even before it had normals. So, basically all you need to do is call setBitmask on the terrain nodepath (Im not sure how your algorithm works, but you should have a nodepath somewhere, right?) and it should be ready for collision with spheres and rays etc.

mhmm it looks as i have to create one primitive for each triangle in order to attach collision, is that right?
sorry for bothering but is driving me crazy, i can’t advance farther without that…

basically what it happens is that when i make the addVertices(x,y,z), if x!=0 collision dont gets recognized by the picker…

I mean,

this don’t works:

primitives = GeomTriangles( Geom.UHStatic )
for n in range(number):
    primitives.addVertices( n*3,n*3+1,n*3+2 )
primitives.closePrimitive()

this works:

primitives = GeomTriangles( Geom.UHStatic )
for n in range(number):
    primitives.addVertices( 0,n*3+1,n*3+2 )
primitives.closePrimitive()

i post here the complete test code,maybe someone can found the solution to this problem…
the issue is in the line colored in red, this is the correct sentence to construct the mesh, but when testing the pick is always None, if i change it, let’s say i put primitives.addVertices( n2,n2+1,n2+2 ) or primitives.addVertices( 0,n3+1,n*3+2 ) it works…

i’m really lost on that


import direct.directbase.DirectStart
#for the events
from direct.showbase import DirectObject
#for collision stuff
from pandac.PandaModules import *

import Image
from random import *

def fromFile(heightmap):
“”“Generates data from given heightmap image file”""
#open heightmap image
hmap = Image.open(heightmap+".bmp").convert(“L”)
#get heightmap image size
xs,ys = hmap.size
#get divisor
cdiv=10
hdiv=10
#generate data list: [[heightpixel,colorpixel],…] #(hmap.getpixel((x,ys-y-1))/hdiv, hmap.getpixel((x,ys-y-1))/cdiv )
return [[(hmap.getpixel((x,y))/hdiv, hmap.getpixel((x,y))/cdiv ) for y in range(ys)] for x in range(xs)],hmap.size

################################################################################
def makeMesh():
“”" get data from file “”"
data,size = fromFile(“media/hmaps/hmap”) #print self.data
“”" generate a terrain “”"
#set transparency of vertex
def tp(n):
list = [1,1,1,1]
return list
#create vdata

vdata = GeomVertexData('plane',GeomVertexFormat.getV3c4t2() , Geom.UHStatic) # GeomVertexFormat.getV3c4t2()
vertex = GeomVertexWriter(vdata, 'vertex')
normal = GeomVertexWriter(vdata, 'normal')
uv = GeomVertexWriter(vdata, 'texcoord')
color = GeomVertexWriter(vdata, 'color')
#create vertices
number = 0

for x in range(1,len(data)-1):
    for y in range(1,len(data[x])-1):
    #get vertex data
        v1 = Vec3(x,y,data[x][y][0])
        c1 = data[x][y][1]
        v2 = Vec3(x+1,y,data[x+1][y][0])
        c2 = data[x+1][y][1]
        v3 = Vec3(x+1,y+1,data[x+1][y+1][0])
        c3 = data[x+1][y+1][1]
        v4 = Vec3(x,y+1,data[x][y+1][0])
        c4 = data[x][y+1][1]

        c1,c2,c3,c4 = tp(c1),tp(c2),tp(c3),tp(c4) 
        #add vertices
        vertex.addData3f(v1)
        color.addData4f(*c1)  
        uv.addData2f(0,0)
        vertex.addData3f(v2)
        color.addData4f(*c2)
        uv.addData2f(1,0)               
        vertex.addData3f(v3)
        color.addData4f(*c3)
        uv.addData2f(1,1)
        vertex.addData3f(v1)
        color.addData4f(*c1)
        uv.addData2f(0,0)
        vertex.addData3f(v3)
        color.addData4f(*c3)
        uv.addData2f(1,1)
        vertex.addData3f(v4)
        color.addData4f(*c4)
        uv.addData2f(0,1)
        #
        number = number + 2
    
#add triangles  
primitives = GeomTriangles( Geom.UHStatic )
for n in range(0,number):
    [color=red]primitives.addVertices( n*3,n*3+1,n*3+2 )
primitives.closePrimitive()

#make geom
geom = Geom(vdata)
geom.addPrimitive(primitives)

#make geom node
node = GeomNode('planeNode')
node.addGeom(geom)

return node

################################################################################
class Picker(DirectObject.DirectObject):
def init(self):
#setup collision stuff
#traverser
self.picker= CollisionTraverser()
base.cTrav = self.picker
#event
self.queue=CollisionHandlerQueue()
#attach a CollisionRay node to the camera
self.pickerNode=CollisionNode(‘mouseRay’)
self.pickerNP=camera.attachNewNode(self.pickerNode)
self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
self.pickerRay=CollisionRay()
self.pickerNode.addSolid(self.pickerRay)
self.picker.addCollider(self.pickerNP, self.queue)

    #this holds the object that has been picked
    self.pickedObj=None
    self.accept('mouse1', self.printMe)

#this function is meant to flag an object as being somthing we can pick
def makePickable(self,newObj):
newObj.setTag(‘pickable’,‘true’)
print ‘========================’
newObj.ls()
print ‘========================’

#this function finds the closest object to the camera that has been hit by our ray
def getObjectHit(self, mpos): #mpos is the position of the mouse on the screen
self.pickedObj=None #be sure to reset this
self.pickerRay.setFromLens(base.camNode, mpos.getX(),mpos.getY())
self.picker.traverse(render)

  if self.queue.getNumEntries() > 0:
     self.queue.sortEntries()
     self.pickedObj=self.queue.getEntry(0).getIntoNodePath()

     parent=self.pickedObj.getParent()
     
     print self.pickedObj,parent
     
     
     ##self.pickedObj=None
     ## while parent != render:
        ## #if parent.getTag('pickable')=='true':
        ## if parent.getNetTag('pickable')=='true':     
           ## self.pickedObj=parent
           ## return parent
        ## else:
           ## parent=parent.getParent()
  return None

def getPickedObj(self):
    return self.pickedObj

def printMe(self):
    self.getObjectHit( base.mouseWatcherNode.getMouse())
    print self.pickedObj

################################################################################
base.toggleWireframe()

basePlane = makeMesh()
planeNode = NodePath(basePlane)
planeNode.reparentTo(render)
planeNode.setPos(0,0,0)
print planeNode

mousePicker=Picker()
mousePicker.makePickable(planeNode)

run()

Are your polygons facing towards the camera? That is, (n3, n3+1, n*3+2) defines the vertices in a counter-clockwise order?

David

uoooooouu!!!

i just invert the order as u said, from

    primitives.addVertices( n*3,n*3+1,n*3+2 )

i changed to

    primitives.addVertices(n*3+2,n*3+1,n*3)

and now it workkkkkkks !

thanks a lot for the thought drwr :slight_smile:

aldough then -of course-, i wasn’t able to see the mesh,
so i tried with

prim.addVertices(n*3+0,n*3+1,n*3+2)

and now everything is fineeee, like in heaven :slight_smile:

Thanks a lot!
c

one stupid newbie question:

a single CollisionTraverser is enough to manage all collisions in the game isn’t it?

Yes.

David