Solved:Weard vertex buffer result after getting mesh info.

Gurrier

10-05-2010 16:07:05

EDIT: the code that Dermont provided is correct. I'll post my code here to just if someone wants to grab it.

Hey guys, a few days ago I needed more than just AABB raycasting. So I started converting the code from the ogre3D wiki to python:
http://89.151.96.106/wiki/index.php/Raycasting_to_the_polygon_level_(Mogre)
this is the c++ version:
http://89.151.96.106/wiki/index.php/Raycasting_to_the_polygon_level

EDIT: I actually had this code... this is it. Was in the physx Demo app.

But now for some reason when I get back my Vertice list the list is allways:
00:Vector3(0, 0, 0)
01:Vector3(-50, -50, -50)
02:Vector3(-50, 50, -50)
03:Vector3(50, 50, -50)
04:Vector3(50, -50, -50)
05:Vector3(-50, -50, 50)
06:Vector3(50, -50, 50)
07:Vector3(50, 50, 50)
08:Vector3(-50, 50, 50)
09:Vector3(-50, -50, -50)
10:Vector3(50, -50, -50)
11:Vector3(50, -50, 50)
12:Vector3(-50, -50, 50)
13:Vector3(50, -50, -50)
14:Vector3(50, 50, -50)
15:Vector3(50, 50, 50)
16:Vector3(50, -50, 50)
17:Vector3(50, 50, -50)
18:Vector3(-50, 50, -50)
19:Vector3(-50, 50, 50)
20:Vector3(50, 50, 50)
21:Vector3(-50, 50, -50)
22:Vector3(-50, -50, -50)
23:Vector3(-50, -50, 50)
24:Vector3(-50, 50, 50)

Even on different meshes, on different positions

then when I want to do an Intersect() on them:

for i in range(0, len(indices), 3):
dHit = ogre.Math.intersects(
mouseRay,
vertices[indices[i]],
vertices[indices[i+1]],
vertices[indices[i+2]],
True,
False
)


It allways return no hits.

Is there someone that can point me ion the right direction?

Solution:
CGetMeshInfo class:
def getVertices ( vertex_data, transform, convertToNx = True ) :
outbuff = []

# get the start of the element
posElem = vertex_data.vertexDeclaration.findElementBySemantic( ogre.VertexElementSemantic.VES_POSITION )
vbuf = vertex_data.vertexBufferBinding.getBuffer( posElem.getSource() )

# get the start of the actual buffer
vertex = vbuf.lock( ogre.HardwareBuffer.HBL_READ_ONLY )

# what we need is the actual address of the buffer, so we have to check if there's an offset as well
# the is basically what baseVertexPointerToElement does
newaddress = posElem.getOffset() + ogre.castAsInt( vertex ) # note the cast to int to get the address

for i in range ( vertex_data.vertexCount ):
points = ogre.getFloat( ogre.castAsVoidPtr ( newaddress ), 3 ) # note the getFloat and Cast back to a pointer :)

if convertToNx:
vec = CMathUtilities.toNxVec3(transform) * physx.NxVec3(points[0],points[1],points[2])
outbuff.append( physx.NxVec3( points[0], points[1], points[2] ) )
else:
vec = transform * ogre.Vector3(points[0],points[1],points[2])
outbuff.append(tuple((vec.x, vec.y, vec.z)))
newaddress += vbuf.getVertexSize()
vbuf.unlock()
return outbuff

def getIndices ( index_data ) :
outbuff = []

numTris = index_data.indexCount
if numTris == 0 : return outbuff
else : numTris /= 3

ibuf = index_data.indexBuffer

if ibuf.getType() == ogre.HardwareIndexBuffer.IT_32BIT:
Use32Bit = True
else: Use32Bit = False

buffer = ibuf.lock( ogre.HardwareBuffer.HBL_READ_ONLY )
address = ogre.castAsInt ( buffer )

for i in range( numTris ):
if Use32Bit:
val = ogre.getUint32 ( ogre.castAsVoidPtr ( address ), 3 )
address += ibuf.getIndexSize() * 3
else:
val = ogre.getUint16 ( ogre.castAsVoidPtr ( address ), 3 )
address += ibuf.getIndexSize() * 3
outbuff.append( tuple(val))
#outbuff.append( l[0] )
#outbuff.append( l[1] )
#outbuff.append( l[2] )
ibuf.unlock()
return outbuff

