Пример #1
0
void LandscapePropertyControl::OnFilepathPropertyChanged(PropertyList *forList, const String &forKey, const String &newValue)
{
    if(EditorSettings::IsValidPath(newValue))
    {
        LandscapeNode *landscape = dynamic_cast<LandscapeNode*> (currentSceneNode);
        if("property.landscape.heightmap" == forKey)
        {
            Vector3 size(
                         propertyList->GetFloatPropertyValue("property.landscape.size"),
                         propertyList->GetFloatPropertyValue("property.landscape.size"),
                         propertyList->GetFloatPropertyValue("property.landscape.height"));
            AABBox3 bbox;
            bbox.AddPoint(Vector3(-size.x/2.f, -size.y/2.f, 0.f));
            bbox.AddPoint(Vector3(size.x/2.f, size.y/2.f, size.z));
            
            if(newValue.length())
            {
                landscape->BuildLandscapeFromHeightmapImage(newValue, bbox);
            }
        }
        else if("property.landscape.texture.tile0" == forKey)
        {
            SetLandscapeTexture(LandscapeNode::TEXTURE_TILE0, newValue);
        }
        else if("property.landscape.texture.tile1" == forKey)
        {
            SetLandscapeTexture(LandscapeNode::TEXTURE_TILE1, newValue);
        }
        else if("property.landscape.texture.tile2" == forKey)
        {
            SetLandscapeTexture(LandscapeNode::TEXTURE_TILE2, newValue);
        }
        else if("property.landscape.texture.tile3" == forKey)
        {
            SetLandscapeTexture(LandscapeNode::TEXTURE_TILE3, newValue);
        }
        else if("property.landscape.texture.tilemask" == forKey)
        {
            SetLandscapeTexture(LandscapeNode::TEXTURE_TILE_MASK, newValue);
        }        
        else if("property.landscape.texture.color" == forKey)
        {
            SetLandscapeTexture(LandscapeNode::TEXTURE_COLOR, newValue);
        }
        else if("property.landscape.texture.tiledtexture" == forKey)
        {
            SetLandscapeTexture(LandscapeNode::TEXTURE_TILE_FULL, newValue);
        }
        else if(    "property.landscape.lightmap" == forKey 
                ||  "property.landscape.alphamask" == forKey)
        {
            String lightMap = propertyList->GetFilepathPropertyValue("property.landscape.lightmap");
            String alphaMask = propertyList->GetFilepathPropertyValue("property.landscape.alphamask");
            
            CreateMaskTexture(lightMap, alphaMask);
        }
    }

    NodesPropertyControl::OnFilepathPropertyChanged(forList, forKey, newValue);
}
Пример #2
0
void LandscapePropertyControl::OnFloatPropertyChanged(PropertyList *forList, const String &forKey, float newValue)
{
    if("property.landscape.size" == forKey || "property.landscape.height" == forKey)
    {
        LandscapeNode *landscape = dynamic_cast<LandscapeNode*> (currentSceneNode);
        
        Vector3 size(
                     propertyList->GetFloatPropertyValue("property.landscape.size"),
                     propertyList->GetFloatPropertyValue("property.landscape.size"),
                     propertyList->GetFloatPropertyValue("property.landscape.height"));
        AABBox3 bbox;
        bbox.AddPoint(Vector3(-size.x/2.f, -size.y/2.f, 0.f));
        bbox.AddPoint(Vector3(size.x/2.f, size.y/2.f, size.z));
        
        
        String heightMap = propertyList->GetFilepathPropertyValue("property.landscape.heightmap");
        if(EditorSettings::IsValidPath(heightMap) && heightMap.length())
        {
            landscape->BuildLandscapeFromHeightmapImage(heightMap, bbox);
        }
    }
    if ("property.landscape.texture0.tilex" == forKey || "property.landscape.texture0.tiley" == forKey)
    {
        LandscapeNode *landscape = dynamic_cast<LandscapeNode*> (currentSceneNode);
        Vector2 tiling(propertyList->GetFloatPropertyValue("property.landscape.texture0.tilex"),
                       propertyList->GetFloatPropertyValue("property.landscape.texture0.tiley"));
        landscape->SetTextureTiling(LandscapeNode::TEXTURE_TILE0, tiling);
    }
    if ("property.landscape.texture1.tilex" == forKey || "property.landscape.texture1.tiley" == forKey)
    {
        LandscapeNode *landscape = dynamic_cast<LandscapeNode*> (currentSceneNode);
        Vector2 tiling(propertyList->GetFloatPropertyValue("property.landscape.texture1.tilex"),
                       propertyList->GetFloatPropertyValue("property.landscape.texture1.tiley"));
        landscape->SetTextureTiling(LandscapeNode::TEXTURE_TILE1, tiling);
    }
	if ("property.landscape.texture2.tilex" == forKey || "property.landscape.texture2.tiley" == forKey)
	{
		LandscapeNode *landscape = dynamic_cast<LandscapeNode*> (currentSceneNode);
		Vector2 tiling(propertyList->GetFloatPropertyValue("property.landscape.texture2.tilex"),
			propertyList->GetFloatPropertyValue("property.landscape.texture2.tiley"));
		landscape->SetTextureTiling(LandscapeNode::TEXTURE_TILE2, tiling);
	}
	if ("property.landscape.texture3.tilex" == forKey || "property.landscape.texture3.tiley" == forKey)
	{
		LandscapeNode *landscape = dynamic_cast<LandscapeNode*> (currentSceneNode);
		Vector2 tiling(propertyList->GetFloatPropertyValue("property.landscape.texture3.tilex"),
			propertyList->GetFloatPropertyValue("property.landscape.texture3.tiley"));
		landscape->SetTextureTiling(LandscapeNode::TEXTURE_TILE3, tiling);
	}
    
    if ("property.material.dencity" == forKey)
    {
		LandscapeNode *landscape = dynamic_cast<LandscapeNode*> (currentSceneNode);
        landscape->SetFogDensity(newValue);
    }

    NodesPropertyControl::OnFloatPropertyChanged(forList, forKey, newValue);
}
Пример #3
0
void ImposterNode::GetOOBBoxScreenCoords(Entity * node, const Matrix4 & mvp, AABBox3 & screenBounds)
{
	const Rect & viewport = RenderManager::Instance()->GetViewport();
	MeshInstanceNode * mesh = dynamic_cast<MeshInstanceNode*>(node);
	if (mesh)
	{
		Vector3 corners[8];
		Vector3 screenVertices[8];

		mesh->GetBoundingBox().GetCorners(corners);
		const Matrix4 & worldTransform = mesh->GetWorldTransform();

		for (int32 k = 0; k < 8; ++k)
		{
			Vector4 pv(corners[k]);
			pv = pv * worldTransform;
			pv = pv * mvp;
			pv.x = (viewport.dx * 0.5f) * (1.f + pv.x/pv.w) + viewport.x;
			pv.y = (viewport.dy * 0.5f) * (1.f + pv.y/pv.w) + viewport.y;
			pv.z = (pv.z/pv.w + 1.f) * 0.5f;

			screenVertices[k] = Vector3(pv.x, pv.y, pv.z);
			screenBounds.AddPoint(screenVertices[k]);

		}
	}

	int32 count = node->GetChildrenCount();
	for (int32 i = 0; i < count; ++i)
	{
		GetOOBBoxScreenCoords(node->GetChild(i), mvp, screenBounds);
	}
}
void VegetationFixedGeometry::PrepareIndexBufferData(uint32 indexBufferIndex,
                        uint32 maxClusters,
                        uint32 maxClusterRowSize,
                        size_t resolutionIndex,
                        uint32 resolutionOffset,
                        Vector<uint32>& layerOffsets,
                        Vector<VegetationIndex>& preparedIndices,
                        AABBox3& indexBufferBBox,
                        VegetationRenderData& renderData)
{
    preparedIndices.clear();
    
    Vector<VegetationVertex>& vertexData = renderData.GetVertices();
    
    uint32 startX = (indexBufferIndex % resolutionTilesPerRow[resolutionIndex]) * maxClusters * resolutionOffset;
    uint32 startY = (indexBufferIndex / resolutionTilesPerRow[resolutionIndex]) * maxClusters * resolutionOffset;
    uint32 endX = startX + maxClusters * resolutionOffset;
    uint32 endY = startY + maxClusters * resolutionOffset;
    
    for(uint32 layerIndex = 0; layerIndex < maxLayerTypes; ++layerIndex)
    {
        TextureSheetCell& cellData = textureSheet.cells[layerIndex];
        
        const VegetationIndex* clusterIndices = VEGETATION_CLUSTER_INDICES[cellData.geometryId];
        uint32 clusterIndexCount = VEGETATION_CLUSTER_INDEX_SIZE[cellData.geometryId];
        uint32 clusterVertexCount = VEGETATION_CLUSTER_SIZE[cellData.geometryId];
        
        for(uint32 y = startY; y < endY; y += resolutionOffset)
        {
            for(uint32 x = startX; x < endX; x += resolutionOffset)
            {
                uint32 baseIndex = layerOffsets[layerIndex] + (y * maxClusterRowSize + x) * clusterVertexCount;
                
                for(uint32 clusterIndexIndex = 0; clusterIndexIndex < clusterIndexCount; ++clusterIndexIndex)
                {
                    size_t vertexIndex = baseIndex + clusterIndices[clusterIndexIndex];
                    
                    DVASSERT(vertexIndex >= 0 && vertexIndex < vertexData.size());
                    
                    VegetationVertex& vertex = vertexData[vertexIndex];
                    vertex.tangent.x = (float32)resolutionIndex;
                    
                    indexBufferBBox.AddPoint(vertex.coord);
                    
                    preparedIndices.push_back(vertexIndex);
                }
            }
        }
    }
}
Пример #5
0
void ParticleLayer3D::PrepareRenderData(Camera* camera)
{
	AABBox3 bbox;
	if (emitter->GetWorldTransformPtr())
	{
		Vector3 emmiterPos = emitter->GetWorldTransformPtr()->GetTranslationVector();
		bbox = AABBox3(emmiterPos, emmiterPos);
	}	

	// Yuri Coder, 2013/06/07. Don't draw SuperEmitter layers - see pls DF-1251 for details.
	if (!sprite || type == TYPE_SUPEREMITTER_PARTICLES)
	{		
		//build bounding box as sum of inner particle emitters bboxes
		if (type == TYPE_SUPEREMITTER_PARTICLES)
		{
			Particle *current = head;
			while (current)
			{
				bbox.AddAABBox(current->GetInnerEmitter()->GetBoundingBox());
				current=current->next;
			}
		}
		
		renderBatch->SetLayerBoundingBox(bbox);
		renderBatch->SetTotalCount(0);		
		return;
	}


	Matrix4 mv;
	Matrix3 rotation;
	bool worldAlign = particleOrientation&ParticleLayer::PARTICLE_ORIENTATION_WORLD_ALIGN;
	if (!worldAlign)
	{
		rotation = emitter->GetRotationMatrix();
	}
	Vector<std::pair<Vector3, Vector3> > basises;
	if (particleOrientation&ParticleLayer::PARTICLE_ORIENTATION_CAMERA_FACING)
	{
		mv = camera->GetMatrix();
		basises.push_back(std::pair<Vector3, Vector3>(Vector3(mv._01, mv._11, mv._21), Vector3(mv._00, mv._10, mv._20)));
	}
	if (particleOrientation&ParticleLayer::PARTICLE_ORIENTATION_X_FACING)
	{
		Vector3 up(0,1,0);
		Vector3 left(0,0,1);
		if (!worldAlign)
		{
			up = up*rotation;
			up.Normalize();
			left = left*rotation;
			left.Normalize();
		}
		basises.push_back(std::pair<Vector3, Vector3>(up, left));
	}
	if (particleOrientation&ParticleLayer::PARTICLE_ORIENTATION_Y_FACING)
	{
		Vector3 up(0,0,1);
		Vector3 left(1,0,0);
		if (!worldAlign)
		{
			up = up*rotation;
			up.Normalize();
			left = left*rotation;
			left.Normalize();
		}
		basises.push_back(std::pair<Vector3, Vector3>(up, left));
	}
	if (particleOrientation&ParticleLayer::PARTICLE_ORIENTATION_Z_FACING)
	{
		Vector3 up(0,1,0);
		Vector3 left(1,0,0);
		if (!worldAlign)
		{
			up = up*rotation;
			up.Normalize();
			left = left*rotation;
			left.Normalize();
		}
		basises.push_back(std::pair<Vector3, Vector3>(up, left));
	}
	
	int32 planesCount =  basises.size();

	direction = camera->GetDirection();

	verts.clear();
	textures.clear();
	colors.clear();

	if (enableFrameBlend)
	{
		textures2.clear();
		times.clear();
	}
	int32 totalCount = 0;

	// Reserve the memory for vectors to avoid the resize operations. Actually there can be less than count
	// particles (for Single Particle or Superemitter one), but never more than count.
	static const int32 POINTS_PER_PARTICLE = 4;
	static const int32 INDICES_PER_PARTICLE = 6;
	verts.resize(count * POINTS_PER_PARTICLE * 3 * planesCount); // 4 vertices per each particle, 3 coords per vertex.
	textures.resize(count * POINTS_PER_PARTICLE * 2 * planesCount); // 4 texture coords per particle, 2 values per texture coord.
	colors.resize(count * POINTS_PER_PARTICLE*planesCount);	
	
	//frame blending
	if (enableFrameBlend)
	{
		textures2.resize(count * POINTS_PER_PARTICLE * 2 * planesCount);
		times.resize(count * POINTS_PER_PARTICLE * planesCount); //single time value per vertex
	}

	Particle * current = head;
	if(current)
	{
		renderBatch->GetMaterial()->GetRenderState()->SetTexture(sprite->GetTexture(current->frame));
	}

	int32 verticesCount = 0;
	int32 texturesCount = 0;
	int32 texturesCount2 = 0;
	int32 timesCount = 0;
	int32 colorsCount = 0;	
	while(current != 0)
	{		
		for (int32 i=0; i<planesCount; ++i)
		{		
			_up = basises[i].first;
			_left = basises[i].second;
			Vector3 topRight;
			Vector3 topLeft;
			Vector3 botRight;
			Vector3 botLeft;

			if (IsLong())
			{
				CalcLong(current, topLeft, topRight, botLeft, botRight);
			}
			else
			{
				CalcNonLong(current, topLeft, topRight, botLeft, botRight);
			}

			verts[verticesCount] = topLeft.x;//0
			verticesCount ++;
			verts[verticesCount] = topLeft.y;
			verticesCount ++;
			verts[verticesCount] = topLeft.z;
			verticesCount ++;

			verts[verticesCount] = topRight.x;//1
			verticesCount ++;
			verts[verticesCount] = topRight.y;
			verticesCount ++;
			verts[verticesCount] = topRight.z;
			verticesCount ++;

			verts[verticesCount] = botLeft.x;//2
			verticesCount ++;
			verts[verticesCount] = botLeft.y;
			verticesCount ++;
			verts[verticesCount] = botLeft.z;
			verticesCount ++;

			verts[verticesCount] = botRight.x;//3
			verticesCount ++;
			verts[verticesCount] = botRight.y;
			verticesCount ++;
			verts[verticesCount] = botRight.z;
			verticesCount ++;

			bbox.AddPoint(topLeft);
			bbox.AddPoint(topRight);
			bbox.AddPoint(botLeft);
			bbox.AddPoint(botRight);

			float32 *pT = sprite->GetTextureVerts(current->frame);

			textures[texturesCount] = pT[0];
			texturesCount ++;
			textures[texturesCount] = pT[1];
			texturesCount ++;

			textures[texturesCount] = pT[2];
			texturesCount ++;
			textures[texturesCount] = pT[3];
			texturesCount ++;

			textures[texturesCount] = pT[4];
			texturesCount ++;
			textures[texturesCount] = pT[5];
			texturesCount ++;

			textures[texturesCount] = pT[6];
			texturesCount ++;
			textures[texturesCount] = pT[7];
			texturesCount ++;

			//frame blending
			if (enableFrameBlend)
			{
				int32 nextFrame = current->frame+1;
				if (nextFrame >= sprite->GetFrameCount())
				{
					if (loopSpriteAnimation)
						nextFrame = 0;
					else
						nextFrame = sprite->GetFrameCount()-1;
					
				}
				pT = sprite->GetTextureVerts(nextFrame);
				textures2[texturesCount2] = pT[0];
				texturesCount2 ++;
				textures2[texturesCount2] = pT[1];
				texturesCount2 ++;

				textures2[texturesCount2] = pT[2];
				texturesCount2 ++;
				textures2[texturesCount2] = pT[3];
				texturesCount2 ++;

				textures2[texturesCount2] = pT[4];
				texturesCount2 ++;
				textures2[texturesCount2] = pT[5];
				texturesCount2 ++;

				textures2[texturesCount2] = pT[6];
				texturesCount2 ++;
				textures2[texturesCount2] = pT[7];
				texturesCount2 ++;
				

				times[timesCount] = current->animTime;
				timesCount++;
				times[timesCount] = current->animTime;
				timesCount++;
				times[timesCount] = current->animTime;
				timesCount++;
				times[timesCount] = current->animTime;
				timesCount++;
			}
			

			// Yuri Coder, 2013/04/03. Need to use drawColor here instead of just colot
			// to take colorOverlife property into account.
			uint32 color = (((uint32)(current->drawColor.a*255.f))<<24) |  (((uint32)(current->drawColor.b*255.f))<<16) |
				(((uint32)(current->drawColor.g*255.f))<<8) | ((uint32)(current->drawColor.r*255.f));
			for(int32 i = 0; i < POINTS_PER_PARTICLE; ++i)
			{
				colors[i + colorsCount] = color;
			}
			colorsCount += POINTS_PER_PARTICLE;

			totalCount++;
		}
		current = TYPE_PARTICLES == type ? current->next : 0;
	}	
	int indexCount = indices.size()/INDICES_PER_PARTICLE;
	if (totalCount>indexCount)
	{
		indices.resize(totalCount*INDICES_PER_PARTICLE);
		for (;indexCount<totalCount; ++indexCount)
		{
			indices[indexCount*INDICES_PER_PARTICLE+0] = indexCount*POINTS_PER_PARTICLE+0;
			indices[indexCount*INDICES_PER_PARTICLE+1] = indexCount*POINTS_PER_PARTICLE+1;
			indices[indexCount*INDICES_PER_PARTICLE+2] = indexCount*POINTS_PER_PARTICLE+2;
			indices[indexCount*INDICES_PER_PARTICLE+3] = indexCount*POINTS_PER_PARTICLE+2;
			indices[indexCount*INDICES_PER_PARTICLE+4] = indexCount*POINTS_PER_PARTICLE+1;
			indices[indexCount*INDICES_PER_PARTICLE+5] = indexCount*POINTS_PER_PARTICLE+3; //preserve order
		}
	}

	renderBatch->SetTotalCount(totalCount);	
	renderBatch->SetLayerBoundingBox(bbox);
	if(totalCount > 0)
	{					
		renderData->SetStream(EVF_VERTEX, TYPE_FLOAT, 3, 0, &verts.front());
		renderData->SetStream(EVF_TEXCOORD0, TYPE_FLOAT, 2, 0, &textures.front());
		renderData->SetStream(EVF_COLOR, TYPE_UNSIGNED_BYTE, 4, 0, &colors.front());				
		if (enableFrameBlend)
		{
			renderData->SetStream(EVF_TEXCOORD1, TYPE_FLOAT, 2, 0, &textures2.front());
			renderData->SetStream(EVF_TIME, TYPE_FLOAT, 1, 0, &times.front());
		}				
	}
	
}
void VegetationFixedGeometry::GenerateVertices(uint32 maxClusters,
                    size_t maxTotalClusters,
                    uint32 maxClusterRowSize,
                    uint32 tilesPerRow,
                    Vector2 unitSize,
                    Vector<uint32>& layerOffsets,
                    VegetationRenderData& renderData)
{
    uint32 clustersPerTile = maxClusters * maxClusters;
    float32 atomicOffsetY = unitSize.y / clustersPerTile;
    
    Vector<uint32> shuffleDepth;
    shuffleDepth.reserve(maxTotalClusters);
    
    Vector<uint32> shuffleDensity;
    shuffleDensity.reserve(maxTotalClusters);
    
    Vector<uint32> depthScratchArray;
    depthScratchArray.reserve(clustersPerTile);
    
    Vector<uint32> densityScratchArray;
    densityScratchArray.reserve(clustersPerTile);
    
    for(uint32 i = 0; i < clustersPerTile; ++i)
    {
        depthScratchArray[i] = i;
        densityScratchArray[i] = (i % maxDensityLevels) + 1;
    }
    
    Vector<VegetationVertex>& vertexData = renderData.GetVertices();
    
    size_t vertexIndex = 0;
    uint32 totalTiles = tilesPerRow * tilesPerRow;
    for(uint32 layerIndex = 0; layerIndex < maxLayerTypes; ++layerIndex)
    {
        layerOffsets[layerIndex] = vertexIndex;
        
        TextureSheetCell& cellData = textureSheet.cells[layerIndex];
        
        const Vector3* clusterVertices = VEGETATION_CLUSTER[cellData.geometryId];
        const Vector3* clusterNormals = VEGETATION_CLUSTER_NORMALS[cellData.geometryId];
        uint32 clusterVertexCount = VEGETATION_CLUSTER_SIZE[cellData.geometryId];
        
        uint32 clusterCounter = 0;
        for(uint32 i = 0; i < totalTiles; ++i)
        {
            std::random_shuffle(densityScratchArray.begin(), densityScratchArray.end(), RandomShuffleFunc);
            std::random_shuffle(depthScratchArray.begin(), depthScratchArray.end(), RandomShuffleFunc);
            for(uint32 k = 0; k < clustersPerTile; ++k)
            {
                shuffleDensity[clusterCounter] = densityScratchArray[k];
                shuffleDepth[clusterCounter] = depthScratchArray[k];
                clusterCounter++;
            }
        }
        
        DVASSERT(clusterCounter == maxTotalClusters);
        
        AABBox3 clusterBBox;
        for(uint32 clusterVertexIndex = 0; clusterVertexIndex < clusterVertexCount; ++clusterVertexIndex)
        {
            clusterBBox.AddPoint(clusterVertices[clusterVertexIndex]);
        }
        
        float32 clusterVisualSize = cellData.geometryScale.x * (clusterBBox.max.x - clusterBBox.min.x);
        uint32 clustersInRow = (uint32)(unitSize.x / clusterVisualSize);
        if(clustersInRow <= 0)
        {
            clustersInRow = 1;
        }
        
        for(size_t clusterIndex = 0; clusterIndex < maxTotalClusters; ++clusterIndex)
        {
            uint32 clusterIndexX = clusterIndex % maxClusterRowSize;
            uint32 clusterIndexY = clusterIndex / maxClusterRowSize;
            
            uint32 matrixIndex = (clusterIndexX / maxClusters) + tilesPerRow * (clusterIndexY / maxClusters); //0...15
            DVASSERT(matrixIndex >= 0 && matrixIndex < (tilesPerRow * tilesPerRow));
            
            uint32 matrixIndexX = matrixIndex % tilesPerRow;
            uint32 matrixIndexY = matrixIndex / tilesPerRow;
            
            Vector2 matrixCellStart(unitSize.x * matrixIndexX, unitSize.y * matrixIndexY);
            
            float32 randomOffsetX = clusterVisualSize * (clusterIndex % clustersInRow) + clusterVisualSize * (0.5f - (float32)Random::Instance()->RandFloat());//unitSize.x * Random::Instance()->RandFloat();
            float32 randomOffsetY = atomicOffsetY * shuffleDepth[clusterIndex]; //unitSize.y * Random::Instance()->RandFloat();
            
            Vector3 clusterCenter(matrixCellStart.x + randomOffsetX, matrixCellStart.y + randomOffsetY, 0.0f);
            
            uint32 densityId = shuffleDensity[clusterIndex];
            
            for(uint32 clusterVertexIndex = 0; clusterVertexIndex < clusterVertexCount; ++clusterVertexIndex)
            {
                DVASSERT(vertexIndex < vertexData.size());
                VegetationVertex& vertex = vertexData[vertexIndex];
                
                vertex.coord.x = clusterCenter.x + clusterVertices[clusterVertexIndex].x * cellData.geometryScale.x;
                vertex.coord.y = clusterCenter.y + clusterVertices[clusterVertexIndex].y * cellData.geometryScale.x;
                vertex.coord.z = clusterCenter.z + clusterVertices[clusterVertexIndex].z * cellData.geometryScale.y;
                
                vertex.normal = clusterNormals[clusterVertexIndex];
                
                vertex.binormal = clusterCenter;
                
                vertex.tangent.y = (float32)layerIndex;
                vertex.tangent.z = (float32)densityId;
                
                vertex.texCoord0.x = cellData.coords[clusterVertexIndex % MAX_CELL_TEXTURE_COORDS].x;
                vertex.texCoord0.y = cellData.coords[clusterVertexIndex % MAX_CELL_TEXTURE_COORDS].y;
                
                vertexIndex++;
            }
        }
    }
}
void LandscapePropertyControl::OnFilepathPropertyChanged(PropertyList *forList, const String &forKey, const String &newValue)
{
	Set<String> errorsLog;
	if("property.landscape.heightmap" == forKey)
	{
		bool isValid = SceneValidator::Instance()->ValidateHeightmapPathname(newValue, errorsLog);
		if(isValid)
		{
			LandscapeNode *landscape = GetLandscape();
			if (!landscape)
				return;

			Vector3 size(
				propertyList->GetFloatPropertyValue("property.landscape.size"),
				propertyList->GetFloatPropertyValue("property.landscape.size"),
				propertyList->GetFloatPropertyValue("property.landscape.height"));
			AABBox3 bbox;
			bbox.AddPoint(Vector3(-size.x/2.f, -size.y/2.f, 0.f));
			bbox.AddPoint(Vector3(size.x/2.f, size.y/2.f, size.z));

			if(newValue.length())
			{
				landscape->BuildLandscapeFromHeightmapImage(newValue, bbox);
			}
		}
	}
	else
	{
		bool isValid = (newValue.empty()) ? true: SceneValidator::Instance()->ValidateTexturePathname(newValue, errorsLog);
		if(isValid)
		{
            String descriptorPathname = String("");
            if(!newValue.empty())
            {
                descriptorPathname = TextureDescriptor::GetDescriptorPathname(newValue);
            }
            
			if("property.landscape.texture.tile0" == forKey)
			{
				SetLandscapeTexture(LandscapeNode::TEXTURE_TILE0, descriptorPathname);
			}
			else if("property.landscape.texture.tile1" == forKey)
			{
				SetLandscapeTexture(LandscapeNode::TEXTURE_TILE1, descriptorPathname);
			}
			else if("property.landscape.texture.tile2" == forKey)
			{
				SetLandscapeTexture(LandscapeNode::TEXTURE_TILE2, descriptorPathname);
			}
			else if("property.landscape.texture.tile3" == forKey)
			{
				SetLandscapeTexture(LandscapeNode::TEXTURE_TILE3, descriptorPathname);
			}
			else if("property.landscape.texture.tilemask" == forKey)
			{
				SetLandscapeTexture(LandscapeNode::TEXTURE_TILE_MASK, descriptorPathname);
			}
			else if("property.landscape.texture.color" == forKey)
			{
				SetLandscapeTexture(LandscapeNode::TEXTURE_COLOR, descriptorPathname);
			}
			else if("property.landscape.texture.tiledtexture" == forKey)
			{
				SetLandscapeTexture(LandscapeNode::TEXTURE_TILE_FULL, descriptorPathname);
			}
		}
	}

	if(0 == errorsLog.size())
	{
		NodesPropertyControl::OnFilepathPropertyChanged(forList, forKey, newValue);
	}
	else
	{
		ShowErrorDialog(errorsLog);
	}
}
void LandscapePropertyControl::OnFloatPropertyChanged(PropertyList *forList, const String &forKey, float newValue)
{
    if("property.landscape.size" == forKey || "property.landscape.height" == forKey)
    {
		LandscapeNode *landscape = GetLandscape();
		if (landscape)
		{
			Vector3 size(
						 propertyList->GetFloatPropertyValue("property.landscape.size"),
						 propertyList->GetFloatPropertyValue("property.landscape.size"),
						 propertyList->GetFloatPropertyValue("property.landscape.height"));
			AABBox3 bbox;
			bbox.AddPoint(Vector3(-size.x/2.f, -size.y/2.f, 0.f));
			bbox.AddPoint(Vector3(size.x/2.f, size.y/2.f, size.z));
			
			Set<String> errorsLog;
			String heightMap = propertyList->GetFilepathPropertyValue("property.landscape.heightmap");
			if(SceneValidator::Instance()->ValidateHeightmapPathname(heightMap, errorsLog) && heightMap.length())
			{
				landscape->BuildLandscapeFromHeightmapImage(heightMap, bbox);
			}
        }
    }
    if ("property.landscape.texture0.tilex" == forKey || "property.landscape.texture0.tiley" == forKey)
    {
		LandscapeNode *landscape = GetLandscape();
		if (landscape)
		{
			Vector2 tiling(propertyList->GetFloatPropertyValue("property.landscape.texture0.tilex"),
						   propertyList->GetFloatPropertyValue("property.landscape.texture0.tiley"));
			landscape->SetTextureTiling(LandscapeNode::TEXTURE_TILE0, tiling);
		}
    }
    if ("property.landscape.texture1.tilex" == forKey || "property.landscape.texture1.tiley" == forKey)
    {
		LandscapeNode *landscape = GetLandscape();
		if (landscape)
		{
			Vector2 tiling(propertyList->GetFloatPropertyValue("property.landscape.texture1.tilex"),
						   propertyList->GetFloatPropertyValue("property.landscape.texture1.tiley"));
			landscape->SetTextureTiling(LandscapeNode::TEXTURE_TILE1, tiling);
		}
    }
	if ("property.landscape.texture2.tilex" == forKey || "property.landscape.texture2.tiley" == forKey)
	{
		LandscapeNode *landscape = GetLandscape();
		if (landscape)
		{
			Vector2 tiling(propertyList->GetFloatPropertyValue("property.landscape.texture2.tilex"),
				propertyList->GetFloatPropertyValue("property.landscape.texture2.tiley"));
			landscape->SetTextureTiling(LandscapeNode::TEXTURE_TILE2, tiling);
		}
	}
	if ("property.landscape.texture3.tilex" == forKey || "property.landscape.texture3.tiley" == forKey)
	{
		LandscapeNode *landscape = GetLandscape();
		if (landscape)
		{
			Vector2 tiling(propertyList->GetFloatPropertyValue("property.landscape.texture3.tilex"),
				propertyList->GetFloatPropertyValue("property.landscape.texture3.tiley"));
			landscape->SetTextureTiling(LandscapeNode::TEXTURE_TILE3, tiling);
		}
	}
    
    if ("property.material.dencity" == forKey)
    {
		LandscapeNode *landscape = GetLandscape();
		if (landscape)
			landscape->SetFogDensity(newValue);
    }

    NodesPropertyControl::OnFloatPropertyChanged(forList, forKey, newValue);
}