void Scene::createBulletTerrain() { Ogre::Terrain* baseTerrain = mTerrainGroup->getTerrain(0, 0); btHeightfieldTerrainShape* hfShape = new btHeightfieldTerrainShape( baseTerrain->getSize(), baseTerrain->getSize(), baseTerrain->getHeightData(), 1, 0, 0, 2, PHY_FLOAT, false); // Min and max height were set to 0 to force the terrain to be completely flat hfShape->setUseDiamondSubdivision(true); // This scale is based on the tutorial, but it may not be true... float metersBetweenVerts = baseTerrain->getWorldSize() / (baseTerrain->getSize() - 1); btVector3 scale(metersBetweenVerts, metersBetweenVerts, 1); hfShape->setLocalScaling(scale); hfShape->setUserPointer((void*) SU_Terrain); btCollisionObject* colObj = new btCollisionObject(); colObj->setCollisionShape(hfShape); colObj->setFriction(0.9); colObj->setRestitution(0.0); colObj->setCollisionFlags(colObj->getCollisionFlags() | btCollisionObject::CF_STATIC_OBJECT | btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT); mSim->getCollisionWorld()->getDynamicsWorld()->addCollisionObject(colObj); mSim->getCollisionWorld()->addShape(hfShape); // Border planes const float px[4] = {-1, 1, 0, 0}; const float py[4] = { 0, 0,-1, 1}; for (int i = 0; i < 4; ++i) { btVector3 vpl(px[i], py[i], 0); btCollisionShape* shp = new btStaticPlaneShape(vpl, 0); shp->setUserPointer((void*) SU_Border); btTransform tr; tr.setIdentity(); tr.setOrigin(vpl * -0.5 * worldSize); btCollisionObject* col = new btCollisionObject(); col->setCollisionShape(shp); col->setWorldTransform(tr); col->setFriction(0.3); //+ col->setRestitution(0.0); col->setCollisionFlags(col->getCollisionFlags() | btCollisionObject::CF_STATIC_OBJECT | btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT); mSim->getCollisionWorld()->getDynamicsWorld()->addCollisionObject(col); mSim->getCollisionWorld()->addShape(shp); } }
void TerrainManager::CreatePhysicsShape(void) { Ogre::TerrainGroup::TerrainIterator ti = mTerrainGroup->getTerrainIterator(); while (ti.hasMoreElements()) { Ogre::Terrain *t = ti.getNext()->instance; LoadTerrainGeometry(t->getMaterialName(), t->getHeightData(), t->getSize(), t->getWorldSize(), t->getMinHeight(), t->getMaxHeight(), t->getPosition()); } }
void ManipulatorTerrain::OnEdit( float dt ) { assert(m_curEditMode != eTerrainEditMode_None); //第0层不能编辑BlendMap,应该从第1层开始 if(m_curEditMode == eTerrainEditMode_Splat && m_curEditLayer == 0) return; Ogre::Terrain* pTerrain = ManipulatorSystem.GetScene()->GetTerrain(); const Vector3 brushPos = m_brush[m_curBrushIndex]->GetPosition(); Vector3 tsPos; pTerrain->getTerrainPosition(brushPos, &tsPos); float brushSizeW, brushSizeH; m_brush[m_curBrushIndex]->GetDimension(brushSizeW, brushSizeH); float worldSize = GetWorldSize(); brushSizeW /= worldSize; brushSizeH /= worldSize; int multiplier; Ogre::TerrainLayerBlendMap* layer = nullptr; if(m_curEditMode == eTerrainEditMode_Deform) { multiplier = pTerrain->getSize() - 1; } else { multiplier = pTerrain->getLayerBlendMapSize(); layer = pTerrain->getLayerBlendMap(m_curEditLayer); } long startx = (long)((tsPos.x - brushSizeW / 2) * multiplier); long starty = (long)((tsPos.y - brushSizeH / 2) * multiplier); long endx = (long)((tsPos.x + brushSizeW / 2) * multiplier); long endy= (long)((tsPos.y + brushSizeH / 2) * multiplier); startx = max(startx, 0L); starty = max(starty, 0L); endx = min(endx, (long)multiplier); endy = min(endy, (long)multiplier); for (long y = starty; y <= endy; ++y) { for (long x = startx; x <= endx; ++x) { float tsXdist = (x / multiplier) - tsPos.x; float tsYdist = (y / multiplier) - tsPos.y; if(m_curEditMode == eTerrainEditMode_Deform) { float* pData = pTerrain->getHeightData(); pData[y*GetMapSize()+x] += 100.0f * dt; } else { float* pData = layer->getBlendPointer(); size_t imgY = multiplier - y; float newValue = pData[imgY*multiplier+x] + dt; newValue = Ogre::Math::Clamp(newValue, 0.0f, 1.0f); pData[imgY*multiplier+x] = newValue; } } } if(m_curEditMode == eTerrainEditMode_Deform) { Ogre::Rect rect(startx, starty, endx, endy); pTerrain->dirtyRect(rect); pTerrain->update(); } else { size_t imgStartY = multiplier - starty; size_t imgEndY = multiplier - endy; Ogre::Rect rect(startx, min(imgStartY,imgEndY), endx, max(imgStartY,imgEndY)); layer->dirtyRect(rect); layer->update(); } }