def getMeshInfo( entity, convertToNx = True ):
vertices = []
faces = []

if entity.getMesh().sharedVertexData:
vertices += CMeshUtilities.GetVerticies( entity.getMesh().sharedVertexData, entity.getParentSceneNode()._getFullTransform() )

for m in range( entity.getMesh().numSubMeshes ):
sm = entity.getMesh().getSubMesh( m )
if not sm.useSharedVertices:
faces += CMeshUtilities.getIndices ( sm.indexData)
vertices += CMeshUtilities.getVertices ( sm.vertexData, entity.getParentSceneNode()._getFullTransform(), convertToNx )
else:
faces += CMeshUtilities.GetIndicies ( sm.indexData )
return vertices, faces


getExtents = staticmethod( getExtents )
getIndices = staticmethod( getIndices )
getVertices = staticmethod( getVertices )
getMeshInfo = staticmethod( getMeshInfo )


CRayCastFromPoint Class:
def Cast(self, ray_scene_query, mousePos, viewport, camera, pCaller, sceneMan):
mouseRay = camera.getCameraToViewportRay(mousePos.x / viewport.getActualWidth(),
mousePos.y / viewport.getActualHeight())
self.m_SceneManager = sceneMan
print "MouseS: " + str(mouseRay.Direction)
print "MouseE: " + str(mouseRay.Origin)

self.m_pray_scene_query = ray_scene_query

if self.m_pray_scene_query:
self.m_pray_scene_query.Ray = mouseRay
rayresult = self.m_pray_scene_query.execute()
if len(rayresult) <= 0:
return None
else:
return None
closest_distance = -1.0
closest_result = ogre.Vector3.ZERO
vNormal = ogre.Vector3.ZERO
query_result = self.m_pray_scene_query.getLastResults()

for this_result in query_result:
##stop checking if we have found a raycast hit that is closer than all remaining entities
if (closest_distance >= 0.0) and (closest_distance < this_result.distance):
break

##only check this result if its a hit against an entity
if (this_result.movable.MovableType != None) and (this_result.movable.MovableType == "Entity"):
##get the entity to check
pentity = this_result.movable

##mesh data to retrieve
self.m_Vertex_count = 0 ## will get value from CGetMeshInformation()
self.m_Index_count = 0 ## will get value from CGetMeshInformation()
self.m_Vertices = [] ## will get value from CGetMeshInformation()
self.m_Indices = [] ## will get value from CGetMeshInformation()


vertices, indices = CMeshUtilities.getMeshInfo(pentity, False)

ncf = -1 ##new closest_found
##test for hitting individual triangles on the mesh
for i in range(0, len(indices)):
dHit = ogre.Math.intersects(
mouseRay,
vertices[ indices[i][0] ],
vertices[ indices[i][1] ],
vertices[ indices[i][2] ],
True,
False
)

#if it was a hit, check the closest
if dHit.first:
if (closest_distance < 0.0) or (dHit.second < closest_distance):
closest_distance = dHit.second
ncf = i

if ncf > -1:
closest_result = mouseRay.getPoint(closest_distance)
##if you don't need the normal, comment this out; you'll save some CPU cycles.
##first change back the tuple to a vector3
verticesList = []
for i in range(0, len(vertices)):
verticesList.append(ogre.Vector3(vertices[i][0], vertices[i][1], vertices[i][2]))

v1 = verticesList[ncf] - verticesList[ncf + 1]
v2 = verticesList[ncf + 2] - verticesList[ncf + 1]
vNormal = v1.crossProduct(v2)



vertices = None
indices = None


if closest_distance >= 0.0:
pCaller.m_Result = ogre.Vector3(closest_result.x, closest_result.y, closest_result.z)
pCaller.m_ResNormal = vNormal / vNormal.normalise()
"""
##visualizes the result
if not self.m_SceneManager.createSceneNode("marker"):
ent = self.m_SceneManager.createEntity("marker", "Cube.mesh")
node = self.m_SceneManager.getRootSceneNode().createChildSceneNode( "marker" )
node.attachObject(ent)
node.position = pCaller.m_Result
node.scale(0.25,0.25,0.25)
else:
self.m_SceneManager.getSceneNode("marker").position = pCaller.m_Result
"""
return rayresult
else:
return None


init:

