Better islands
This commit is contained in:
@@ -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})
|
||||
|
||||
|
||||
@@ -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
BIN
brushes.kra
Normal file
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 265 KiB |
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
world_map.kra
BIN
world_map.kra
Binary file not shown.
Reference in New Issue
Block a user