//check intersection of an axis-aligned box with the terrain bool Intersect(const Terrain &t, const WFMath::AxisBox<3> &bbox) { float max, min=bbox.lowCorner()[2]; int res = t.getResolution(); //determine which segments are involved //usually will just be one int xlow = (int) floor(bbox.lowCorner()[0] / res); int xhigh = (int) gridceil(bbox.highCorner()[0] / res); int ylow = (int) floor(bbox.lowCorner()[1] / res); int yhigh = (int) gridceil(bbox.highCorner()[1] / res); //loop across all tiles covered by this bbox for (int x = xlow; x < xhigh; x++) { for (int y = ylow; y < yhigh; y++) { //check the bbox against the extent of each tile //as an early rejection Segment *thisSeg=t.getSegment(x,y); if (thisSeg) max=thisSeg->getMax(); else max=Terrain::defaultLevel; if (max > min) { //entity bbox overlaps with the extents of this tile //now check each tile point covered by the entity bbox //clip the points to be tested against the bbox int min_x = (int) floor(bbox.lowCorner()[0] - (x * res)); if (min_x < 0) min_x = 0; int max_x = (int) gridceil(bbox.highCorner()[0] - (x * res)); if (max_x > res) min_x = res; int min_y = (int) floor(bbox.lowCorner()[1] - (y * res)); if (min_y < 0) min_y = 0; int max_y = (int) gridceil(bbox.highCorner()[1] - (y * res)); if (max_y > res) min_y = res; //loop over each point and see if it is greater than the minimum //of the bbox. If all points are below, the the bbox does NOT //intersect. If a single point is above, then the bbox MIGHT //intersect. for (int xpt = min_x; xpt <= max_x; xpt++) { for (int ypt = min_y; ypt <= max_y; ypt++) { if (thisSeg) { if (thisSeg->get(xpt,ypt) > min) return true; } else if (Terrain::defaultLevel > min) return true; } } } } } return false; }

void Viewer::draw() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(backgroundCol.x(), backgroundCol.y(), backgroundCol.z(), 1.0f); if (mySky.wantSky()) mySky.Render( ); glEnable(GL_LIGHTING); if (applyGLSL) { glEnable(GL_VERTEX_PROGRAM_ARB); glEnable(GL_FRAGMENT_PROGRAM_ARB); light.position[3] = 1; light.setLight(); } else{ light.position[3] = 0; light.setLight(); } QVector4D ltmp(light.position[0],light.position[1],light.position[2],light.position[3]); ltmp.normalize(); GLfloat lpos[4] = {ltmp.x(),ltmp.y(),ltmp.z(),ltmp.w()}; glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 1, lpos); // Draws a terrain if (curTerr>=0 && curTerr<terrains.size()){ Terrain * terrain = terrains[curTerr]; if (applyTexture) glBindTexture( GL_TEXTURE_2D, terrain->texid ); else glBindTexture( GL_TEXTURE_2D, 0); terrain->Draw(); //glLineWidth(10.0); //glPointSize(10.0); //glColor3f(1.0f,0.0f,0.0f); for (int i=0; i<terrain->artifacts.size(); i++){ glColor3f(terrain->severity[i]/2.2f, 0.0f, 0.0f); drawFlag(terrain->artifacts[i]); } } glDisable(GL_VERTEX_PROGRAM_ARB); glDisable(GL_FRAGMENT_PROGRAM_ARB); glDisable(GL_LIGHTING); //glLineWidth(1.0); //glPointSize(1.0); }

