Game Development Community

dev|Pro Game Development Curriculum

Forest Editor Exporter (Scale Fixed)

by Kevin Mitchell · 03/05/2011 (7:35 am) · 6 comments

Explanation ---------------------------------------------------------------


This is a quick fix I have come up with for utilizing the Forest Editor for developing massive environmental faster. But Trying to unload the editor when not using it for development. The exporter will export a TSStatic version of the forest for injection into the .MIS file.


Implementation ------------------------------------------------------------


To the bottom of the "forestDataFile.h"
Append the following:

///FOREST EXPORTER 
	StringTableEntry mDataFileNameExp;

	void startExporter();
	void writeExporter(ForestItemData *data,const MatrixF &xfm,F32 scale );
	void endExporter();
	///FOREST EXPORTER

To the top of "forestDataFile.cpp"
Append:

//-----------------------------------------------------------------------------
// Torque 3D
// Copyright (C) InstantAction, Inc.
//-----------------------------------------------------------------------------

#include "platform/platform.h"
#include "forest/forestDataFile.h"

#include "forest/forest.h"
#include "forest/forestCell.h"
#include "T3D/physics/physicsBody.h"
#include "core/stream/fileStream.h"
#include "core/resource.h"
#include "math/mathIO.h"
#include "math/mPoint2.h"
#include "platform/profiler.h"

///FOREST EXPORTER 
#include <iostream>   //<==================
///FOREST EXPORTER

To the bottom of "forestDAtaFile.cpp"
Append:

///FOREST EXPORTER 

	FileStream exporter;
	char isExporter=0;
void ForestData::startExporter()
{

   // We need to construct a default file name
   String missionName( Con::getVariable( "$Client::MissionFile" ) );
   missionName.replace( "tools/levels", "levels" );

   Torque::Path basePath( missionName );
   String fileName = Torque::FS::MakeUniquePath( basePath.getPath(), basePath.getFileName(), "forestExporter" );
   mDataFileNameExp = StringTable->insert( fileName );

   if ( !exporter.open(mDataFileNameExp, Torque::FS::File::Write ) )
   {
	  isExporter=0;
      Con::errorf( "ForestExporter::write() - Failed opening stream!" );
      return;
   }

	  isExporter=1;
   exporter.writeText("ntnew SimGroup(ExportedForestItems) {rn");
		exporter.writeText("ttlocked = "1";rn");
		exporter.writeText("ttcanSave = "1";rn");
		exporter.writeText("ttcanSaveDynamicFields = "1";rn");
   

}

void ForestData::writeExporter(ForestItemData *data,const MatrixF &xfm,F32 scale )
{
		if(isExporter==0)return;
		char stringBuffer[255];
		memset(stringBuffer,0,sizeof(char)*255);

		//exporter.writeString( allDatablocks[i]->getInternalName() );

		exporter.writeText("ttnew TSStatic() {rn");

			//exporter.writeText("tttshapeName = "art/ArtPacks/FlowerPower_Items/blockStone001.dts";rn");

			//exporter.writeString("shapeName = "~/data/shapes/Winter/TreeNoSnow01.dts";");
			sprintf(stringBuffer, "tttshapeName = "%s";rn",data->mShapeFile);
			exporter.writeText(stringBuffer);
			//exporter.writeText("tttshapeName = "~/data/shapes/Winter/TreeNoSnow01.dts";rn");

			exporter.writeText("tttplayAmbient = "1";rn");
			exporter.writeText("tttmeshCulling = "0";rn");
			exporter.writeText("tttoriginSort = "0";rn");
			exporter.writeText("tttcollisionType = "Collision Mesh";rn");
			exporter.writeText("tttdecalType = "Collision Mesh";rn");
			exporter.writeText("tttallowPlayerStep = "1";rn");
			exporter.writeText("tttrenderNormals = "0";rn");
			exporter.writeText("tttforceDetail = "-1";rn");


			// exporter.writeText("tttposition = "-8.06511 -18.2087 2.36013";rn");
			// exporter.writeText("tttrotation = "1 0 0 0";rn");
			// exporter.writeText("tttscale = "1 1 1";rn");

			//POS
			sprintf(stringBuffer, "tttposition = "%f %f %f";rn",xfm.getPosition().x,xfm.getPosition().y,xfm.getPosition().z);
			exporter.writeText(stringBuffer);

			//ROT
			sprintf(stringBuffer, "tttrotation = "%f %f %f 0";rn",xfm.toEuler().x,xfm.toEuler().y,xfm.toEuler().z);
			exporter.writeText(stringBuffer);

			//SCA
			sprintf(stringBuffer, "tttscale = "%f %f %f";rn",xfm.getScale().x*scale,xfm.getScale().y*scale,xfm.getScale().z*scale);
			exporter.writeText(stringBuffer);

			exporter.writeText("tttcanSave = "1";rn");
			exporter.writeText("tttcanSaveDynamicFields = "1";rn");
		exporter.writeText("ttt};rn");

}

