Better islands

This commit is contained in:
2025-06-26 04:51:35 +03:00
parent 1463a1cde0
commit f58402921f
9 changed files with 324 additions and 402 deletions

View File

@@ -114,7 +114,21 @@ add_custom_command(
# ${CMAKE_BINARY_DIR}/skybox
# COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/resources/debug
# ${CMAKE_BINARY_DIR}/resources/debug
DEPENDS ${CMAKE_SOURCE_DIR}/resources.cfg)
DEPENDS ${CMAKE_SOURCE_DIR}/resources.cfg)
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/resources/terrain/world_map.png
COMMAND unzip -o ${CMAKE_SOURCE_DIR}/world_map.kra mergedimage.png -d ${CMAKE_BINARY_DIR}/world_map
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_BINARY_DIR}/world_map/mergedimage.png
${CMAKE_BINARY_DIR}/resources/terrain/world_map.png
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/world_map
DEPENDS ${CMAKE_SOURCE_DIR}/world_map.kra)
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/resources/terrain/brushes.png
COMMAND unzip -o ${CMAKE_SOURCE_DIR}/brushes.kra mergedimage.png -d ${CMAKE_BINARY_DIR}/brushes
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_BINARY_DIR}/brushes/mergedimage.png
${CMAKE_BINARY_DIR}/resources/terrain/brushes.png
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/brushes
DEPENDS ${CMAKE_SOURCE_DIR}/brushes.kra)
set(SKYBOX_SRC
early_morning_bk.jpg
@@ -179,7 +193,9 @@ add_custom_command(
${CMAKE_SOURCE_DIR}/assets/vroid/jane2-dress.vrm
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
add_custom_target(stage_files ALL DEPENDS ${CMAKE_BINARY_DIR}/resources.cfg ${MATERIALS_OUTPUT})
add_custom_target(stage_files ALL DEPENDS ${CMAKE_BINARY_DIR}/resources.cfg ${MATERIALS_OUTPUT}
${CMAKE_BINARY_DIR}/resources/terrain/world_map.png
${CMAKE_BINARY_DIR}/resources/terrain/brushes.png)
add_custom_target(remove_scenes COMMAND rm -f ${CREATE_SCENES})

View File

@@ -487,6 +487,8 @@ public:
Ogre::Vector3 pos =
mCameraPivot->getPosition() + move * speed * delta;
float y = m_terrain.get_height(pos);
if (y < 0)
y = 0.0f;
pos.y = y;
mCameraPivot->translate(pos - opos);
@@ -590,7 +592,7 @@ public:
}
if (mSunNode->getOrientation().getPitch().valueRadians() > 0)
mScnMgr->setAmbientLight(
Ogre::ColourValue(0.0f, 0.0f, 0.2f, 1.0f));
Ogre::ColourValue(0.1f, 0.1f, 0.4f, 1.0f));
else
mScnMgr->setAmbientLight(
Ogre::ColourValue(0.2f, 0.2f, 0.2f, 1.0f));
@@ -622,6 +624,7 @@ public:
// "InterfaceName", getRenderWindow());
// mScnMgr->setSkyBox(true, "Skybox/Dynamic", 490);
// /* mCamera->getCameraToViewportRay(left, top); */
#if 1
sky = new SkyBoxRenderer(getSceneManager());
bool drawFirst = true;
uint8_t renderQueue = drawFirst ?
@@ -640,6 +643,7 @@ public:
m->load();
m_water.createWater(mCamera);
getRoot()->addFrameListener(&m_water);
#endif
}
void create_entity_node(const Ogre::String &name, int key)
{

BIN
brushes.kra Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 265 KiB

View File

@@ -13,53 +13,290 @@
#include <OgreMaterialManager.h>
#include <OgreTerrainAutoUpdateLod.h>
#include <OgreTerrainPagedWorldSection.h>
#include <OgreBullet.h>
#include <OgreMath.h>
#include <OgreLogManager.h>
#include "terrain.h"
#define ENDLESS_TERRAIN_FILE_PREFIX Ogre::String("EndlessWorldTerrain")
#define ENDLESS_TERRAIN_FILE_SUFFIX Ogre::String("dat")
#define TERRAIN_WORLD_SIZE 12000.0f
#define TERRAIN_SIZE 513
#define HOLD_LOD_DISTANCE 3000.0
#define TERRAIN_WORLD_SIZE 4000.0f
#define TERRAIN_SIZE 129
// #define HOLD_LOD_DISTANCE 3000.0
#define USE_PERLIN_DEFINER 0
template <typename T> T CLAMP(T value, T low, T high)
{
return (value < low) ? low : ((value > high) ? high : value);
}
class FlatTerrainDefiner
: public Ogre::TerrainPagedWorldSection::TerrainDefiner {
: public Ogre::TerrainPagedWorldSection::TerrainDefiner,
public Ogre::FrameListener {
Ogre::SceneManager *mScnMgr;
Ogre::Bullet::DynamicsWorld *mWorld;
struct gen_collider {
Ogre::TerrainGroup *group;
long x;
long y;
};
std::deque<struct gen_collider> collider_queue;
Ogre::Image img, img_noise, img_brushes;
public:
FlatTerrainDefiner(Ogre::SceneManager *scm,
Ogre::Bullet::DynamicsWorld *world)
: Ogre::TerrainPagedWorldSection::TerrainDefiner()
, Ogre::FrameListener()
, mScnMgr(scm)
, mWorld(world)
{
Ogre::Root::getSingleton().addFrameListener(this);
img.load(
"world_map.png",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
img_noise.load(
"terrain.png",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
img_brushes.load(
"brushes.png",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
}
private:
#if 0
float get_terrain_height(const Ogre::Vector2 &worldOffset, int x, int y)
{
revisedValuePoint = (worldOffset + Ogre::Vector2(x, y));
int img_x = revisedValuePoint.x + img.getWidth() / 2;
int img_y = revisedValuePoint.y + img.getHeight() / 2;
float height = 0.0f;
if (img_x < 0 || img_x >= img.getWidth() || img_y < 64 ||
img_y >= img.getWidth())
height = -150.0f;
else {
Ogre::ColourValue color(0, 0, 0, 1);
int m, n;
color = img.getColourAt(img_x, img_y, 0);
float mheight = (color.r - 0.55f) * 120.0f;
height = mheight;
}
return height;
}
#endif
float get_noise_height(const Ogre::Vector2 &worldOffset, int x, int y)
{
int h;
Ogre::Vector2 noisePoint;
struct noise_types {
Ogre::Vector2 noiseOfft;
float noiseMul;
float noiseBias;
float noiseAmp;
};
static struct noise_types noise_pass[] = {
{ { -100.0f, 70.0f }, 10.2f, -0.55f, 5.0f },
{ { -130.0f, 55.0f }, 5.35f, -0.55f, 1.0f }
};
static float noise_values[] = { 0.0f, 0.0f };
for (h = 0; h < (int)sizeof(noise_values) /
(int)sizeof(noise_values[0]);
h++) {
noisePoint = (worldOffset + Ogre::Vector2(x, y) +
noise_pass[h].noiseOfft) *
noise_pass[h].noiseMul;
int noise_x =
(int)(noisePoint.x + img_noise.getWidth() / 2) %
img_noise.getWidth();
int noise_y = (int)(noisePoint.y +
img_noise.getHeight() / 2) %
img_noise.getHeight();
Ogre::ColourValue noise_color =
img_noise.getColourAt(noise_x, noise_y, 0);
noise_values[h] =
(noise_color.r + noise_pass[h].noiseBias) *
noise_pass[h].noiseAmp;
}
return noise_values[0] + noise_values[1];
}
#define BRUSH_SIZE 64
float get_brush_height(int id, int x, int y)
{
int m = 0;
switch (id) {
case 0:
m = 0;
break;
case 1:
m = BRUSH_SIZE;
break;
default:
OgreAssert(false, "bad brush id");
break;
}
return img_brushes.getColourAt(x, y + m, 0).r;
}
float get_base_height(const Ogre::Vector2 &worldOffset, int x, int y)
{
float height = 0.0f;
int world_x = worldOffset.x + x;
int world_y = worldOffset.y + y;
int world_img_x =
world_x + (int)img.getWidth() * BRUSH_SIZE / 2;
int world_img_y =
world_y + (int)img.getHeight() * BRUSH_SIZE / 2;
Ogre::ColourValue color, colorb1, colorb2;
// float d;
int map_img_x = world_img_x / (BRUSH_SIZE);
int map_img_y = world_img_y / (BRUSH_SIZE);
int brush_img_x = world_img_x % BRUSH_SIZE;
int brush_img_y = world_img_y % BRUSH_SIZE;
if (world_img_x < 0 ||
world_img_x >= img.getWidth() * BRUSH_SIZE ||
world_img_y < 0 ||
world_img_y >= img.getWidth() * BRUSH_SIZE) {
height = -1.0f;
goto out;
}
color = img.getColourAt(map_img_x, map_img_y, 0);
colorb1 = img_brushes.getColourAt(brush_img_x,
brush_img_y + BRUSH_SIZE, 0);
colorb2 = img_brushes.getColourAt(brush_img_x, brush_img_y, 0);
// d = Ogre::Math::saturate(color.r - 0.05f);
height = color.r;
out:
return height;
}
public:
void define(Ogre::TerrainGroup *terrainGroup, long x, long y) override
{
#if 0
Ogre::Image img;
img.load(
"terrain.png",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
int terrainSize = terrainGroup->getTerrainSize();
uint16_t terrainSize = terrainGroup->getTerrainSize();
float *heightMap = OGRE_ALLOC_T(float, terrainSize *terrainSize,
MEMCATEGORY_GEOMETRY);
// float *heightMapCollider = OGRE_ALLOC_T(
// float, terrainSize *terrainSize, MEMCATEGORY_GEOMETRY);
Ogre::Vector2 worldOffset(Ogre::Real(x * (terrainSize - 1)),
Ogre::Real(y * (terrainSize - 1)));
float mCycle = 1.0f;
// worldOffset += mOriginPoint;
Ogre::Vector2 worldOrigin =
Ogre::Vector2(img.getWidth(), img.getHeight()) * 0.5f;
float chunk = 128.0f;
Ogre::Vector2 revisedValuePoint;
for (int i = 0; i < terrainSize; i++)
for (int j = 0; j < terrainSize; j++) {
revisedValuePoint =
(worldOffset + Ogre::Vector2(j, i)) /
mCycle;
heightMap[i * terrainSize + j] =
img.getColourAt(j * img.getWidth() /
terrainSize,
i * img.getHeight() /
terrainSize,
0)
.r *
0.2f -
0.1f;
float brush_height0 =
get_brush_height(0, j % BRUSH_SIZE,
i % BRUSH_SIZE) -
0.55f;
float brush_height1 =
get_brush_height(1, j % BRUSH_SIZE,
i % BRUSH_SIZE) -
0.55f;
float mheight =
Ogre::Math::lerp(
brush_height1, brush_height0,
get_base_height(worldOffset, j,
i)) *
120.0f;
float height = mheight;
if (mheight > 0.5f)
height += 2.0f +
get_noise_height(worldOffset,
j, i);
else if (mheight < -0.5f)
height -= 2.0f +
get_noise_height(worldOffset,
j, i);
// height = -2.0f;
heightMap[i * terrainSize + j] = height;
// heightMapCollider[(terrainSize - i - 1) *
// terrainSize +
// j] = height;
}
terrainGroup->defineTerrain(x, y, heightMap);
OGRE_FREE(heightMap, MEMCATEGORY_GEOMETRY);
#endif
terrainGroup->defineTerrain(x, y, -10.0f);
Ogre::LogManager::getSingleton().logError(
"defined terrain at " +
Ogre::StringConverter::toString(x) + " " +
Ogre::StringConverter::toString(y));
// collider_queue.push_back(
// { terrainGroup, x, y, heightMapCollider });
delete[] heightMap;
collider_queue.push_back({ terrainGroup, x, y });
}
bool frameStarted(const Ogre::FrameEvent &evt) override
{
(void)evt;
update();
return true;
}
void update()
{
static bool created = false;
std::deque<struct gen_collider> output;
while (!collider_queue.empty()) {
Ogre::TerrainGroup *group =
collider_queue.front().group;
long x = collider_queue.front().x;
long y = collider_queue.front().y;
Ogre::Terrain *terrain = group->getTerrain(x, y);
Ogre::Vector3 worldPos;
group->convertTerrainSlotToWorldPosition(x, y,
&worldPos);
if (terrain && terrain->getHeightData() &&
terrain->isLoaded() &&
!terrain->isDerivedDataUpdateInProgress()) {
Ogre::LogManager::getSingleton().logError(
"can create collider for " +
Ogre::StringConverter::toString(x) +
" " +
Ogre::StringConverter::toString(y));
float minH = terrain->getMinHeight();
float maxH = terrain->getMaxHeight();
int size = terrain->getSize();
float worldSize = terrain->getWorldSize();
if (!created || true) {
btRigidBody *body =
mWorld->addTerrainRigidBody(
group, x, y);
Ogre::LogManager::getSingleton().logError(
"created rigid body " +
Ogre::StringConverter::toString(
Ogre::Bullet::convert(
body->getWorldTransform()
.getOrigin())));
Ogre::LogManager::getSingleton().logError(
"minHeight " +
Ogre::StringConverter::toString(
minH));
Ogre::LogManager::getSingleton().logError(
"maxHeight " +
Ogre::StringConverter::toString(
maxH));
Ogre::LogManager::getSingleton().logError(
"size " +
Ogre::StringConverter::toString(
size));
Ogre::LogManager::getSingleton().logError(
"world size " +
Ogre::StringConverter::toString(
worldSize));
Ogre::LogManager::getSingleton().logError(
"created collider for " +
Ogre::StringConverter::toString(
x) +
" " +
Ogre::StringConverter::toString(
y));
created = true;
}
collider_queue.pop_front();
} else {
output.push_back(collider_queue.front());
collider_queue.pop_front();
}
}
collider_queue = output;
}
};
@@ -91,19 +328,6 @@ void TerrainSetup::setupTerrain(Ogre::Camera *camera, Ogre::Light *sun,
Ogre::LogManager::getSingleton().setMinLogLevel(Ogre::LML_TRIVIAL);
#if 0
Ogre::Light *l = mScnMgr->createLight("tstLight");
l->setType(Ogre::Light::LT_DIRECTIONAL);
l->setDiffuseColour(ColourValue::White);
l->setSpecularColour(ColourValue(0.4, 0.4, 0.4));
auto ln = mSceneMgr->getRootSceneNode()->createChildSceneNode();
ln->setDirection(Vector3(0.55, -0.3, 0.75).normalisedCopy());
ln->attachObject(l);
mScnMgr->setAmbientLight(Ogre::ColourValue(0.2, 0.2, 0.2));
#endif
mTerrainGroup =
OGRE_NEW Ogre::TerrainGroup(mScnMgr, Ogre::Terrain::ALIGN_X_Z,
TERRAIN_SIZE, TERRAIN_WORLD_SIZE);
@@ -126,14 +350,15 @@ void TerrainSetup::setupTerrain(Ogre::Camera *camera, Ogre::Light *sun,
mTerrainPaging = OGRE_NEW Ogre::TerrainPaging(mPageManager);
mPagedWorld = mPageManager->createWorld();
mTerrainPagedWorldSection = mTerrainPaging->createWorldSection(
mPagedWorld, mTerrainGroup, 300, 500, ENDLESS_PAGE_MIN_X,
mPagedWorld, mTerrainGroup, 300, 800, ENDLESS_PAGE_MIN_X,
ENDLESS_PAGE_MIN_Y, ENDLESS_PAGE_MAX_X, ENDLESS_PAGE_MAX_Y);
#if USE_PERLIN_DEFINER == 1
mPerlinNoiseTerrainGenerator = OGRE_NEW PerlinNoiseTerrainGenerator;
mTerrainPagedWorldSection->setDefiner(mPerlinNoiseTerrainGenerator);
#else
mTerrainPagedWorldSection->setDefiner(OGRE_NEW FlatTerrainDefiner);
mTerrainPagedWorldSection->setDefiner(OGRE_NEW FlatTerrainDefiner(
camera->getSceneManager(), dynamicsWorld));
#endif
mTerrainGroup->freeTemporaryResources();
@@ -156,229 +381,14 @@ void TerrainSetup::setupTerrain(Ogre::Camera *camera, Ogre::Light *sun,
// setupControls();
}
#if 0
void TerrainSetup::setupTerrain(Ogre::Camera *camera)
{
//! [global_opts]
mTerrainGlobals = new Ogre::TerrainGlobalOptions();
//! [global_opts]
mScnMgr = camera->getSceneManager();
#if 0
mEditMarker = m_app->getSceneManager()->createEntity("editMarker",
"sphere.mesh");
#endif
mEditNode = mScnMgr->getRootSceneNode()->createChildSceneNode(
"TerrainEditNode");
// mEditNode->attachObject(mEditMarker);
mEditNode->setScale(0.05, 0.05, 0.05);
#if 0
setupControls();
#endif
// mCameraMan->setTopSpeed(50);
// setDragLook(true);
#if OGRE_PLATFORM != OGRE_PLATFORM_ANDROID
Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(
Ogre::TFO_ANISOTROPIC);
Ogre::MaterialManager::getSingleton().setDefaultAnisotropy(8);
#endif
Ogre::ColourValue fadeColour(0.7, 0.7, 0.8);
//! [linear_fog]
mScnMgr->setFog(Ogre::FOG_LINEAR, fadeColour, 0, 2000, 10000);
//! [linear_fog]
Ogre::LogManager::getSingleton().setMinLogLevel(Ogre::LML_TRIVIAL);
//! [light]
Ogre::Light *l = mScnMgr->createLight();
l->setType(Ogre::Light::LT_DIRECTIONAL);
l->setDiffuseColour(Ogre::ColourValue::White);
l->setSpecularColour(Ogre::ColourValue(0.4, 0.4, 0.4));
Ogre::SceneNode *ln =
mScnMgr->getRootSceneNode()->createChildSceneNode();
ln->setDirection(Ogre::Vector3(0.55, -0.3, 0.75).normalisedCopy());
ln->attachObject(l);
//! [light]
mScnMgr->setAmbientLight(Ogre::ColourValue(0.2, 0.2, 0.2));
//! [terrain_create]
mTerrainGroup =
new Ogre::TerrainGroup(mScnMgr, Ogre::Terrain::ALIGN_X_Z,
TERRAIN_SIZE, TERRAIN_WORLD_SIZE);
mTerrainGroup->setOrigin(mTerrainPos);
//! [terrain_create]
#if OGRE_PLATFORM != OGRE_PLATFORM_APPLE_IOS
//! [terrain_save_config]
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
".", "FileSystem", mTerrainGroup->getResourceGroup(), false,
true);
mTerrainGroup->setFilenameConvention("TerrainSample", "bin");
//! [terrain_save_config]
#endif
configureTerrainDefaults(l);
#ifdef PAGING
// Paging setup
mPageManager = OGRE_NEW Ogre::PageManager();
// Since we're not loading any pages from .page files, we need a way just
// to say we've loaded them without them actually being loaded
mPageManager->setPageProvider(&mDummyPageProvider);
mPageManager->addCamera(camera);
mTerrainPaging = OGRE_NEW Ogre::TerrainPaging(mPageManager);
Ogre::PagedWorld *world = mPageManager->createWorld();
mTerrainPaging->createWorldSection(
world, mTerrainGroup, 2000, 3000, TERRAIN_PAGE_MIN_X,
TERRAIN_PAGE_MIN_Y, TERRAIN_PAGE_MAX_X, TERRAIN_PAGE_MAX_Y);
#else
//! [define_loop]
for (long x = TERRAIN_PAGE_MIN_X; x <= TERRAIN_PAGE_MAX_X; ++x)
for (long y = TERRAIN_PAGE_MIN_Y; y <= TERRAIN_PAGE_MAX_Y; ++y)
defineTerrain(x, y);
// sync load since we want everything in place when we start
mTerrainGroup->loadAllTerrains(true);
//! [define_loop]
#endif
//! [init_blend]
if (mTerrainsImported) {
for (const auto &ti : mTerrainGroup->getTerrainSlots()) {
initBlendMaps(ti.second->instance);
}
}
mTerrainGroup->freeTemporaryResources();
//! [init_blend]
#if 0
// create a few entities on the terrain
Entity *e = mSceneMgr->createEntity("tudorhouse.mesh");
Vector3 entPos(mTerrainPos.x + 2043, 0, mTerrainPos.z + 1715);
Quaternion rot;
entPos.y = mTerrainGroup->getHeightAtWorldPosition(entPos) +
65.5 + mTerrainPos.y;
rot.FromAngleAxis(Degree(Math::RangeRandom(-180, 180)),
Vector3::UNIT_Y);
SceneNode *sn =
mSceneMgr->getRootSceneNode()->createChildSceneNode(
entPos, rot);
sn->setScale(Vector3(0.12, 0.12, 0.12));
sn->attachObject(e);
mHouseList.push_back(e);
e = mSceneMgr->createEntity("tudorhouse.mesh");
entPos = Vector3(mTerrainPos.x + 1850, 0, mTerrainPos.z + 1478);
entPos.y = mTerrainGroup->getHeightAtWorldPosition(entPos) +
65.5 + mTerrainPos.y;
rot.FromAngleAxis(Degree(Math::RangeRandom(-180, 180)),
Vector3::UNIT_Y);
sn = mSceneMgr->getRootSceneNode()->createChildSceneNode(entPos,
rot);
sn->setScale(Vector3(0.12, 0.12, 0.12));
sn->attachObject(e);
mHouseList.push_back(e);
e = mSceneMgr->createEntity("tudorhouse.mesh");
entPos = Vector3(mTerrainPos.x + 1970, 0, mTerrainPos.z + 2180);
entPos.y = mTerrainGroup->getHeightAtWorldPosition(entPos) +
65.5 + mTerrainPos.y;
rot.FromAngleAxis(Degree(Math::RangeRandom(-180, 180)),
Vector3::UNIT_Y);
sn = mSceneMgr->getRootSceneNode()->createChildSceneNode(entPos,
rot);
sn->setScale(Vector3(0.12, 0.12, 0.12));
sn->attachObject(e);
mHouseList.push_back(e);
//! [skybox]
mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
//! [skybox]
#endif
}
#endif
#if 0
void TerrainSetup::configureTerrainDefaults(Ogre::Light *l)
{
//! [configure_lod]
mTerrainGlobals->setMaxPixelError(8);
mTerrainGlobals->setCompositeMapDistance(3000);
//! [configure_lod]
// mTerrainGlobals->setUseRayBoxDistanceCalculation(true);
// mTerrainGlobals->getDefaultMaterialGenerator()->setDebugLevel(1);
// mTerrainGlobals->setLightMapSize(256);
Ogre::TerrainMaterialGeneratorA::SM2Profile *matProfile =
static_cast<Ogre::TerrainMaterialGeneratorA::SM2Profile *>(
mTerrainGlobals->getDefaultMaterialGenerator()
->getActiveProfile());
// Disable the lightmap for OpenGL ES 2.0. The minimum number of samplers allowed is 8(as opposed to 16 on
// desktop). Otherwise we will run over the limit by just one. The minimum was raised to 16 in GL ES 3.0.
if (Ogre::Root::getSingletonPtr()
->getRenderSystem()
->getCapabilities()
->getNumTextureUnits() < 9) {
matProfile->setLightmapEnabled(false);
}
// Disable steep parallax by default
matProfile->setLayerParallaxOcclusionMappingEnabled(false);
//! [composite_lighting]
// Important to set these so that the terrain knows what to use for baked (non-realtime) data
mTerrainGlobals->setLightMapDirection(l->getDerivedDirection());
mTerrainGlobals->setCompositeMapAmbient(mScnMgr->getAmbientLight());
mTerrainGlobals->setCompositeMapDiffuse(l->getDiffuseColour());
//! [composite_lighting]
// mTerrainGlobals->setCompositeMapAmbient(ColourValue::Red);
// Configure default import settings for if we use imported image
//! [import_settings]
Ogre::Terrain::ImportData &defaultimp =
mTerrainGroup->getDefaultImportSettings();
defaultimp.inputScale = 600;
defaultimp.minBatchSize = 33;
defaultimp.maxBatchSize = 65;
//! [import_settings]
//! [tex_from_src]
Ogre::Image combined;
combined.loadTwoImagesAsRGBA("Ground23_col.jpg", "Ground23_spec.png",
"General");
Ogre::TextureManager::getSingleton().loadImage("Ground23_diffspec",
"General", combined);
//! [tex_from_src]
//! [textures]
defaultimp.layerList.resize(3);
defaultimp.layerList[0].worldSize = 200;
defaultimp.layerList[0].textureNames.push_back("Ground37_diffspec.dds");
defaultimp.layerList[0].textureNames.push_back(
"Ground37_normheight.dds");
defaultimp.layerList[1].worldSize = 200;
defaultimp.layerList[1].textureNames.push_back(
"Ground23_diffspec"); // loaded from memory
defaultimp.layerList[1].textureNames.push_back(
"Ground23_normheight.dds");
defaultimp.layerList[2].worldSize = 400;
defaultimp.layerList[2].textureNames.push_back("Rock20_diffspec.dds");
defaultimp.layerList[2].textureNames.push_back("Rock20_normheight.dds");
//! [textures]
}
#endif
void TerrainSetup::configureTerrainDefaults(Ogre::Light *l)
{
// Configure global
mTerrainGlobals->setMaxPixelError(1);
mTerrainGlobals->setMaxPixelError(0);
// testing composite map
mTerrainGlobals->setCompositeMapDistance(30);
// mTerrainGlobals->setCompositeMapDistance(30);
mTerrainGlobals->setCompositeMapDistance(500);
//mTerrainGlobals->setUseRayBoxDistanceCalculation(true);
mTerrainGlobals->getDefaultMaterialGenerator()->setLightmapEnabled(
false);
@@ -392,7 +402,7 @@ void TerrainSetup::configureTerrainDefaults(Ogre::Light *l)
mTerrainGroup->getDefaultImportSettings();
defaultimp.terrainSize = TERRAIN_SIZE;
defaultimp.worldSize = TERRAIN_WORLD_SIZE;
defaultimp.inputScale = 600;
defaultimp.inputScale = 1.0f;
defaultimp.minBatchSize = 33;
defaultimp.maxBatchSize = 65;
#if 0
@@ -430,3 +440,9 @@ void TerrainSetup::configureTerrainDefaults(Ogre::Light *l)
// defaultimp.layerList[0].textureNames.push_back("Rock20_normheight.png");
//! [textures]
}
bool TerrainSetup::DummyPageProvider::prepareProceduralPage(
Ogre::Page *page, Ogre::PagedWorldSection *section)
{
return true;
}

View File

@@ -36,71 +36,7 @@ class TerrainSetup {
std::unordered_map<Ogre::PageID, btRigidBody *> body;
btDynamicsWorld *mBtWorld;
bool prepareProceduralPage(Ogre::Page *page,
Ogre::PagedWorldSection *section)
{
Ogre::TerrainGroup *pGroup =
((Ogre::TerrainPagedWorldSection *)section)
->getTerrainGroup();
long x, y;
pGroup->unpackIndex(page->getID(), &x, &y);
Ogre::Terrain *pTerrain = pGroup->getTerrain(x, y);
if (!pTerrain)
return true;
float *terrainHeightData = pTerrain->getHeightData();
Ogre::Vector3 terrainPosition = pTerrain->getPosition();
float *pDataConvert = new float[pTerrain->getSize() *
pTerrain->getSize()];
for (int i = 0; i < pTerrain->getSize(); i++)
memcpy(pDataConvert + pTerrain->getSize() *
i, // source
terrainHeightData +
pTerrain->getSize() *
(pTerrain->getSize() -
i - 1), // target
sizeof(float) *
(pTerrain->getSize()) // size
);
float metersBetweenVertices =
pTerrain->getWorldSize() /
(pTerrain->getSize() -
1); //edit: fixed 0 -> 1 on 2010-08-13
btVector3 localScaling(metersBetweenVertices, 1,
metersBetweenVertices);
btHeightfieldTerrainShape *groundShape =
new btHeightfieldTerrainShape(
pTerrain->getSize(),
pTerrain->getSize(), pDataConvert,
1 /*ignore*/, pTerrain->getMinHeight(),
pTerrain->getMaxHeight(), 1, PHY_FLOAT,
true);
groundShape->setUseDiamondSubdivision(true);
groundShape->setLocalScaling(localScaling);
btRigidBody *groundBody = new btRigidBody(
0, new btDefaultMotionState(), groundShape);
groundBody->getWorldTransform().setOrigin(btVector3(
terrainPosition.x,
terrainPosition.y + (pTerrain->getMaxHeight() -
pTerrain->getMinHeight()) /
2,
terrainPosition.z));
groundBody->getWorldTransform().setRotation(
btQuaternion(Ogre::Quaternion::IDENTITY.x,
Ogre::Quaternion::IDENTITY.y,
Ogre::Quaternion::IDENTITY.z,
Ogre::Quaternion::IDENTITY.w));
mBtWorld->addRigidBody(groundBody);
body[page->getID()] = groundBody;
return true;
}
Ogre::PagedWorldSection *section);
bool loadProceduralPage(Ogre::Page *page,
Ogre::PagedWorldSection *section)
{
@@ -417,77 +353,7 @@ public:
}
std::unordered_set<long> col_terrains;
std::unordered_map<long, btRigidBody *> col_bodies;
void create_colliders()
{
btDynamicsWorld *world = mDynWorld->getBtWorld();
std::unordered_set<long> new_terrains;
Ogre::TerrainGroup::TerrainSlotMap slots =
mTerrainGroup->getTerrainSlots();
auto slot_it = slots.begin();
while (slot_it != slots.end()) {
Ogre::Terrain *terrain = slot_it->second->instance;
long x = slot_it->second->x;
long y = slot_it->second->y;
long key = y * 1024 + y;
std::cout << "x: " << x << "\n";
std::cout << "y: " << y << "\n";
if (!terrain) {
slot_it++;
continue;
}
if (new_terrains.find(key) != new_terrains.end()) {
slot_it++;
continue;
}
if (col_terrains.find(key) != col_terrains.end()) {
slot_it++;
continue;
}
new_terrains.insert(key);
col_terrains.insert(key);
btRigidBody *body = createHeightfieldShape(
terrain->getSize(), terrain->getHeightData(),
terrain->getMinHeight(),
terrain->getMaxHeight(), terrain->getPosition(),
terrain->getWorldSize() /
(terrain->getSize() - 1),
world);
OgreAssert(body, "Could not allocate body");
col_bodies[key] = body;
std::cout << "adding terrain body: " << terrain << " "
<< col_bodies[key] << "\n";
slot_it++;
}
auto col_it = col_terrains.begin();
std::list<long> rm_bodies;
while (col_it != col_terrains.end()) {
std::cout
<< "checking: terrain still exists: " << *col_it
<< "\n";
/* no terrain */
if (new_terrains.find(*col_it) == new_terrains.end()) {
std::cout << "was removed: "
<< col_bodies[*col_it] << " "
<< *col_it << "\n";
rm_bodies.push_back(*col_it);
/* free shapes and bodies */
}
col_it++;
}
#if 0
while (!rm_bodies.empty()) {
long key = rm_bodies.front();
rm_bodies.pop_front();
btRigidBody *body = col_bodies[key];
OgreAssert(body, "No body :(");
btCollisionShape *shape = body->getCollisionShape();
col_terrains.erase(key);
mDynWorld->getBtWorld()->removeRigidBody(body);
delete shape;
delete body;
}
#endif
}
btRigidBody *createHeightfieldShape(int size, float *data,
const Ogre::Real &minHeight,
const Ogre::Real &maxHeight,
@@ -537,5 +403,6 @@ public:
world->addRigidBody(body);
return body;
}
#endif
};
#endif

View File

@@ -25,7 +25,7 @@ Water::~Water()
void Water::createWater(Ogre::Camera *camera)
{
int i;
float w = 400;
float w = 1000;
mCamera = camera;
mScnMgr = camera->getSceneManager();
mCameraNode = camera->getParentSceneNode();
@@ -59,7 +59,9 @@ void Water::createWater(Ogre::Camera *camera)
mWaterNode = mScnMgr->getRootSceneNode()->createChildSceneNode("Water");
Ogre::Entity *water = mScnMgr->createEntity("WaterR", "water");
water->setVisibilityFlags(WATER_MASK);
water->setCastShadows(true);
auto mat = Ogre::MaterialManager::getSingleton().getByName("Water");
mat->setReceiveShadows(false);
mat->getTechnique(0)
->getPass(0)
->getTextureUnitState(0)
@@ -72,6 +74,7 @@ void Water::createWater(Ogre::Camera *camera)
Ogre::Entity *water_lod1 = mScnMgr->createEntity(
"Water" + Ogre::StringConverter::toString(i), "water");
water_lod1->setMaterialName("Water");
water_lod1->setMaterial(mat);
Ogre::SceneNode *node_w = mWaterNode->createChildSceneNode(
"Water" + Ogre::StringConverter::toString(i),
positions[i] * w, Ogre::Quaternion::IDENTITY);

View File

@@ -28,6 +28,8 @@ material Water
{
ambient 1.0 1.0 1.0 1.0
diffuse 0.0 0.2 0.5 1.0
cull_hardware none
cull_software none
/*
vertex_program_ref Examples/FresnelRefractReflectVP
{
@@ -62,6 +64,7 @@ material Water
texture waves2.png
// min / mag filtering, no mip
filtering linear linear none
tex_address_mode mirror
}
// Reflection
texture_unit
@@ -75,6 +78,19 @@ material Water
content_type compositor Fresnel refraction
tex_address_mode mirror
}
// Normal
texture_unit
{
texture waves2.png
sampler_ref RTSS/NormalMapSampler
// RT Shader system section.
rtshader_system
{
normal_map tangent_space
}
tex_address_mode mirror
}
}
}
}

Binary file not shown.