##Polygon Level Raycast
self.m_pray_scene_query = self.m_SceneManager.createRayQuery(ogre.Ray(), self.m_SceneManager.WORLD_GEOMETRY_TYPE_MASK)
if not self.m_pray_scene_query:
return False
self.m_pray_scene_query.setSortByDistance(True)
self.m_pray_scene_query.setQueryMask(self.DATACARRIER_MASK)
from Framework.RayCast import CRayCastFromPoint
rayCast = CRayCastFromPoint()
result = rayCast.Cast(self.m_pray_scene_query, self.m_MousePos, self.m_Viewport, self.m_Camera, self, self.m_SceneManager)
print str(result)

dermont

13-05-2010 00:03:13

You probably need to multiply your vertices by the entities parent scene node's transformation matrix, e.g for bullet:


class MeshShapeUtil:
....

@staticmethod
def GetIndicies ( indexData ) :
outbuff = []
numTris = indexData.indexCount
if numTris == 0 : return outbuff
else : numTris /= 3

ibuf = indexData.indexBuffer
if ibuf.getType() == ogre.HardwareIndexBuffer.IT_32BIT:
Use32Bit = True
else: Use32Bit = False

buffer = ibuf.lock(ogre.HardwareBuffer.HBL_READ_ONLY)
address = ogre.castAsInt ( buffer )

for i in range( numTris ):
if Use32Bit:
l = ogre.getUint32 ( ogre.castAsVoidPtr ( address ), 3 )
address += ibuf.getIndexSize() * 3
else:
l = ogre.getUint16 ( ogre.castAsVoidPtr ( address ), 3 )
address += ibuf.getIndexSize() * 3
outbuff.append(tuple(l))
ibuf.unlock()
return outbuff

@staticmethod
def GetVerticies ( vertex_data, transform ) :
outbuff = []

# get the start of the element
posElem = vertex_data.vertexDeclaration.findElementBySemantic(ogre.VertexElementSemantic.VES_POSITION)
vbuf = vertex_data.vertexBufferBinding.getBuffer(posElem.getSource())

# get the start of the actual buffer
vertex = vbuf.lock(ogre.HardwareBuffer.HBL_READ_ONLY)

# what we need is the actual address of the buffer, so we have to check if there's an offset as well
# the is basically what baseVertexPointerToElement does
newaddress = posElem.getOffset() + ogre.castAsInt(vertex) # note the cast to int to get the address

for i in range (vertex_data.vertexCount):
points = ogre.getFloat( ogre.castAsVoidPtr ( newaddress), 3 ) # note the getFloat and Cast back to a pointer :)

vec = transform * ogre.Vector3(points[0],points[1],points[2])
outbuff.append(tuple((vec.x,vec.y,vec.z)))
newaddress += vbuf.getVertexSize()
vbuf.unlock()
return outbuff

#------------------------------------------
# TriMesh Shape
#------------------------------------------
@staticmethod
def createTriMeshShape(entity):
vertices = []
faces = []

if entity.getMesh().sharedVertexData:
vertices += MeshShapeUtil.GetVerticies( entity.getMesh().sharedVertexData, entity.getParentSceneNode()._getFullTransform() )

for m in range(entity.getMesh().numSubMeshes):
sm = entity.getMesh().getSubMesh(m)
if not sm.useSharedVertices:
faces += MeshShapeUtil.GetIndicies ( sm.indexData )
vertices += MeshShapeUtil.GetVerticies ( sm.vertexData, entity.getParentSceneNode()._getFullTransform() )
else:
faces += MeshShapeUtil.GetIndicies ( sm.indexData )

mTriMesh = bullet.btTriangleMesh()
for ind in faces:
v1 = vertices[ind[0]]
v2 = vertices[ind[1]]
v3 = vertices[ind[2]]
b1 = bullet.btVector3(v1[0],v1[1],v1[2])
b2 = bullet.btVector3(v2[0],v2[1],v2[2])
b3 = bullet.btVector3(v3[0],v3[1],v3[2])
#print b1.x(),b1.y(),b1.z()
mTriMesh.addTriangle(b1, b2, b3)

useQuantizedAABB = True
del vertices
del faces

return mTriMesh, bullet.btBvhTriangleMeshShape(mTriMesh, useQuantizedAABB)

Gurrier

13-05-2010 09:42:21

Good point. When I was posting the same problem at the oGre3D Help forum I tought about it and was thinking it didn't look at the scale, position and orientation of his node.

Anyway, going to look into your posted code and see what major differences there are.

Edit: It was that. Thanks for you code. It made it a bit easyer.