void ForestData::endExporter()
{
	if(isExporter==0)return;
    exporter.writeText("t};rn");
	exporter.close();
}

///FOREST EXPORTER


Inside forestDataFile.cpp around line 127 of function "bool ForestData::read( Stream &stream )"


Change:

// Read in the items.
   stream.read( &count );
   for ( U32 i=0; i < count; i++ )
   {
      stream.read( &dataIndex );
      mathRead( stream, &pos );
      mathRead( stream, &rot );
      stream.read( &scale );

      data = allDatablocks[ dataIndex ];
      if ( data )
      {
         rot.setMatrix( &xfm );
         xfm.setPosition( pos );

         addItem( smNextItemId++, data, xfm, scale );
      }
      else
      {
         skippedItems++;
      }
   }

To:

///FOREST EXPORTER 
	startExporter();
///FOREST EXPORTER 

   // Read in the items.
   stream.read( &count );
   for ( U32 i=0; i < count; i++ )
   {
      stream.read( &dataIndex );
      mathRead( stream, &pos );
      mathRead( stream, &rot );
      stream.read( &scale );

      data = allDatablocks[ dataIndex ];
      if ( data )
      {
         rot.setMatrix( &xfm );
         xfm.setPosition( pos );

///FOREST EXPORTER 
		writeExporter(data, xfm, scale);
///FOREST EXPORTER 
         addItem( smNextItemId++, data, xfm, scale );
      }
      else
      {
         skippedItems++;
      }
   }
///FOREST EXPORTER 
	endExporter();
///FOREST EXPORTER



To the script add to the main "main.cs"

//---------------------------------------------------------------------------------------------
// Torque Game Builder
// Copyright (C) GarageGames.com, Inc.
//---------------------------------------------------------------------------------------------

//---------------------------------------------------------------------------------------------
// Path to the folder that contains the editors we will load.
//---------------------------------------------------------------------------------------------
$Tools::resourcePath = "tools/";

// These must be loaded first, in this order, before anything else is loaded
$Tools::loadFirst = "editorClasses base worldEditor";

//---------------------------------------------------------------------------------------------
// Object that holds the simObject id that the materialEditor uses to interpret its material list
//---------------------------------------------------------------------------------------------
$Tools::materialEditorList = "";

///FOREST EXPORTER 
$Forest::ENABLED=true;   //<======================
///FOREST EXPORTER


To the "scripts/server/game.cs"

Change:

if (isScriptFile("art/forest/managedItemData.cs"))
         exec("art/forest/managedItemData.cs");
      //FOREST CONVERTER
      if (isFile("art/forest/FK_Managed_Dae_DTS_Elements.cs"))//ADD NEW CODE HERE
         exec("art/forest/FK_Managed_Dae_DTS_Elements.cs");
      //FOREST CONVERTER

To:

///FOREST EXPORTER 
   if($Forest::ENABLED==true){
      if (isScriptFile("art/forest/managedItemData.cs"))
         exec("art/forest/managedItemData.cs");
      //FOREST CONVERTER
      if (isFile("art/forest/FK_Managed_Dae_DTS_Elements.cs"))//ADD NEW CODE HERE
         exec("art/forest/FK_Managed_Dae_DTS_Elements.cs");
      //FOREST CONVERTER
   }
///FOREST EXPORTER



To the "core/scripts/server/game.cs"

Change:

