hkUint16 DestructibleHierarchy::getLookupIndexOfNewDestructibleNode(DestructibleHierarchy* hierarchy, int nodeIdxInDestructibleHierarchy) { HK_ASSERT2(0xad678bad, s_nodeInfos, "Array not created."); if (s_nodeInfos->isEmpty()) { // dummy node, so that index of valid nodes in non-zero s_nodeInfos->expandOne(); } unsigned int lookupIdx = s_nodeInfos->getSize(); NodeInformation& info = s_nodeInfos->expandOne(); info.m_destructibleHierarchy = hierarchy; info.m_nodeIdx = nodeIdxInDestructibleHierarchy; HK_ASSERT2(0xad6288dd, s_nodeInfos->getSize() <= (1<<16), "Too many destructible nodes in the lookup table -- we only have 16 bits for the index into the table" ); return hkUint16(lookupIdx); }
hkpMoppBvTreeShape* RoundTrackDemo::createMoppShape() { // // Create the vertices (a "heightfield" of triangles) // { const float borderHeight = 5.0f; const hkReal radius = 500.0f; const hkReal width = 55.0f; const hkReal jumps = 0.15f; const hkReal bendsFrequency = 10.0f; const hkReal bendsSize = 60.0f; { for(int i = 0; i < SIDEA; i++) { for (int j = 0; j < SIDEB; j++ ) { float h = (hkMath::cos(0.2f*((hkReal)j + i)) + 0.5f * hkMath::sin( 0.2f*2.0f * i)); h = h * h * h * h *h * h - 6; h *= jumps; // // Now bend the track in a circle // hkReal angle = i / float(SIDEA) * 6.32f; float si = hkMath::sin( angle ); float co = hkMath::cos( angle ); int j2 = j-1; if ( j2<0 ) j2++; if ( j2 >= SIDEB - 2) j2--; float sj = j2 / float(SIDEB - 2); float bends = bendsSize * hkMath::sin( angle * bendsFrequency ) * hkMath::sin( angle * bendsFrequency * 0.34f ); float x = si * (radius + sj * width + bends) + radius; float y = co * (radius + sj * width + bends); m_vertices[(i * SIDEB + j) * 3 + 0] = x; m_vertices[(i * SIDEB + j) * 3 + 1] = h; m_vertices[(i * SIDEB + j) * 3 + 2] = y; } } } // // Add a border // { for(int i = 0; i < SIDEA; i++) { m_vertices[ (i * SIDEB + 0 ) * 3 + 1] = borderHeight; m_vertices[ (i * SIDEB + SIDEB-1) * 3 + 1] = borderHeight; } } } // // Create the triangles // { hkUint16 corner = 0; int index = 0; for(int i = 0; i < SIDEA - 1; i++) { for (int j = 0; j < SIDEB - 1; j++ ) { m_indices[index] = hkUint16(corner); m_indices[index + 1] = hkUint16(corner + 1); m_indices[index + 2] = hkUint16(corner + SIDEB); m_indices[index + 3] = hkUint16(corner + 1); m_indices[index + 4] = hkUint16(corner + SIDEB); m_indices[index + 5] = hkUint16(corner + SIDEB + 1); index += 6; corner++; } corner++; } } hkpMeshShape* meshShape = new hkpFastMeshShape( ); meshShape->setRadius(0.05f); { hkpMeshShape::Subpart part; part.m_vertexBase = m_vertices; part.m_vertexStriding = sizeof(float) * 3; part.m_numVertices = NUM_VERTICES; part.m_indexBase = m_indices; part.m_indexStriding = sizeof( hkUint16 ) * 3; part.m_numTriangles = NUM_TRIANGLES; part.m_stridingType = hkpMeshShape::INDICES_INT16; meshShape->addSubpart( part ); } hkpMoppCompilerInput mci; hkpMoppCode* code = hkpMoppUtility::buildCode( meshShape , mci); hkpMoppBvTreeShape* moppShape = new hkpMoppBvTreeShape(meshShape, code); code->removeReference(); meshShape->removeReference(); return moppShape; }
void FlatLand::setupVertexAndTriangleData() { // // Create the vertices (a "heightfield" of triangles) // { const float borderHeight = getBorderHeight(); { for(int i = 0; i < m_side; i++) { for (int j = 0; j < m_side; j++ ) { float h = getHeight( i, j ); m_vertices[(i * m_side + j) * 4 + 0] = i * 1.0f - m_side * 0.5f; m_vertices[(i * m_side + j) * 4 + 1] = h; m_vertices[(i * m_side + j) * 4 + 2] = j * 1.0f - m_side * 0.5f; m_vertices[(i * m_side + j) * 4 + 3] = 0.0f; // we need to set this to avoid denormals on P4 } } } // // Add a border // { for(int i = 0; i < m_side; i++) { m_vertices[ ( i * m_side + 0 ) * 4 + 1] = borderHeight; m_vertices[ ( i * m_side + m_side-1) * 4 + 1] = borderHeight; m_vertices[ ( (m_side-1) * m_side + i ) * 4 + 1] = borderHeight; m_vertices[ (i ) * 4 + 1] = borderHeight; } } } // // Create the triangles // { hkUint16 corner = 0; int index = 0; for(int i = 0; i < m_side - 1; i++) { for (int j = 0; j < m_side - 1; j++ ) { m_indices[index] = hkUint16(corner); m_indices[index + 1] = hkUint16(corner + 1); m_indices[index + 2] = hkUint16(corner + m_side); // m_indices[index + 3] Dummy m_indices[index + 4] = hkUint16(corner + 1); m_indices[index + 5] = hkUint16(corner + m_side + 1); m_indices[index + 6] = hkUint16(corner + m_side); // m_indices[index + 7] Dummy index += 8; corner++; } corner++; } } }
void TowerLand::setupVertexAndTriangleData() { // // Create the vertices (a "heightfield" of triangles) // { const float borderHeight = getBorderHeight(); { for(int i = 0; i < m_side; i++) { for (int j = 0; j < m_side; j++ ) { float h = getHeight( i, j ); m_vertices[ (i * m_side + j) * 4 + 0 ] = ((i - m_side * 0.5f) / m_side) * m_size; m_vertices[ (i * m_side + j) * 4 + 1 ] = h; m_vertices[ (i * m_side + j) * 4 + 2 ] = ((j - m_side * 0.5f) / m_side) * m_size - ( (i%2) * m_shift); m_vertices[ (i * m_side + j) * 4 + 3 ] = 0.0f; // we need to set this to avoid denormals on P4 } } } // // Add a border // { for(int i = 0; i < m_side; i++) { m_vertices[ (i * m_side + 0 ) * 4 + 1] = borderHeight; m_vertices[ (i * m_side + m_side-1) * 4 + 1] = borderHeight; m_vertices[ ( (m_side-1) * (m_side-1) + i ) * 4 + 1] = borderHeight; m_vertices[ (i ) * 4 + 1] = borderHeight; } } } // // Create the triangles // { hkUint16 corner = 0; int index = 0; for(int i = 0; i < m_side - 1; i++) { for (int j = 0; j < m_side - 1; j++ ) { m_indices[index] = hkUint16(corner); m_indices[index + 1] = hkUint16(corner + 1); m_indices[index + 2] = hkUint16(corner + m_side); m_indices[index + 3] = 0; // padding needed for spus m_indices[index + 4] = hkUint16(corner + 1); m_indices[index + 5] = hkUint16(corner + m_side + 1); m_indices[index + 6] = hkUint16(corner + m_side); m_indices[index + 7] = 0; // padding needed for spus index += 8; corner++; } corner++; } } }
void hkFlattenShapeHierarchyUtil::getLeafShapesFromShape(const hkpShape* shape, const hkTransform& transform, const hkBool isFixedBody, hkArray<hkpExtendedMeshShape::TrianglesSubpart>& trianglePartsOut, hkArray<hkpConvexShape*>& convexShapesOut, hkArray<hkpShape*>& otherShapesOut) { const hkpShapeType type = shape->getType(); hkTransform newTransform; const hkpShape* childShape = HK_NULL; hkUlong userData = HK_NULL; switch(type) { case HK_SHAPE_LIST: case HK_SHAPE_CONVEX_LIST: { const hkpShapeContainer* container = shape->getContainer(); hkpShapeContainer::ShapeBuffer buffer; HK_ASSERT2(0xad67da22, 0 == (0xffff0000 & hkUlong(shape->getUserData())), "We're dropping a non-zero lookupIndex from user data."); hkUint16 materialId = hkUint16(0xffff & hkUlong(shape->getUserData())); for (hkpShapeKey key = container->getFirstKey(); key != HK_INVALID_SHAPE_KEY; key = container->getNextKey(key)) { const hkpShape* child = container->getChildShape(key, buffer); if (materialId && 0 == (0xffff & hkUlong(child->getUserData())) ) { // no material id for the child -- copy it hkUlong childData = hkUlong(child->getUserData()) | materialId; // Warning: modifying the const input hkpShape* const_cast<hkpShape*>(child)->setUserData(childData); } //HK_ASSERT2(0xad6777dd, isFixedBody || !isLeafShape(child), "A child of a list shape cannot be a terminal node. You must use a transform shape in between." ); getLeafShapesFromShape(child, transform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut); } } break; case HK_SHAPE_TRANSFORM: { const hkpTransformShape* transformShape = static_cast<const hkpTransformShape*>(shape); newTransform.setMul(transform, transformShape->getTransform()); childShape = transformShape->getChildShape(); userData = hkUlong(transformShape->getUserData()); } break; case HK_SHAPE_CONVEX_TRANSFORM: { const hkpConvexTransformShape* convexTransformShape = static_cast<const hkpConvexTransformShape*>(shape); newTransform.setMul(transform, convexTransformShape->getTransform()); childShape = convexTransformShape->getChildShape(); userData = hkUlong(convexTransformShape->getUserData()); } break; case HK_SHAPE_CONVEX_TRANSLATE: { const hkpConvexTranslateShape* convexTranslateShape = static_cast<const hkpConvexTranslateShape*>(shape); hkTransform localTransform( static_cast<const hkRotation&>(hkRotation::getIdentity()), convexTranslateShape->getTranslation() ); newTransform.setMul(transform, localTransform); childShape = convexTranslateShape->getChildShape(); userData = hkUlong(convexTranslateShape->getUserData()); } break; case HK_SHAPE_BV_TREE: { const hkpBvTreeShape* bvTreeshape = static_cast<const hkpBvTreeShape*>(shape); HK_ASSERT2(0xad67da22, 0 == (0xffff0000 & hkUlong(bvTreeshape->getUserData())), "We're dropping a non-zero lookupIndex from user data."); const hkpShapeContainer* container = bvTreeshape->getContainer(); for (hkpShapeKey key = container->getFirstKey(); key!= HK_INVALID_SHAPE_KEY; key = container->getNextKey(key)) { hkpShapeContainer::ShapeBuffer buffer; const hkpShape* child = container->getChildShape(key, buffer); const hkpShapeType childType = child->getType(); if ((childType == HK_SHAPE_LIST) || (childType == HK_SHAPE_CONVEX_LIST)) { getLeafShapesFromShape(child, transform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut); } } break; } case HK_SHAPE_MOPP: { const hkpMoppBvTreeShape* bvTreeshape = static_cast<const hkpMoppBvTreeShape*>(shape); // HK_ASSERT2(0xad67da22, 0 == (0xffff0000 & hkUlong(bvTreeshape->getUserData())), "We're dropping a non-zero lookupIndex from user data."); getLeafShapesFromShape(bvTreeshape->getShapeCollection(), transform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut); break; } default: { //HK_ASSERT2(0xad67ddaa, isFixedBody, "A child of a list was attached without an intermediate transform shape. This is not handled."); // We can get simple shapes without transforms when processing fixed bodies. We do add a hkpConvexTransformShape as usual then ... childShape = shape; newTransform = transform; userData = hkUlong(shape->getUserData()); //HK_ASSERT2(0XAD678D8D, 0 == (userData & 0xffff0000), "Userdata of a fixed body (other than the one fixed uber body) has a non-zero destructible info index."); } break; } if (HK_NULL != childShape) { hkBool leafDone = false; if (hkOneFixedMoppUtil::isTerminalConvexShape(childShape)) { // Create new transform shape to wrap the child terminal shape hkpConvexTransformShape* newConvexTransformShape = new hkpConvexTransformShape(static_cast<const hkpConvexShape*>(childShape), newTransform); newConvexTransformShape->setUserData( userData ); HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & hkUlong(childShape->getUserData())) || (0xffff0000 & userData) == (0xffff0000 & hkUlong(childShape->getUserData())), "We're dropping a non-zero user data."); HK_ASSERT2(0xad67da24, 0 == (0xffff & hkUlong(childShape->getUserData())) || (0xffff & userData) == (0xffff & hkUlong(childShape->getUserData())), "Materials differ in the terminal shape and its wrapping hkpTransformShape."); // put this transform on the shapesOut list convexShapesOut.pushBack(newConvexTransformShape); leafDone = true; } else if (isLeafShape(childShape)) { // It's not a terminal(leaf?) convex shape, but it might be a mesh, or indeed a simplemesh. // It's most likely to be a storagemesh, but we can't assume that, so check vtable: const hkClass* childShapeClass = hkBuiltinTypeRegistry::getInstance().getVtableClassRegistry()->getClassFromVirtualInstance(childShape); if( hkpMeshShapeClass.isSuperClass(*childShapeClass) ) { const hkpMeshShape* mesh = static_cast<const hkpMeshShape*>(childShape); // Confirm vertex data not shared, see below #if defined(HK_DEBUG) { for(int i = 0; i < mesh->getNumSubparts(); i++) { const hkpMeshShape::Subpart& meshSubPartI = mesh->getSubpartAt(i); for(int j = i+1; j < mesh->getNumSubparts(); j++) { const hkpMeshShape::Subpart& meshSubPartJ = mesh->getSubpartAt(j); HK_ASSERT2(0x0, meshSubPartI.m_vertexBase != meshSubPartJ.m_vertexBase, "This method can't (currently) collapse chared meshs data as it collpases the transform into the verts\n"); } } } #endif for(int i = 0; i < mesh->getNumSubparts(); i++) { const hkpMeshShape::Subpart& meshSubPart = mesh->getSubpartAt(i); // Now we have the subpart. We can't know if the data pointed to is 'owned' by the mesh (eg. subclass hkpStorageMeshShape) // or 'pointed to' (base class hkpMeshShape) // // We'll just assume here we can 'share' the data by grabbing the pointers... hkpExtendedMeshShape::TrianglesSubpart extendedMeshSubPart; extendedMeshSubPart.m_vertexBase = meshSubPart.m_vertexBase; extendedMeshSubPart.m_vertexStriding = meshSubPart.m_vertexStriding; extendedMeshSubPart.m_numVertices = meshSubPart.m_numVertices; extendedMeshSubPart.m_triangleOffset = meshSubPart.m_triangleOffset; // .. but we'll have to multiply in the transform! This assumes the vertex data is not shared! { for(int j = 0; j < extendedMeshSubPart.m_numVertices ; j++) { hkVector4 v; v(0) = extendedMeshSubPart.m_vertexBase[0 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j]; v(1) = extendedMeshSubPart.m_vertexBase[1 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j]; v(2) = extendedMeshSubPart.m_vertexBase[2 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j]; v.setTransformedPos(transform, v); const_cast<float*>(extendedMeshSubPart.m_vertexBase)[0 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j] = v(0); const_cast<float*>(extendedMeshSubPart.m_vertexBase)[1 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j] = v(1); const_cast<float*>(extendedMeshSubPart.m_vertexBase)[2 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j] = v(2); } } extendedMeshSubPart.m_indexBase = meshSubPart.m_indexBase; extendedMeshSubPart.m_indexStriding = meshSubPart.m_indexStriding; extendedMeshSubPart.m_numTriangleShapes = meshSubPart.m_numTriangles; extendedMeshSubPart.m_stridingType = (meshSubPart.m_stridingType == hkpMeshShape::INDICES_INT16) ? hkpExtendedMeshShape::INDICES_INT16 : hkpExtendedMeshShape::INDICES_INT32; trianglePartsOut.pushBack(extendedMeshSubPart); leafDone = true; } } } if(!leafDone) { HK_WARN(0xad678dda, "An extra hkTransform shape has been inserted into the hierarchy. This might be suboptimal."); // Create new transform shape to wrap the child terminal shape hkpTransformShape* newTransformShape = new hkpTransformShape(childShape, newTransform); newTransformShape->setUserData( userData ); HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & hkUlong(childShape->getUserData())) || (0xffff0000 & userData) == (0xffff0000 & hkUlong(childShape->getUserData())), "We're dropping a non-zero user data."); HK_ASSERT2(0xad67da24, 0 == (0xffff & hkUlong(childShape->getUserData())) || (0xffff & userData) == (0xffff & hkUlong(childShape->getUserData())), "Materials differ in the terminal shape and its wrapping hkpTransformShape."); // put this transform on the shapesOut list otherShapesOut.pushBack(newTransformShape); leafDone = true; } if(!leafDone) { //HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & shape->getUserData()), "We're dropping a non-zero user data."); if ( 0xffff0000 & hkUlong(shape->getUserData()) ) { // copy the destruction info index downwards.. HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & hkUlong(childShape->getUserData())) || (0xffff0000 & userData) == (0xffff0000 & hkUlong(childShape->getUserData())), "We're dropping a non-zero user data."); HK_ASSERT2(0xad67da24, 0 == (0xffff & hkUlong(childShape->getUserData())) || (0xffff & hkUlong(shape->getUserData())) == (0xffff & hkUlong(childShape->getUserData())), "Materials differ in the terminal shape and its wrapping hkpTransformShape."); //HK_WORLD_ACCESS_CHECK(parentBody->getWorld(), HK_ACCESS_RW ); // Warning: we're actually modifying the const hkpShape* passed as an input parameter const_cast<hkpShape*>(childShape)->setUserData( shape->getUserData() ); } getLeafShapesFromShape(childShape, newTransform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut); } } }
hkString TweakerUtils::tweakData(const hkString& memberPath, void* rootData, const hkClass& rootKlass, float offset, const hkReal threshold, FloatTweakType floatTweakType) { if (memberPath.getLength() == 0) return hkString("/"); const hkClass* klass; void* data; hkString classPath = TweakerUtils::getClass(memberPath, rootData, rootKlass, data, klass); hkString memberName = memberPath; if (classPath.getLength() > 0) memberName = memberName.replace(classPath, hkString("")); // deal with arrays int rightBracketIndex = memberName.indexOf( ']' ); int arrayIndex = -1; if ( rightBracketIndex != -1 ) { int leftBracketIndex = memberName.indexOf( '[' ); hkString indexString = memberName.substr( leftBracketIndex + 1, rightBracketIndex - leftBracketIndex - 1 ); arrayIndex = hkString::atoi( indexString.cString() ); memberName = memberName.substr( 0, leftBracketIndex ); } int memberIdx = getMemberIdx(memberName, *klass); if (memberIdx < 0) return classPath; const hkClassMember& member = klass->getMember(memberIdx); void* memberData = static_cast<void*>(static_cast<char*>(data) + member.getOffset()); hkString str; switch (member.getType()) { case hkClassMember::TYPE_REAL : { switch(floatTweakType) { case MULTIPLICATIVE: { hkReal& value = lookupMember<hkReal>(memberData); value *= (value > 0) ? 1.0f + offset : 1.0f - offset; // On 0 snap to +ve or -ve if ( value == 0.0f ) { value = (offset > 0) ? threshold : -threshold; } // Snap to 0 exactly if (hkMath::fabs(value) < threshold) { value = 0.0f; } break; } case ADDITIVE: { hkReal& value = lookupMember<hkReal>(memberData); value += offset; } } } break; case hkClassMember::TYPE_INT32 : { hkInt32& value = lookupMember<hkInt32>(memberData); hkInt32 offsetAsInt = convertTweakerFloatToInt(offset); value += offsetAsInt; } break; case hkClassMember::TYPE_UINT32 : { hkUint32& value = lookupMember<hkUint32>(memberData); hkInt32 offsetAsInt = convertTweakerFloatToInt(offset); value += offsetAsInt; } break; case hkClassMember::TYPE_INT16 : { hkInt16& value = lookupMember<hkInt16>(memberData); hkInt32 offsetAsInt = convertTweakerFloatToInt(offset); value = hkInt16( value + offsetAsInt); } break; case hkClassMember::TYPE_UINT16 : { hkUint16& value = lookupMember<hkUint16>(memberData); hkInt32 offsetAsInt = convertTweakerFloatToInt(offset); value = hkUint16( value + offsetAsInt); } break; case hkClassMember::TYPE_BOOL : { bool& value = lookupMember<bool>(memberData); value = !value; } break; case hkClassMember::TYPE_ENUM : { const hkClassEnum& e = member.getEnumType(); int value = member.getEnumValue(memberData); // Find item with current value int itemIdx = 0; while ( e.getItem(itemIdx).getValue() != value) itemIdx++; itemIdx += (offset > 0) ? 1 : e.getNumItems() -1; itemIdx = itemIdx % e.getNumItems(); member.setEnumValue(memberData, e.getItem(itemIdx).getValue()); } break; case hkClassMember::TYPE_ARRAY : { switch( member.getSubType() ) { case hkClassMember::TYPE_INT32 : { void* ptrAddr = static_cast<void*>(memberData); hkArray<hkInt32>* arrayPtr = static_cast<hkArray<hkInt32>*>( ptrAddr ); (*arrayPtr)[arrayIndex] += (offset > 0) ? 1 : -1; break; } default: { break; } } } break; default: break; } return memberPath; }
hkString TweakerUtils::setReal( const hkString& memberPath, void* rootData, const hkClass& rootKlass, float newValue ) { if (memberPath.getLength() == 0) return hkString("/"); const hkClass* klass; void* data; hkString classPath = TweakerUtils::getClass(memberPath, rootData, rootKlass, data, klass); hkString memberName = memberPath; if (classPath.getLength() > 0) memberName = memberName.replace(classPath, hkString("")); // deal with arrays int rightBracketIndex = memberName.indexOf( ']' ); int arrayIndex = -1; if ( rightBracketIndex != -1 ) { int leftBracketIndex = memberName.indexOf( '[' ); hkString indexString = memberName.substr( leftBracketIndex + 1, rightBracketIndex - leftBracketIndex - 1 ); arrayIndex = hkString::atoi( indexString.cString() ); memberName = memberName.substr( 0, leftBracketIndex ); } int memberIdx = getMemberIdx(memberName, *klass); if (memberIdx < 0) return classPath; const hkClassMember& member = klass->getMember(memberIdx); void* memberData = static_cast<void*>(static_cast<char*>(data) + member.getOffset()); hkString str; switch (member.getType()) { case hkClassMember::TYPE_REAL : { hkReal& value = lookupMember<hkReal>(memberData); value = newValue; } break; case hkClassMember::TYPE_INT32 : { hkInt32& value = lookupMember<hkInt32>(memberData); value = hkInt32(newValue); } break; case hkClassMember::TYPE_UINT32 : { hkUint32& value = lookupMember<hkUint32>(memberData); value = hkUint32(newValue); } break; case hkClassMember::TYPE_INT16 : { hkInt16& value = lookupMember<hkInt16>(memberData); value = hkInt16(newValue); } break; case hkClassMember::TYPE_UINT16 : { hkUint16& value = lookupMember<hkUint16>(memberData); value = hkUint16(newValue); } break; case hkClassMember::TYPE_BOOL : { bool& value = lookupMember<bool>(memberData); value = (newValue!=0.0f); } break; case hkClassMember::TYPE_ENUM : { // for backward compatibility we clear the data on zero, otherwise do nothing to enums if ( newValue == 0.0f ) { const hkClassEnum& e = member.getEnumType(); member.setEnumValue(memberData, e.getItem(0).getValue()); } } break; case hkClassMember::TYPE_ARRAY: { switch( member.getSubType() ) { case hkClassMember::TYPE_REAL : { void* ptrAddr = static_cast<void*>(memberData); hkArray<hkReal>* arrayPtr = static_cast<hkArray<hkReal>*>( ptrAddr ); (*arrayPtr)[arrayIndex] = newValue; } break; case hkClassMember::TYPE_INT32 : { void* ptrAddr = static_cast<void*>(memberData); hkArray<hkInt32>* arrayPtr = static_cast<hkArray<hkInt32>*>( ptrAddr ); (*arrayPtr)[arrayIndex] = static_cast<hkInt32>(newValue); } break; default: break; } } break; default: break; } return memberPath; }
// Generate a rough terrain HK_FORCE_INLINE hkReal getHeightAtImpl(int x, int z) const { // Lookup data and return a float // We scale the data artifically by 5 to make it look interesting return hkReal(m_data[x * m_zRes + z]) / hkReal(hkUint16(-1)) * 2048.0f - 1024.0f; }