void SimpleGrid::remove() { if (!isCreated()) { return; } Module::remove(); if (mVertices) { if (getNormalMode() == MaterialManager::NM_VERTEX) { delete [] static_cast<Mesh::POS_NORM_VERTEX*>(mVertices); } else if (getNormalMode() == MaterialManager::NM_RTT) { delete [] static_cast<Mesh::POS_VERTEX*>(mVertices); } } if (mVerticesChoppyBuffer) { delete [] mVerticesChoppyBuffer; } }
void SimpleGrid::create() { HydraxLOG("Creating " + getName() + " module."); Module::create(); int v, u; if (getNormalMode() == MaterialManager::NM_VERTEX) { mVertices = new Mesh::POS_NORM_VERTEX[mOptions.Complexity*mOptions.Complexity]; Mesh::POS_NORM_VERTEX* Vertices = static_cast<Mesh::POS_NORM_VERTEX*>(mVertices); for(v=0; v<mOptions.Complexity; v++) { for(u=0; u<mOptions.Complexity; u++) { Vertices[v*mOptions.Complexity + u].x = (static_cast<float>(v)/(mOptions.Complexity-1)) * mOptions.MeshSize.Width; Vertices[v*mOptions.Complexity + u].z = (static_cast<float>(u)/(mOptions.Complexity-1)) * mOptions.MeshSize.Height; Vertices[v*mOptions.Complexity + u].nx = 0; Vertices[v*mOptions.Complexity + u].ny = -1; Vertices[v*mOptions.Complexity + u].nz = 0; } } if (mOptions.ChoppyWaves) { mVerticesChoppyBuffer = new Mesh::POS_NORM_VERTEX[mOptions.Complexity*mOptions.Complexity]; for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++) { mVerticesChoppyBuffer[i] = Vertices[i]; } } } else if (getNormalMode() == MaterialManager::NM_RTT) { mVertices = new Mesh::POS_VERTEX[mOptions.Complexity*mOptions.Complexity]; Mesh::POS_VERTEX* Vertices = static_cast<Mesh::POS_VERTEX*>(mVertices); for(v=0; v<mOptions.Complexity; v++) { for(u=0; u<mOptions.Complexity; u++) { Vertices[v*mOptions.Complexity + u].x = (static_cast<float>(v)/(mOptions.Complexity-1)) * mOptions.MeshSize.Width; Vertices[v*mOptions.Complexity + u].z = (static_cast<float>(u)/(mOptions.Complexity-1)) * mOptions.MeshSize.Height; } } } HydraxLOG(getName() + " created."); }
void SimpleGrid::_performChoppyWaves() { if (getNormalMode() != MaterialManager::NM_VERTEX || !mOptions.ChoppyWaves) { return; } int v, u, Underwater = 1; if (mHydrax->_isCurrentFrameUnderwater()) { Underwater = -1; } Mesh::POS_NORM_VERTEX* Vertices = static_cast<Mesh::POS_NORM_VERTEX*>(mVertices); for(v=1; v<(mOptions.Complexity-1); v++) { for(u=1; u<(mOptions.Complexity-1); u++) { Vertices[v*mOptions.Complexity + u].x += Vertices[v*mOptions.Complexity + u].nx * mOptions.ChoppyStrength * Underwater; Vertices[v*mOptions.Complexity + u].z += Vertices[v*mOptions.Complexity + u].nz * mOptions.ChoppyStrength * Underwater; } } }
void SimpleGrid::_calculeNormals() { if (getNormalMode() != MaterialManager::NM_VERTEX) { return; } int v, u; Ogre::Vector3 vec1, vec2, normal; Mesh::POS_NORM_VERTEX* Vertices = static_cast<Mesh::POS_NORM_VERTEX*>(mVertices); for(v=1; v<(mOptions.Complexity-1); v++) { for(u=1; u<(mOptions.Complexity-1); u++) { vec1 = Ogre::Vector3( Vertices[v*mOptions.Complexity + u + 1].x-Vertices[v*mOptions.Complexity + u - 1].x, Vertices[v*mOptions.Complexity + u + 1].y-Vertices[v*mOptions.Complexity + u - 1].y, Vertices[v*mOptions.Complexity + u + 1].z-Vertices[v*mOptions.Complexity + u - 1].z); vec2 = Ogre::Vector3( Vertices[(v+1)*mOptions.Complexity + u].x - Vertices[(v-1)*mOptions.Complexity + u].x, Vertices[(v+1)*mOptions.Complexity + u].y - Vertices[(v-1)*mOptions.Complexity + u].y, Vertices[(v+1)*mOptions.Complexity + u].z - Vertices[(v-1)*mOptions.Complexity + u].z); normal = vec2.crossProduct(vec1); Vertices[v*mOptions.Complexity + u].nx = normal.x; Vertices[v*mOptions.Complexity + u].ny = normal.y; Vertices[v*mOptions.Complexity + u].nz = normal.z; } } }
void CSystemNormal::spawnWrapper(const void *context) { if(getNormalMode()) { ((CSystemNormal*)(context))->spawn(); } }
void Module::setNoise(Noise::Noise* Noise, GPUNormalMapManager* g, const bool& DeleteOldNoise) { if(DeleteOldNoise) { delete mNoise; } mNoise = Noise; if(mCreated) { if(!mNoise->isCreated()) { mNoise->create(); } if(getNormalMode() == MaterialManager::NM_RTT) { if(!mNoise->createGPUNormalMapResources(g)) { HydraxLOG(mNoise->getName() + " doesn't support GPU Normal map generation"); } } else { mNoise->removeGPUNormalMapResources(g); } } else { mNoise->removeGPUNormalMapResources(g); } }
float SimpleGrid::getHeigth(const Ogre::Vector2 &Position) { if (getNormalMode() != MaterialManager::NM_RTT) { Ogre::Vector2 RelativePos = mHydrax->getMesh()->getGridPosition(Position); RelativePos.x *= mOptions.MeshSize.Width; RelativePos.y *= mOptions.MeshSize.Height; return mHydrax->getPosition().y + mNoise->getValue(RelativePos.x, RelativePos.y)*mOptions.Strength; } else // RTT Normals calculations works with world-space coords { return mHydrax->getPosition().y + mNoise->getValue(Position.x, Position.y)*mOptions.Strength; } }
void SimpleGrid::setOptions(const Options &Options) { mMeshOptions.MeshSize = Options.MeshSize; mMeshOptions.MeshStrength = Options.Strength; mMeshOptions.MeshComplexity = Options.Complexity; mHydrax->getMesh()->setOptions(mMeshOptions); mHydrax->_setStrength(Options.Strength); if (isCreated()) { if (Options.Complexity != mOptions.Complexity || Options.ChoppyWaves != Options.ChoppyWaves) { remove(); mOptions = Options; create(); if (mNormalMode == MaterialManager::NM_RTT) { if (!mNoise->createGPUNormalMapResources(mHydrax->getGPUNormalMapManager())) { HydraxLOG(mNoise->getName() + " doesn't support GPU Normal map generation."); } } Ogre::String MaterialNameTmp = mHydrax->getMesh()->getMaterialName(); mHydrax->getMesh()->remove(); mHydrax->getMesh()->setOptions(getMeshOptions()); mHydrax->getMesh()->setMaterialName(MaterialNameTmp); mHydrax->getMesh()->create(); return; } mOptions = Options; int v, u; if (getNormalMode() == MaterialManager::NM_VERTEX) { Mesh::POS_NORM_VERTEX* Vertices = static_cast<Mesh::POS_NORM_VERTEX*>(mVertices); for(v=0; v<mOptions.Complexity; v++) { for(u=0; u<mOptions.Complexity; u++) { Vertices[v*mOptions.Complexity + u].x = (static_cast<float>(v)/(mOptions.Complexity-1)) * mOptions.MeshSize.Width; Vertices[v*mOptions.Complexity + u].z = (static_cast<float>(u)/(mOptions.Complexity-1)) * mOptions.MeshSize.Height; } } if (mOptions.ChoppyWaves && mVerticesChoppyBuffer) { for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++) { mVerticesChoppyBuffer[i] = Vertices[i]; } } } else if (getNormalMode() == MaterialManager::NM_RTT) { Mesh::POS_VERTEX* Vertices = static_cast<Mesh::POS_VERTEX*>(mVertices); for(v=0; v<mOptions.Complexity; v++) { for(u=0; u<mOptions.Complexity; u++) { Vertices[v*mOptions.Complexity + u].x = (static_cast<float>(v)/(mOptions.Complexity-1)) * mOptions.MeshSize.Width; Vertices[v*mOptions.Complexity + u].z = (static_cast<float>(u)/(mOptions.Complexity-1)) * mOptions.MeshSize.Height; } } } return; } mOptions = Options; }
void SimpleGrid::update(const Ogre::Real &timeSinceLastFrame) { if (!isCreated()) { return; } Module::update(timeSinceLastFrame); // Update heigths int i = 0, v, u; if (getNormalMode() == MaterialManager::NM_VERTEX) { Mesh::POS_NORM_VERTEX* Vertices = static_cast<Mesh::POS_NORM_VERTEX*>(mVertices); if (mOptions.ChoppyWaves) { for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++) { Vertices[i] = mVerticesChoppyBuffer[i]; Vertices[i].y = mNoise->getValue(Vertices[i].x, Vertices[i].z) * mOptions.Strength; } } else { for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++) { Vertices[i].y = mNoise->getValue(Vertices[i].x, Vertices[i].z) * mOptions.Strength; } } } else if (getNormalMode() == MaterialManager::NM_RTT) { Mesh::POS_VERTEX* Vertices = static_cast<Mesh::POS_VERTEX*>(mVertices); // For object-space to world-space conversion // RTT normals calculation needs world-space coords Ogre::Vector3 p = Ogre::Vector3(0,0,0); Ogre::Matrix4 mWorldMatrix; mHydrax->getMesh()->getEntity()->getParentSceneNode()->getWorldTransforms(&mWorldMatrix); for(int i = 0; i < mOptions.Complexity*mOptions.Complexity; i++) { p.x = Vertices[i].x; p.y = 0; p.z = Vertices[i].z; // Calculate the world-space position mWorldMatrix.transformAffine(p); Vertices[i].y = mNoise->getValue(p.x, p.z) * mOptions.Strength; } } // Smooth the heightdata if (mOptions.Smooth) { if (getNormalMode() == MaterialManager::NM_VERTEX) { Mesh::POS_NORM_VERTEX* Vertices = static_cast<Mesh::POS_NORM_VERTEX*>(mVertices); for(v=1; v<(mOptions.Complexity-1); v++) { for(u=1; u<(mOptions.Complexity-1); u++) { Vertices[v*mOptions.Complexity + u].y = 0.2f * (Vertices[v *mOptions.Complexity + u ].y + Vertices[v *mOptions.Complexity + (u+1)].y + Vertices[v *mOptions.Complexity + (u-1)].y + Vertices[(v+1)*mOptions.Complexity + u ].y + Vertices[(v-1)*mOptions.Complexity + u ].y); } } } else if (getNormalMode() == MaterialManager::NM_RTT) { Mesh::POS_VERTEX* Vertices = static_cast<Mesh::POS_VERTEX*>(mVertices); for(v=1; v<(mOptions.Complexity-1); v++) { for(u=1; u<(mOptions.Complexity-1); u++) { Vertices[v*mOptions.Complexity + u].y = 0.2f * (Vertices[v *mOptions.Complexity + u ].y + Vertices[v *mOptions.Complexity + (u+1)].y + Vertices[v *mOptions.Complexity + (u-1)].y + Vertices[(v+1)*mOptions.Complexity + u ].y + Vertices[(v-1)*mOptions.Complexity + u ].y); } } } } // Update normals _calculeNormals(); // Perform choppy waves _performChoppyWaves(); // Upload geometry changes mHydrax->getMesh()->updateGeometry(mOptions.Complexity*mOptions.Complexity, mVertices); }