if (isScriptFile("art/forest/managedItemData.cs"))
		exec("art/forest/managedItemData.cs");
	//FOREST CONVERTER
	if (isFile("art/forest/FK_Managed_Dae_DTS_Elements.cs"))//ADD NEW CODE HERE
		exec("art/forest/FK_Managed_Dae_DTS_Elements.cs");
	//FOREST CONVERTER

To:

///FOREST EXPORTER 
   if($Forest::ENABLED==true){
      if (isScriptFile("art/forest/managedItemData.cs"))
         exec("art/forest/managedItemData.cs");
      //FOREST CONVERTER
      if (isFile("art/forest/FK_Managed_Dae_DTS_Elements.cs"))//ADD NEW CODE HERE
         exec("art/forest/FK_Managed_Dae_DTS_Elements.cs");
      //FOREST CONVERTER
   }
///FOREST EXPORTER


EDIT<<<<<<<<<<<<<<<<

To the "tools/foresteditor/main.cs"

//-----------------------------------------------------------------------------
// Torque Forest Kit
// Copyright (C) Sickhead Games, LLC
//-----------------------------------------------------------------------------

///FOREST EXPORTER 
if($Forest::ENABLED==false)return; //<<========
///FOREST EXPORTER 

function initializeForestEditor()
{

Usage ---------------------------------------------------------------------



Usage:

With forest editor enabled. Load the scene you want to export with a forest object in it. When the load of the forest is complete it will create an export file to the same directory as the .mis file.

For example if i paint 2 trees on to a map.

HuntersTown:

EX: ~gamelevelsMapsHuntersTown

HuntersTown.forest <= Forest file
HuntersTown.mis <= Mission file
HuntersTown.forestExporter <= First Export
HuntersTown2.forestExporter <= Second Export

The exporter records the last loaded forest. And Keeps track of previous versions.
The exporter contans a folder simgroup for the forest and will hve a tsStatic for each tree,
new SimGroup(ExportedForestItems) {
		locked = "1";
		canSave = "1";
		canSaveDynamicFields = "1";
		new TSStatic() {
			shapeName = "art/ArtPacks/FlowerPower_Items/fp_grnOakFAN008C.dts";
			playAmbient = "1";
			meshCulling = "0";
			originSort = "0";
			collisionType = "Collision Mesh";
			decalType = "Collision Mesh";
			allowPlayerStep = "1";
			renderNormals = "0";
			forceDetail = "-1";
			position = "-57.257729 -61.894714 -2.859917";
			rotation = "0.000000 0.000000 -1.215311 0";
			scale = "1.000000 1.000000 1.000000";
			canSave = "1";
			canSaveDynamicFields = "1";
			};
		new TSStatic() {
			shapeName = "art/ArtPacks/FlowerPower_Items/fp_grnOakFAN008C.dts";
			playAmbient = "1";
			meshCulling = "0";
			originSort = "0";
			collisionType = "Collision Mesh";
			decalType = "Collision Mesh";
			allowPlayerStep = "1";
			renderNormals = "0";
			forceDetail = "-1";
			position = "-51.329670 -59.636295 -3.213763";
			rotation = "0.000000 0.000000 -0.408174 0";
			scale = "1.000000 1.000000 1.000000";
			canSave = "1";
			canSaveDynamicFields = "1";
			};
	};


Just copy the contents of the desired exported forest and copy to the end of the .mis file.

Next we can disable the forest editor.

///FOREST EXPORTER 
$Forest::ENABLED=false;
///FOREST EXPORTER




You mission will now contain the elements you painted using the editor.


Video ---------------------------------------------------------------------



The following is a video of me using 1300 Forest items that I want to use for various maps in my game and the difference of load when using the exported forest as TSStatic items.




HD version on youtube.

#1
03/05/2011 (9:22 am)
nice work Kevin. Definately a time saver on large forests, and reducing the overall datablock load times.
#2
03/05/2011 (11:27 am)
just noticed i missed some parts in to code >.<

EDIT:

Code updated.
#3
03/05/2011 (11:39 am)
Thanks Julian I just want something to fix the load it was killing me. And I didn't want to not use the forest editor.
#4
03/06/2011 (4:19 am)
Updated 7:19 est 3/6/2011
#5
03/07/2011 (1:04 am)
As usual, amazing resource!
Thanks
#6
03/27/2011 (2:22 pm)
good resource!!

@ vincent
i know its off topic but that is a sick setup you have in your pic.