float* SnowTerrain::getTerrainHeightData() { Terrain *t = mTerrainGroup->getTerrain(0,0); // Get terrain height data using official method float* terrainHeightData = t->getHeightData(); return terrainHeightData; }

bool Map::deleteUnit(Unit* unit) { Terrain* pos = getTerrainUnderUnit(unit->getID()); m_unitList.erase(unit->getID()); pos->setUnit(NULL); delete unit; return true; }

static duk_ret_t Terrain_PatchExists_uint_uint(duk_context* ctx) { Terrain* thisObj = GetThisWeakObject<Terrain>(ctx); uint patchX = (uint)duk_require_number(ctx, 0); uint patchY = (uint)duk_require_number(ctx, 1); bool ret = thisObj->PatchExists(patchX, patchY); duk_push_boolean(ctx, ret); return 1; }

static duk_ret_t Terrain_GetPoint_uint_uint(duk_context* ctx) { Terrain* thisObj = GetThisWeakObject<Terrain>(ctx); uint x = (uint)duk_require_number(ctx, 0); uint y = (uint)duk_require_number(ctx, 1); float ret = thisObj->GetPoint(x, y); duk_push_number(ctx, ret); return 1; }

bool ParaTerrain::TerrainLattice::IsHole( float x, float y ) { Terrain *pTerrain = GetTerrainAtPoint(x, y); if(pTerrain!=NULL) { return pTerrain->IsHoleW(x,y); } return false; }

static duk_ret_t Terrain_SetPointHeight_uint_uint_float(duk_context* ctx) { Terrain* thisObj = GetThisWeakObject<Terrain>(ctx); uint x = (uint)duk_require_number(ctx, 0); uint y = (uint)duk_require_number(ctx, 1); float height = (float)duk_require_number(ctx, 2); thisObj->SetPointHeight(x, y, height); return 0; }

void TerrainLattice::SetVertexElevation(float x, float y, float newElevation, bool recalculate_geometry) { /* some vertex on border needs to be duplicated. This macro set the vertex on the given terrain tile. * it is just to make the code easy to understand */ #define SETELEVATION(indexX, indexY) \ pTerrain = GetTerrain((indexX), (indexY));\ if(pTerrain && (!pTerrain->IsEmpty())){\ int nIndex = pTerrain->GetVertexW(x,y);\ pTerrain->SetVertexElevation(nIndex, newElevation,recalculate_geometry);\ pTerrain->SetModified(true, MODIFIED_HEIGHTMAP);\ } Terrain *pTerrain = NULL; if(x<0 || y<0) return; int indexX = (int)(x / m_TerrainWidth); int indexY = (int)(y / m_TerrainHeight); SETELEVATION(indexX, indexY); float dX = x-indexX*m_TerrainWidth; float dY = y-indexY*m_TerrainHeight; float fRadius = pTerrain->GetVertexSpacing()/2; if(dX<fRadius) { SETELEVATION(indexX-1, indexY); if(dY<fRadius) { SETELEVATION(indexX-1, indexY-1); } else if(dY>m_TerrainHeight-fRadius) { SETELEVATION(indexX-1, indexY+1); } } else if(dX>m_TerrainWidth-fRadius) { SETELEVATION(indexX+1, indexY); if(dY<fRadius) { SETELEVATION(indexX+1, indexY-1); } else if(dY>m_TerrainHeight-fRadius) { SETELEVATION(indexX+1, indexY+1); } } if(dY<fRadius) { SETELEVATION(indexX, indexY-1); } else if(dY>m_TerrainHeight-fRadius) { SETELEVATION(indexX, indexY+1); } }

static duk_ret_t Terrain_MakePatchFlat_uint_uint_float(duk_context* ctx) { Terrain* thisObj = GetThisWeakObject<Terrain>(ctx); uint patchX = (uint)duk_require_number(ctx, 0); uint patchY = (uint)duk_require_number(ctx, 1); float heightValue = (float)duk_require_number(ctx, 2); thisObj->MakePatchFlat(patchX, patchY, heightValue); return 0; }

static duk_ret_t Terrain_ShouldBeSerialized_bool_bool(duk_context* ctx) { Terrain* thisObj = GetThisWeakObject<Terrain>(ctx); bool serializeTemporary = duk_require_boolean(ctx, 0); bool serializeLocal = duk_require_boolean(ctx, 1); bool ret = thisObj->ShouldBeSerialized(serializeTemporary, serializeLocal); duk_push_boolean(ctx, ret); return 1; }

void TerrainEditTool::sync(Level *level) { // Generate Terrain object Terrain terrain; for(int i = 0; i < _items.size(); i++) { terrain.append(_items.at(i)->getPolygon()); } level->setTerrain(terrain); }

Terrain* Terrain::create(b2World* world,Hero* hero) { Terrain* terrain = new Terrain; if (terrain && terrain->init(world,hero)) { terrain->autorelease(); return terrain; } return NULL; }

bool TerrainLattice::SnapPointToVertexGrid(float& x, float& y) { Terrain *pTerrain = GetTerrainAtPoint(x, y); if(pTerrain==NULL || pTerrain->IsEmpty()) return false; float fVertexSpacing = pTerrain->GetVertexSpacing(); x = (Math::Round(x / fVertexSpacing))*fVertexSpacing; y = (Math::Round(y / fVertexSpacing))*fVertexSpacing; return true; }

float TerrainLattice::GetVertexElevation(float x, float y) { Terrain *pTerrain = GetTerrainAtPoint(x, y); if(pTerrain!=NULL) { return pTerrain->GetVertexElevation(pTerrain->GetVertexW(x,y)); } else return 0.f; }

/* * @param xpos and ypos: The amount in pixels to check if is valid move */ bool Entity::isValidLevelMove(int xpos, int ypos) { if (xpos / 32 < 0 || ypos / 32 < 0 || xpos/32 >= MAX_TERRAINS_ROW || ypos/32 >= MAX_TERRAINS_COL) return false; Terrain* terrain = current_level->getTerrain(xpos/32, ypos/32); if (terrain != NULL && terrain->isWalkable() && !terrain->isWater()) return true; return false; }

void TilesetEditor::setTerrainImage(Tile *tile) { Terrain *terrain = mTerrainDock->currentTerrain(); if (!terrain) return; mCurrentTilesetDocument->undoStack()->push(new SetTerrainImage(mCurrentTilesetDocument, terrain->id(), tile->id())); }

static duk_ret_t Terrain_LoadFromImageFile_String_float_float(duk_context* ctx) { Terrain* thisObj = GetThisWeakObject<Terrain>(ctx); String filename = duk_require_string(ctx, 0); float offset = (float)duk_require_number(ctx, 1); float scale = (float)duk_require_number(ctx, 2); bool ret = thisObj->LoadFromImageFile(filename, offset, scale); duk_push_boolean(ctx, ret); return 1; }

void TerrainLattice::SetAllLoadedModified(bool bIsModified, DWORD dwModifiedBits) { bool bSaveConfigFile = false; TerrainTileCacheMap_type::iterator itCurCP, itEndCP = m_pCachedTerrains.end(); for( itCurCP = m_pCachedTerrains.begin(); itCurCP != itEndCP; ++ itCurCP) { Terrain* pTerrain = (*itCurCP).second.pTerrain; pTerrain->SetModified(bIsModified, dwModifiedBits); } }

static duk_ret_t Terrain_SetAttribute_String_Variant_AttributeChange__Type(duk_context* ctx) { int numArgs = duk_get_top(ctx); Terrain* thisObj = GetThisWeakObject<Terrain>(ctx); String id = duk_require_string(ctx, 0); Variant value = GetVariant(ctx, 1); AttributeChange::Type change = numArgs > 2 ? (AttributeChange::Type)(int)duk_require_number(ctx, 2) : AttributeChange::Default; thisObj->SetAttribute(id, value, change); return 0; }

void TerrainLattice::SetVertexInfo(float x,float y,uint32 data,uint32 bitMask,uint32 bitOffset) { #define SETDATA(idxX,idxY)\ pTerrain = GetTerrain((idxX),(idxY));\ if(pTerrain && (!pTerrain->IsEmpty())){\ int idx = pTerrain->GetVertexW(x,y);\ pTerrain->SetVertexInfo(idx,data,bitMask,bitOffset);\ } Terrain* pTerrain = NULL; if(x<0 || y<0) return; int idxX = (int)(x / m_TerrainWidth); int idxY = (int)(y / m_TerrainHeight); SETDATA(idxX,idxY); float dx = x - idxX * m_TerrainWidth; float dy = y - idxY * m_TerrainHeight; float radius = pTerrain->GetVertexSpacing() / 2; if(dx < radius) { SETDATA(idxX - 1,idxY); if(dy < radius) { SETDATA(idxX-1,idxY-1); } else if(dy > m_TerrainHeight - radius) { SETDATA(idxX-1,idxY+1); } } else if(dx > m_TerrainWidth - radius) { SETDATA(idxX+1, idxY); if(dy<radius) { SETDATA(idxX+1, idxY-1); } else if(dy>m_TerrainHeight-radius) { SETDATA(idxX+1, idxY+1); } } if(dy<radius) { SETDATA(idxX, idxY-1); } else if(dy>m_TerrainHeight-radius) { SETDATA(idxX, idxY+1); } }

static duk_ret_t Terrain_Resize_uint_uint_uint_uint(duk_context* ctx) { int numArgs = duk_get_top(ctx); Terrain* thisObj = GetThisWeakObject<Terrain>(ctx); uint newWidth = (uint)duk_require_number(ctx, 0); uint newHeight = (uint)duk_require_number(ctx, 1); uint oldPatchStartX = numArgs > 2 ? (uint)duk_require_number(ctx, 2) : 0; uint oldPatchStartY = numArgs > 3 ? (uint)duk_require_number(ctx, 3) : 0; thisObj->Resize(newWidth, newHeight, oldPatchStartX, oldPatchStartY); return 0; }

void Water::_allocBlock() { Terrain * terrain = Environment::Instance()->GetTerrain(); mBlockCountX = terrain->GetConfig().xSectionCount; mBlockCountZ = terrain->GetConfig().zSectionCount; mBlocks = new WaterBlock[terrain->GetConfig().iSectionCount]; _initBlock(); }

Terrain * Terrain::create() { Terrain * terrain = new Terrain(); if (terrain && terrain->initWithSpriteFrameName("blank.png")) { terrain->setAnchorPoint(ccp(0,0)); terrain->initTerrain(); terrain->autorelease(); return terrain; } CC_SAFE_DELETE(terrain); return NULL; }

void TerrainLattice::GetNormal(float x, float y, float &normalX, float &normalY, float &normalZ) { Terrain *pTerrain = GetTerrainAtPoint(x, y); if (pTerrain != NULL) return pTerrain->GetNormalW(x, y,normalX,normalY,normalZ ); else { normalX = 0; normalY = 0; normalZ = 1.0f; } }

int CGlobalTerrain::GetTextureCount(float x, float y) { Terrain * pTerrain = GetTerrainAtPoint(x, y); if (pTerrain) { if (pTerrain->GetTextureSet()) { return pTerrain->GetTextureSet()->GetNumTextures(); } } return 0; }

float PhysicsRigidBody::getHeight(float x, float z) const { GP_ASSERT(_collisionShape); GP_ASSERT(_node); // If our node has a terrain, call getHeight() on it since we need to factor in local // scaling on the terrain into the height calculation. Terrain* terrain = dynamic_cast<Terrain*>(_node->getDrawable()); if (terrain) return terrain->getHeight(x, z); // This function is only supported for heightfield rigid bodies. if (_collisionShape->getType() != PhysicsCollisionShape::SHAPE_HEIGHTFIELD) { GP_WARN("Attempting to get the height of a non-heightfield rigid body."); return 0.0f; } GP_ASSERT(_collisionShape->_shapeData.heightfieldData); // Ensure inverse kmMat4 is updated so we can transform from world back into local heightfield coordinates for indexing if (_collisionShape->_shapeData.heightfieldData->inverseIsDirty) { _collisionShape->_shapeData.heightfieldData->inverseIsDirty = false; //_node->getWorldMatrix().invert(&_collisionShape->_shapeData.heightfieldData->inverse); kmMat4Invert(&_collisionShape->_shapeData.heightfieldData->inverse, &_node->getWorldMatrix()); } // Calculate the correct x, z position relative to the heightfield data. float cols = _collisionShape->_shapeData.heightfieldData->heightfield->getColumnCount(); float rows = _collisionShape->_shapeData.heightfieldData->heightfield->getRowCount(); GP_ASSERT(cols > 0); GP_ASSERT(rows > 0); //kmVec3 v = _collisionShape->_shapeData.heightfieldData->inverse * Vector3(x, 0.0f, z); kmVec3 v = vec3Zero; kmMat3Transform(&v, &_collisionShape->_shapeData.heightfieldData->inverse, x, 0.0f, z, 0.0f); x = v.x + (cols - 1) * 0.5f; z = v.z + (rows - 1) * 0.5f; // Get the unscaled height value from the HeightField float height = _collisionShape->_shapeData.heightfieldData->heightfield->getHeight(x, z); // Apply scale back to height kmVec3 worldScale = vec3Zero; //_node->getWorldMatrix().getScale(&worldScale); kmMat4Decompose(&_node->getWorldMatrix(), &worldScale, NULL, NULL); height *= worldScale.y; return height; }

void ParaTerrain::TerrainLattice::ResizeTextureMaskWidth( int nWidth ) { TerrainTileCacheMap_type::iterator itCurCP, itEndCP = m_pCachedTerrains.end(); for( itCurCP = m_pCachedTerrains.begin(); itCurCP != itEndCP; ++ itCurCP) { Terrain* pTerrain = (*itCurCP).second.pTerrain; if(pTerrain) { pTerrain->ResizeTextureMaskWidth(nWidth); } } }

void CollisionManager::CollideBulletTerrain( Bullet& bullet, Terrain& terrain ) { if( terrain.Type() != Terrain::Rock ) { bullet.SetCoordinates( terrain.GetCoordinates() ); return; } MessageBeep(MB_ICONSTOP); bullet.Explode(); bullet.Damage(terrain); }

void PropertyBrowser::applyTerrainValue(PropertyId id, const QVariant &val) { Terrain *terrain = static_cast<Terrain*>(mObject); if (id == NameProperty) { QUndoStack *undoStack = mMapDocument->undoStack(); undoStack->push(new RenameTerrain(mMapDocument, terrain->tileset(), terrain->id(), val.toString())); } }