示例#1
0
int lua_TerrainPatch_getMaterialCount(lua_State* state)
{
    // Get the number of parameters.
    int paramCount = lua_gettop(state);

    // Attempt to match the parameters to a valid binding.
    switch (paramCount)
    {
        case 1:
        {
            if ((lua_type(state, 1) == LUA_TUSERDATA))
            {
                TerrainPatch* instance = getInstance(state);
                unsigned int result = instance->getMaterialCount();

                // Push the return value onto the stack.
                lua_pushunsigned(state, result);

                return 1;
            }

            lua_pushstring(state, "lua_TerrainPatch_getMaterialCount - Failed to match the given parameters to a valid function signature.");
            lua_error(state);
            break;
        }
        default:
        {
            lua_pushstring(state, "Invalid number of parameters (expected 1).");
            lua_error(state);
            break;
        }
    }
    return 0;
}
示例#2
0
void Terrain::UpdatePatchLod(TerrainPatch* patch)
{
    Geometry* geometry = patch->GetGeometry();

    // All LOD levels except the coarsest have 16 versions for stitching
    unsigned lodLevel = patch->GetLodLevel();
    unsigned drawRangeIndex = lodLevel << 4;
    if (lodLevel < numLodLevels_ - 1)
    {
        TerrainPatch* north = patch->GetNorthPatch();
        TerrainPatch* south = patch->GetSouthPatch();
        TerrainPatch* west = patch->GetWestPatch();
        TerrainPatch* east = patch->GetEastPatch();

        if (north && north->GetLodLevel() > lodLevel)
            drawRangeIndex |= STITCH_NORTH;
        if (south && south->GetLodLevel() > lodLevel)
            drawRangeIndex |= STITCH_SOUTH;
        if (west && west->GetLodLevel() > lodLevel)
            drawRangeIndex |= STITCH_WEST;
        if (east && east->GetLodLevel() > lodLevel)
            drawRangeIndex |= STITCH_EAST;
    }

    if (drawRangeIndex < drawRanges_.Size())
        geometry->SetDrawRange(TRIANGLE_LIST, drawRanges_[drawRangeIndex].first_, drawRanges_[drawRangeIndex].second_, false);
}
示例#3
0
float Camera::getActualHeight(vec3 objectPos)
{
  float actualY;
  vec3 tempObjectPos = objectPos;
  vec3 tempCameraPos = position;
  tempObjectPos.y = 0;
  tempCameraPos.y = 0;
  // (gridSize-2)*patchSize is the maximum distance, -3 for safety.
  if(Norm(tempCameraPos - tempObjectPos) < (float)(2*patchSize))
    {
      float xPosition,zPosition;    
      if(objectPos.x < 0.0) {
	xPosition = blendedSize-1*(fmod(-1*objectPos.x,(float)(blendedSize)));
      }
      else {
	xPosition = fmod(objectPos.x,(float)(blendedSize));  
      }
      if(objectPos.z < 0.0) {
	zPosition = blendedSize-1*(fmod(-1*objectPos.z,(float)(blendedSize)));
      }
      else {
	zPosition = fmod(objectPos.z,(float)(blendedSize));  
      }

      std::vector<TerrainPatch*> objectActualPatchRow;
      TerrainPatch *objectActualPatch;

      int patchXIndex = floor((objectPos.x - xPosition)/(float)(blendedSize));
      int patchZIndex = floor((objectPos.z - zPosition)/(float)(blendedSize));
        
      for(int i = 0; i < gridSize; i++){
	if(terrainVector->at(i).at(0)->yGrid == patchZIndex){
	  objectActualPatchRow = terrainVector->at(i);
	}
      }
      // Can trig out of range in objectActualPatchRow and probably
      // earlier in terrainVector also.
      for(int i = 0; i < gridSize; i++){
	if(objectActualPatchRow.at(i)->xGrid == patchXIndex){
	  objectActualPatch = objectActualPatchRow.at(i);
	}
      }

      actualY = objectActualPatch->calcHeight(xPosition,zPosition);
    }
  else
    actualY = 90.0;
  
  return actualY;
}
示例#4
0
int lua_TerrainPatch_getBoundingBox(lua_State* state)
{
    // Get the number of parameters.
    int paramCount = lua_gettop(state);

    // Attempt to match the parameters to a valid binding.
    switch (paramCount)
    {
        case 2:
        {
            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
                lua_type(state, 2) == LUA_TBOOLEAN)
            {
                // Get parameter 1 off the stack.
                bool param1 = gameplay::ScriptUtil::luaCheckBool(state, 2);

                TerrainPatch* instance = getInstance(state);
                void* returnPtr = (void*)&(instance->getBoundingBox(param1));
                if (returnPtr)
                {
                    gameplay::ScriptUtil::LuaObject* object = (gameplay::ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(gameplay::ScriptUtil::LuaObject));
                    object->instance = returnPtr;
                    object->owns = false;
                    luaL_getmetatable(state, "BoundingBox");
                    lua_setmetatable(state, -2);
                }
                else
                {
                    lua_pushnil(state);
                }

                return 1;
            }

            lua_pushstring(state, "lua_TerrainPatch_getBoundingBox - Failed to match the given parameters to a valid function signature.");
            lua_error(state);
            break;
        }
        default:
        {
            lua_pushstring(state, "Invalid number of parameters (expected 2).");
            lua_error(state);
            break;
        }
    }
    return 0;
}
示例#5
0
int lua_TerrainPatch_cameraChanged(lua_State* state)
{
    // Get the number of parameters.
    int paramCount = lua_gettop(state);

    // Attempt to match the parameters to a valid binding.
    switch (paramCount)
    {
        case 2:
        {
            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
                (lua_type(state, 2) == LUA_TUSERDATA || lua_type(state, 2) == LUA_TTABLE || lua_type(state, 2) == LUA_TNIL))
            {
                // Get parameter 1 off the stack.
                bool param1Valid;
                gameplay::ScriptUtil::LuaArray<Camera> param1 = gameplay::ScriptUtil::getObjectPointer<Camera>(2, "Camera", false, &param1Valid);
                if (!param1Valid)
                {
                    lua_pushstring(state, "Failed to convert parameter 1 to type 'Camera'.");
                    lua_error(state);
                }

                TerrainPatch* instance = getInstance(state);
                instance->cameraChanged(param1);
                
                return 0;
            }

            lua_pushstring(state, "lua_TerrainPatch_cameraChanged - Failed to match the given parameters to a valid function signature.");
            lua_error(state);
            break;
        }
        default:
        {
            lua_pushstring(state, "Invalid number of parameters (expected 2).");
            lua_error(state);
            break;
        }
    }
    return 0;
}
示例#6
0
void TerrainPatch::SetIndexSimplification()
{
	TerrainPatch* west  = m_parentTerrain->GetWestNeighborOf ( m_column, m_row );
	TerrainPatch* east  = m_parentTerrain->GetEastNeighborOf ( m_column, m_row );
	TerrainPatch* north = m_parentTerrain->GetNorthNeighborOf ( m_column, m_row );
	TerrainPatch* south = m_parentTerrain->GetSouthNeighborOf ( m_column, m_row );


	m_mipLevels[ (int) m_LOD]->SetIndexBlockSimplification( 
		(west  != NULL) ? (int)( (int)west->LOD()  - (int)m_LOD) : 0,
		(east  != NULL) ? (int)( (int)east->LOD()  - (int)m_LOD) : 0,
		(north != NULL) ? (int)( (int)north->LOD() - (int)m_LOD) : 0,
		(south != NULL) ? (int)( (int)south->LOD() - (int)m_LOD) : 0);

}
示例#7
0
void TerrainFunction::AddFunction(TerrainPatch& patch) const {
	// Read all frequently used data from pGrid.
	const vec2& world_south_west(patch.GetSouthWest());
	const vec2& world_north_east(patch.GetNorthEast());
	const int vertex_count_x = patch.GetVertexRes();
	const int vertex_count_y = patch.GetVertexRes();
	const float grid_width = patch.GetPatchSize();
	const float grid_height = patch.GetPatchSize();

	float a;

	// Calculate start X vertex index.
	int vertex_minimum_x;
	a = position_.x-outer_radius_;
	if (a <= world_south_west.x) {
		vertex_minimum_x = 0;
	} else {
		vertex_minimum_x = (int)::floor((a-world_south_west.x) * vertex_count_x / grid_width);
	}

	// Calculate end X vertex index.
	int vertex_maximum_x;
	a = position_.x+outer_radius_;
	if (a >= world_north_east.x) {
		vertex_maximum_x = vertex_count_x;
	} else {
		vertex_maximum_x = (int)::ceil((a-world_south_west.x) * vertex_count_x / grid_width);
	}

	// Calculate start Y vertex index.
	int vertex_minimum_y;
	a = position_.y-outer_radius_;
	if (a <= world_south_west.y) {
		vertex_minimum_y = 0;
	} else {
		vertex_minimum_y = (int)::floor((a-world_south_west.y) * vertex_count_y / grid_height);
	}

	// Calculate end Y vertex index.
	int vertex_maximum_y;
	a = position_.y+outer_radius_;
	if (a >= world_north_east.y) {
		vertex_maximum_y = vertex_count_y;
	} else {
		vertex_maximum_y = (int)::ceil((a-world_south_west.y) * vertex_count_y / grid_height);
	}

	patch.IterateOverPatch(*this, vertex_minimum_x, vertex_maximum_x, vertex_minimum_y, vertex_maximum_y);
}
示例#8
0
void Terrain::CreateGeometry()
{
    recreateTerrain_ = false;

    if (!node_)
        return;

    URHO3D_PROFILE(CreateTerrainGeometry);

    unsigned prevNumPatches = patches_.Size();

    // Determine number of LOD levels
    unsigned lodSize = (unsigned)patchSize_;
    numLodLevels_ = 1;
    while (lodSize > MIN_PATCH_SIZE && numLodLevels_ < maxLodLevels_)
    {
        lodSize >>= 1;
        ++numLodLevels_;
    }

    // Determine total terrain size
    patchWorldSize_ = Vector2(spacing_.x_ * (float)patchSize_, spacing_.z_ * (float)patchSize_);
    bool updateAll = false;

    if (heightMap_)
    {
        numPatches_ = IntVector2((heightMap_->GetWidth() - 1) / patchSize_, (heightMap_->GetHeight() - 1) / patchSize_);
        numVertices_ = IntVector2(numPatches_.x_ * patchSize_ + 1, numPatches_.y_ * patchSize_ + 1);
        patchWorldOrigin_ =
            Vector2(-0.5f * (float)numPatches_.x_ * patchWorldSize_.x_, -0.5f * (float)numPatches_.y_ * patchWorldSize_.y_);
        if (numVertices_ != lastNumVertices_ || lastSpacing_ != spacing_ || patchSize_ != lastPatchSize_)
            updateAll = true;
        unsigned newDataSize = (unsigned)(numVertices_.x_ * numVertices_.y_);

        // Create new height data if terrain size changed
        if (!heightData_ || updateAll)
            heightData_ = new float[newDataSize];

        // Ensure that the source (unsmoothed) data exists if smoothing is active
        if (smoothing_ && (!sourceHeightData_ || updateAll))
        {
            sourceHeightData_ = new float[newDataSize];
            updateAll = true;
        }
        else if (!smoothing_)
            sourceHeightData_.Reset();
    }
    else
    {
        numPatches_ = IntVector2::ZERO;
        numVertices_ = IntVector2::ZERO;
        patchWorldOrigin_ = Vector2::ZERO;
        heightData_.Reset();
        sourceHeightData_.Reset();
    }

    lastNumVertices_ = numVertices_;
    lastPatchSize_ = patchSize_;
    lastSpacing_ = spacing_;

    // Remove old patch nodes which are not needed
    if (updateAll)
    {
        URHO3D_PROFILE(RemoveOldPatches);

        PODVector<Node*> oldPatchNodes;
        node_->GetChildrenWithComponent<TerrainPatch>(oldPatchNodes);
        for (PODVector<Node*>::Iterator i = oldPatchNodes.Begin(); i != oldPatchNodes.End(); ++i)
        {
            bool nodeOk = false;
            Vector<String> coords = (*i)->GetName().Substring(6).Split('_');
            if (coords.Size() == 2)
            {
                int x = ToInt(coords[0]);
                int z = ToInt(coords[1]);
                if (x < numPatches_.x_ && z < numPatches_.y_)
                    nodeOk = true;
            }

            if (!nodeOk)
                node_->RemoveChild(*i);
        }
    }

    // Keep track of which patches actually need an update
    PODVector<bool> dirtyPatches((unsigned)(numPatches_.x_ * numPatches_.y_));
    for (unsigned i = 0; i < dirtyPatches.Size(); ++i)
        dirtyPatches[i] = updateAll;

    patches_.Clear();

    if (heightMap_)
    {
        // Copy heightmap data
        const unsigned char* src = heightMap_->GetData();
        float* dest = smoothing_ ? sourceHeightData_ : heightData_;
        unsigned imgComps = heightMap_->GetComponents();
        unsigned imgRow = heightMap_->GetWidth() * imgComps;
        IntRect updateRegion(-1, -1, -1, -1);

        if (imgComps == 1)
        {
            URHO3D_PROFILE(CopyHeightData);

            for (int z = 0; z < numVertices_.y_; ++z)
            {
                for (int x = 0; x < numVertices_.x_; ++x)
                {
                    float newHeight = (float)src[imgRow * (numVertices_.y_ - 1 - z) + x] * spacing_.y_;

                    if (updateAll)
                        *dest = newHeight;
                    else
                    {
                        if (*dest != newHeight)
                        {
                            *dest = newHeight;
                            GrowUpdateRegion(updateRegion, x, z);
                        }
                    }

                    ++dest;
                }
            }
        }
        else
        {
            URHO3D_PROFILE(CopyHeightData);

            // If more than 1 component, use the green channel for more accuracy
            for (int z = 0; z < numVertices_.y_; ++z)
            {
                for (int x = 0; x < numVertices_.x_; ++x)
                {
                    float newHeight = ((float)src[imgRow * (numVertices_.y_ - 1 - z) + imgComps * x] +
                                       (float)src[imgRow * (numVertices_.y_ - 1 - z) + imgComps * x + 1] / 256.0f) * spacing_.y_;

                    if (updateAll)
                        *dest = newHeight;
                    else
                    {
                        if (*dest != newHeight)
                        {
                            *dest = newHeight;
                            GrowUpdateRegion(updateRegion, x, z);
                        }
                    }

                    ++dest;
                }
            }
        }

        // If updating a region of the heightmap, check which patches change
        if (!updateAll)
        {
            int lodExpand = 1 << (numLodLevels_ - 1);
            // Expand the right & bottom 1 pixel more, as patches share vertices at the edge
            updateRegion.left_ -= lodExpand;
            updateRegion.right_ += lodExpand + 1;
            updateRegion.top_ -= lodExpand;
            updateRegion.bottom_ += lodExpand + 1;

            int sX = Max(updateRegion.left_ / patchSize_, 0);
            int eX = Min(updateRegion.right_ / patchSize_, numPatches_.x_ - 1);
            int sY = Max(updateRegion.top_ / patchSize_, 0);
            int eY = Min(updateRegion.bottom_ / patchSize_, numPatches_.y_ - 1);
            for (int y = sY; y <= eY; ++y)
            {
                for (int x = sX; x <= eX; ++x)
                    dirtyPatches[y * numPatches_.x_ + x] = true;
            }
        }

        patches_.Reserve((unsigned)(numPatches_.x_ * numPatches_.y_));

        bool enabled = IsEnabledEffective();

        {
            URHO3D_PROFILE(CreatePatches);

            // Create patches and set node transforms
            for (int z = 0; z < numPatches_.y_; ++z)
            {
                for (int x = 0; x < numPatches_.x_; ++x)
                {
                    String nodeName = "Patch_" + String(x) + "_" + String(z);
                    Node* patchNode = node_->GetChild(nodeName);

                    if (!patchNode)
                    {
                        // Create the patch scene node as local and temporary so that it is not unnecessarily serialized to either
                        // file or replicated over the network
                        patchNode = node_->CreateChild(nodeName, LOCAL);
                        patchNode->SetTemporary(true);
                    }

                    patchNode->SetPosition(Vector3(patchWorldOrigin_.x_ + (float)x * patchWorldSize_.x_, 0.0f,
                        patchWorldOrigin_.y_ + (float)z * patchWorldSize_.y_));

                    TerrainPatch* patch = patchNode->GetComponent<TerrainPatch>();
                    if (!patch)
                    {
                        patch = patchNode->CreateComponent<TerrainPatch>();
                        patch->SetOwner(this);
                        patch->SetCoordinates(IntVector2(x, z));

                        // Copy initial drawable parameters
                        patch->SetEnabled(enabled);
                        patch->SetMaterial(material_);
                        patch->SetDrawDistance(drawDistance_);
                        patch->SetShadowDistance(shadowDistance_);
                        patch->SetLodBias(lodBias_);
                        patch->SetViewMask(viewMask_);
                        patch->SetLightMask(lightMask_);
                        patch->SetShadowMask(shadowMask_);
                        patch->SetZoneMask(zoneMask_);
                        patch->SetMaxLights(maxLights_);
                        patch->SetCastShadows(castShadows_);
                        patch->SetOccluder(occluder_);
                        patch->SetOccludee(occludee_);
                    }

                    patches_.Push(WeakPtr<TerrainPatch>(patch));
                }
            }
        }

        // Create the shared index data
        if (updateAll)
            CreateIndexData();

        // Create vertex data for patches. First update smoothing to ensure normals are calculated correctly across patch borders
        if (smoothing_)
        {
            URHO3D_PROFILE(UpdateSmoothing);

            for (unsigned i = 0; i < patches_.Size(); ++i)
            {
                if (dirtyPatches[i])
                {
                    TerrainPatch* patch = patches_[i];
                    const IntVector2& coords = patch->GetCoordinates();
                    int startX = coords.x_ * patchSize_;
                    int endX = startX + patchSize_;
                    int startZ = coords.y_ * patchSize_;
                    int endZ = startZ + patchSize_;

                    for (int z = startZ; z <= endZ; ++z)
                    {
                        for (int x = startX; x <= endX; ++x)
                        {
                            float smoothedHeight = (
                                GetSourceHeight(x - 1, z - 1) + GetSourceHeight(x, z - 1) * 2.0f + GetSourceHeight(x + 1, z - 1) +
                                GetSourceHeight(x - 1, z) * 2.0f + GetSourceHeight(x, z) * 4.0f + GetSourceHeight(x + 1, z) * 2.0f +
                                GetSourceHeight(x - 1, z + 1) + GetSourceHeight(x, z + 1) * 2.0f + GetSourceHeight(x + 1, z + 1)
                            ) / 16.0f;

                            heightData_[z * numVertices_.x_ + x] = smoothedHeight;
                        }
                    }
                }
            }
        }

        for (unsigned i = 0; i < patches_.Size(); ++i)
        {
            TerrainPatch* patch = patches_[i];

            if (dirtyPatches[i])
            {
                CreatePatchGeometry(patch);
                CalculateLodErrors(patch);
            }

            SetPatchNeighbors(patch);
        }
    }

    // Send event only if new geometry was generated, or the old was cleared
    if (patches_.Size() || prevNumPatches)
    {
        using namespace TerrainCreated;

        VariantMap& eventData = GetEventDataMap();
        eventData[P_NODE] = node_;
        node_->SendEvent(E_TERRAINCREATED, eventData);
    }
}
示例#9
0
void Terrain::CreateGeometry()
{
    recreateTerrain_ = false;

    if (!node_)
        return;

    PROFILE(CreateTerrainGeometry);

    unsigned prevNumPatches = patches_.Size();

    // Determine number of LOD levels
    unsigned lodSize = patchSize_;
    numLodLevels_ = 1;
    while (lodSize > MIN_PATCH_SIZE && numLodLevels_ < MAX_LOD_LEVELS)
    {
        lodSize >>= 1;
        ++numLodLevels_;
    }

    // Determine total terrain size
    patchWorldSize_ = Vector2(spacing_.x_ * (float)patchSize_, spacing_.z_ * (float)patchSize_);
    if (heightMap_)
    {
        numPatches_ = IntVector2((heightMap_->GetWidth() - 1) / patchSize_, (heightMap_->GetHeight() - 1) / patchSize_);
        numVertices_ = IntVector2(numPatches_.x_ * patchSize_ + 1, numPatches_.y_ * patchSize_ + 1);
        patchWorldOrigin_ = Vector2(-0.5f * (float)numPatches_.x_ * patchWorldSize_.x_, -0.5f * (float)numPatches_.y_ *
            patchWorldSize_.y_);
        heightData_ = new float[numVertices_.x_ * numVertices_.y_];
    }
    else
    {
        numPatches_ = IntVector2::ZERO;
        numVertices_ = IntVector2::ZERO;
        patchWorldOrigin_ = Vector2::ZERO;
        heightData_.Reset();
    }

    // Remove old patch nodes which are not needed
    PODVector<Node*> oldPatchNodes;
    node_->GetChildrenWithComponent<TerrainPatch>(oldPatchNodes);
    for (PODVector<Node*>::Iterator i = oldPatchNodes.Begin(); i != oldPatchNodes.End(); ++i)
    {
        bool nodeOk = false;
        Vector<String> coords = (*i)->GetName().Substring(6).Split('_');
        if (coords.Size() == 2)
        {
            int x = ToInt(coords[0]);
            int z = ToInt(coords[1]);
            if (x < numPatches_.x_ && z < numPatches_.y_)
                nodeOk = true;
        }

        if (!nodeOk)
            node_->RemoveChild(*i);
    }

    patches_.Clear();

    if (heightMap_)
    {
        // Copy heightmap data
        const unsigned char* src = heightMap_->GetData();
        float* dest = heightData_;
        unsigned imgComps = heightMap_->GetComponents();
        unsigned imgRow = heightMap_->GetWidth() * imgComps;

        if (imgComps == 1)
        {
            for (int z = 0; z < numVertices_.y_; ++z)
            {
                for (int x = 0; x < numVertices_.x_; ++x)
                    *dest++ = (float)src[imgRow * (numVertices_.y_ - 1 - z) + x] * spacing_.y_;
            }
        }
        else
        {
            // If more than 1 component, use the green channel for more accuracy
            for (int z = 0; z < numVertices_.y_; ++z)
            {
                for (int x = 0; x < numVertices_.x_; ++x)
                    *dest++ = ((float)src[imgRow * (numVertices_.y_ - 1 - z) + imgComps * x] + (float)src[imgRow *
                        (numVertices_.y_ - 1 - z) + imgComps * x + 1] / 256.0f) * spacing_.y_;
            }
        }

        if (smoothing_)
            SmoothHeightMap();
        
        patches_.Reserve(numPatches_.x_ * numPatches_.y_);

        bool enabled = IsEnabledEffective();

        // Create patches and set node transforms
        for (int z = 0; z < numPatches_.y_; ++z)
        {
            for (int x = 0; x < numPatches_.x_; ++x)
            {
                String nodeName = "Patch_" + String(x) + "_" + String(z);
                Node* patchNode = node_->GetChild(nodeName);
                
                if (!patchNode)
                {
                    // Create the patch scene node as local and temporary so that it is not unnecessarily serialized to either
                    // file or replicated over the network
                    patchNode = node_->CreateChild(nodeName, LOCAL);
                    patchNode->SetTemporary(true);
                }
                
                patchNode->SetPosition(Vector3(patchWorldOrigin_.x_ + (float)x * patchWorldSize_.x_, 0.0f, patchWorldOrigin_.y_ +
                    (float)z * patchWorldSize_.y_));

                TerrainPatch* patch = patchNode->GetOrCreateComponent<TerrainPatch>();
                patch->SetOwner(this);
                patch->SetCoordinates(IntVector2(x, z));

                // Copy initial drawable parameters
                patch->SetEnabled(enabled);
                patch->SetMaterial(material_);
                patch->SetDrawDistance(drawDistance_);
                patch->SetShadowDistance(shadowDistance_);
                patch->SetLodBias(lodBias_);
                patch->SetViewMask(viewMask_);
                patch->SetLightMask(lightMask_);
                patch->SetShadowMask(shadowMask_);
                patch->SetZoneMask(zoneMask_);
                patch->SetMaxLights(maxLights_);
                patch->SetCastShadows(castShadows_);
                patch->SetOccluder(occluder_);
                patch->SetOccludee(occludee_);

                patches_.Push(WeakPtr<TerrainPatch>(patch));
            }
        }

        // Create the shared index data
        CreateIndexData();

        // Create vertex data for patches
        for (Vector<WeakPtr<TerrainPatch> >::Iterator i = patches_.Begin(); i != patches_.End(); ++i)
        {
            CreatePatchGeometry(*i);
            CalculateLodErrors(*i);
            SetNeighbors(*i);
        }
    }

    // Send event only if new geometry was generated, or the old was cleared
    if (patches_.Size() || prevNumPatches)
    {
        using namespace TerrainCreated;

        VariantMap& eventData = GetEventDataMap();
        eventData[P_NODE] = node_;
        node_->SendEvent(E_TERRAINCREATED, eventData);
    }
}
示例#10
0
void TerrainFunctionGroup::AddFunctions(TerrainPatch& patch) const {
	// No optimizations like the ones in TerrainFunction are possible.
	patch.IterateOverPatch(*this, 0, patch.GetVertexRes(), 0, patch.GetVertexRes());
}