Ejemplo n.º 1
0
Triangle RandomTriangleNearOrigin(float maxDistanceFromOrigin)
{
	return Triangle(RandomPointNearOrigin(maxDistanceFromOrigin), RandomPointNearOrigin(maxDistanceFromOrigin), RandomPointNearOrigin(maxDistanceFromOrigin));
}
Ejemplo n.º 2
0
  void ModelContainerView::generateHeightMap(int pMapId, int x, int y)
  {
      //TODO: Fix this in general.
      //Here we need to load the GridMap from .map file. then generate vertex map from heigh points.
      GridMap mapArray[64][64]; //TODO: make smaller array and recalculate matching gridmap.
      for (int x1 = x-1; x1 <= x+1; ++x1)
        for (int y1 = y-1; y1 <= y+1; ++y1) {
            mapArray[x1][y1] = GridMap();
            char tmp[12];
            sprintf(tmp, "%03u%02u%02u.map",pMapId,x1,y1);
            std::string gmap =  gMapDataDir + "/" + tmp;
            if (mapArray[x1][y1].loadData(gmap.c_str()))
                printf("Loaded %s\n", gmap.c_str());
        }
    float x_min,y_min,x_max, y_max;
    x_max = (32-x)*SIZE_OF_GRIDS + 50;
    y_max = (32-y)*SIZE_OF_GRIDS + 50;
    x_min = (32-x)*SIZE_OF_GRIDS - 533 - 50;
    y_min = (32-y)*SIZE_OF_GRIDS - 533 - 50;
    for (float x = x_min; x < x_max-2;x += 2)
        for (float y = y_min; y < y_max-2;y += 2) {
            int gx,gy;
            // Here we need to add vertexes. so 3 Vector3 for each triangle.
            // FIXME: This is overly efficient since we visit each vector3 multipletimes during loop.
            gx = (int)(32 - x / SIZE_OF_GRIDS);
            gy = (int)(32 - y / SIZE_OF_GRIDS);
            float heightxy = mapArray[gx][gy].getHeight(x,y);
            gx = (int)(32 - (x+2) / SIZE_OF_GRIDS);
            float heightx1y = mapArray[gx][gy].getHeight(x+2,y);
            gx = (int)(32 - x / SIZE_OF_GRIDS);
            gy = (int)(32 - (y+2) / SIZE_OF_GRIDS);
            float heightxy1 = mapArray[gx][gy].getHeight(x,y+2);
            gx = (int)(32 - (x+2) / SIZE_OF_GRIDS);
            float heightx1y1 = mapArray[gx][gy].getHeight(x+2,y+2);
            Vector3 vector1(x,y,heightxy);
            Vector3 vector2(x+2,y,heightx1y);
            Vector3 vector3(x,y+2,heightxy1);
            Vector3 vector4(x+2,y+2,heightx1y1);
            /*
             * vector1 ------ vector2
             *   |     \     /    |
             *   |      \   /     |
             *   |       \ /      |
             *   |        X       |
             *   |       / \      |
             *   |      /   \     |
             *   |     /     \    |
             * vector3 -------- vector4
             */

            Triangle t1 = Triangle(vector1,vector4,vector3);
            Triangle t2 = Triangle(vector1,vector2,vector4);
            // Check if the center of this Triangle is deep under water. (here: 1 meter)
            Vector3 center = t1.center();
            if (mapArray[(int)(32 - center.x / SIZE_OF_GRIDS)][(int)(32 - center.y / SIZE_OF_GRIDS)].getLiquidLevel(center.x,center.y) < center.z - 1.f)
                globalTriangleArray.append(t1);
            center = t2.center();
            if (mapArray[(int)(32 - center.x / SIZE_OF_GRIDS)][(int)(32 - center.y / SIZE_OF_GRIDS)].getLiquidLevel(center.x,center.y) < center.z - 1.f)
                globalTriangleArray.append(t2);
        }
  }
Ejemplo n.º 3
0
                //=================================================================
                bool TileAssembler::readRawFile(std::string& pModelFilename,  ModelPosition& pModelPosition, AABSPTree<SubModel *> *pMainTree)
                {
                    bool result = false;

                    std::string filename = iSrcDir;
                    if(filename.length() >0)
                        filename.append("/");
                    filename.append(pModelFilename);
                    FILE *rf = fopen(filename.c_str(), "rb");
                    if(!rf)
                    {
                        // depending on the extractor version, the data could be located in the root dir
                        std::string baseModelFilename = pModelFilename.substr((pModelFilename.find_first_of("/")+1),pModelFilename.length());
                        filename = iSrcDir;
                        if(filename.length() >0)
                            filename.append("/");
                        filename.append(baseModelFilename);
                        rf = fopen(filename.c_str(), "rb");
                    }
                    char ident[8];

                    int trianglecount =0;

                    #ifdef _ASSEMBLER_DEBUG
                    int startgroup = 0;                     //2;
                    int endgroup = INT_MAX;                 //2;
                    fprintf(::g_df,"-------------------------------------------------\n");
                    fprintf(::g_df,"%s\n", pModelFilename.c_str());
                    fprintf(::g_df,"-------------------------------------------------\n");
                    #else
                    int startgroup = 0;
                    int endgroup = INT_MAX;
                    #endif

                    if(rf)
                    {
                        if(fread(&ident, 8, 1, rf) != 1) { fclose(rf); return(false); }
                        if(strcmp(ident, "VMAP001") == 0)
                        {
                            // OK, do nothing
                        }
                        else if(strcmp(ident, "VMAP002") == 0)
                        {
                            // we have to read one int. This is needed during the export and we have to skip it here
                            int tempNVectors;
                            if(fread(&tempNVectors, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }

                        }
                        else
                        {
                            // wrong version
                            fclose(rf);
                            return(false);
                        }
                        uint32 groups;
                        char blockId[5];
                        blockId[4] = 0;
                        int blocksize;

                        if(fread(&groups, sizeof(uint32), 1, rf) != 1) { fclose(rf); return(false); }

                        for(int g=0;g<(int)groups;g++)
                        {
                            // group MUST NOT have more then 65536 indexes !! Array will have a problem with that !! (strange ...)
                            Array<int> tempIndexArray;
                            Array<Vector3> tempVertexArray;

                            AABSPTree<Triangle> *gtree = new AABSPTree<Triangle>();

                            uint32 flags;
							uint32 isindoor;
							if(fread(&isindoor, sizeof(uint32), 1, rf) != 1) { fclose(rf); return(false); }
							if(fread(&flags, sizeof(uint32), 1, rf) != 1) { fclose(rf); return(false); }

                            uint32 branches;
                            if(fread(&blockId, 4, 1, rf) != 1) { fclose(rf); return(false); }
                            if(strcmp(blockId, "GRP ") != 0) { fclose(rf); return(false); }
                            if(fread(&blocksize, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
                            if(fread(&branches, sizeof(uint32), 1, rf) != 1) { fclose(rf); return(false); }
                            for(int b=0;b<(int)branches; b++)
                            {
                                uint32 indexes;
                                // indexes for each branch (not used jet)
                                if(fread(&indexes, sizeof(uint32), 1, rf) != 1) { fclose(rf); return(false); }
                            }

                            // ---- indexes
                            if(fread(&blockId, 4, 1, rf) != 1) { fclose(rf); return(false); }
                            if(strcmp(blockId, "INDX") != 0) { fclose(rf); return(false); }
                            if(fread(&blocksize, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
                            unsigned int nindexes;
                            if(fread(&nindexes, sizeof(uint32), 1, rf) != 1) { fclose(rf); return(false); }
                            if(nindexes >0)
                            {
                                unsigned short *indexarray = new unsigned short[nindexes*sizeof(unsigned short)];
                                if(fread(indexarray, sizeof(unsigned short), nindexes, rf) != nindexes) { fclose(rf); return(false); }
                                for(int i=0;i<(int)nindexes; i++)
                                {
                                    unsigned short val = indexarray[i];
                                    tempIndexArray.append(val);
                                }
                                delete indexarray;
                            }

                            // ---- vectors
                            if(fread(&blockId, 4, 1, rf) != 1) {fclose(rf); return(false); }
                            if(strcmp(blockId, "VERT") != 0) { fclose(rf); return(false); }
                            if(fread(&blocksize, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
                            unsigned int nvectors;
                            if(fread(&nvectors, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
                            float *vectorarray = 0;
                            if(nvectors >0)
                            {
                                vectorarray = new float[nvectors*sizeof(float)*3];
                                if(fread(vectorarray, sizeof(float)*3, nvectors, rf) != nvectors) { fclose(rf); return(false); }
                            }
                            // ----- liquit
                            if(flags & 1)
                            {
                                // we have liquit -> not handled yet ... skip
                                if(fread(&blockId, 4, 1, rf) != 1) { fclose(rf); return(false); }
                                if(strcmp(blockId, "LIQU") != 0) { fclose(rf); return(false); }
                                if(fread(&blocksize, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
                                fseek(rf, blocksize, SEEK_CUR);
                            }

                            for(unsigned int i=0, indexNo=0; indexNo<nvectors; indexNo++)
                            {
                                Vector3 v = Vector3(vectorarray[i+2], vectorarray[i+1], vectorarray[i+0]);
                                i+=3;
                                v = pModelPosition.transform(v);

                                float swapy = v.y;
                                v.y = v.x;
                                v.x = swapy;

                                tempVertexArray.append(v);
                            }

                            // ---- calculate triangles
                            int rest = nindexes%3;
                            if(rest != 0)
                            {
                                nindexes -= rest;
                            }

                            for(unsigned int i=0;i<(nindexes);)
                            {
                                Triangle t = Triangle(tempVertexArray[tempIndexArray[i+2]], tempVertexArray[tempIndexArray[i+1]], tempVertexArray[tempIndexArray[i+0]] );
                                i+=3;
                                trianglecount++;
                                if(g>= startgroup && g <= endgroup)
                                {
                                    gtree->insert(t);
                                }
                            }

                            if(vectorarray != 0)
                            {
                                delete vectorarray;
                            }

                            if(gtree->size() >0)
                            {
                                gtree->balance();
                                SubModel *sm = new SubModel(gtree);
								sm->setIndoorFlag( isindoor );
                                #ifdef _ASSEMBLER_DEBUG
                                if(::g_df) fprintf(::g_df,"group trianglies: %d, Tris: %d, Nodes: %d, gtree.triangles: %d\n", g, sm->getNTriangles(), sm->getNNodes(), gtree->memberTable.size());
                                if(sm->getNTriangles() !=  gtree->memberTable.size())
                                {
                                    if(::g_df) fprintf(::g_df,"ERROR !!!! group trianglies: %d, Tris: %d, Nodes: %d, gtree.triangles: %d\n", g, sm->getNTriangles(), sm->getNNodes(), gtree->memberTable.size());
                                }
                                #endif
                                sm->setBasePosition(pModelPosition.iPos);
                                pMainTree->insert(sm);
                            }
                            delete gtree;
                        }
                        fclose(rf);
                        result = true;
                    }
                    return(result);
                }
Ejemplo n.º 4
0
void Polygon::AddTriangle(int a, int b, int c)
{
	triangles.push_back(Triangle(a, b, c));
}
Ejemplo n.º 5
0
bool File::load_binarySTL(vector<Triangle> &triangles,
			  uint max_triangles, bool readnormals)
{
    ifstream file;
    ustring filename = _file->get_path();
    file.open(filename.c_str(), ifstream::in | ifstream::binary);

    if(file.fail()) {
      cerr << _("Error: Unable to open stl file - ") << filename << endl;
      return false;
    }
    // cerr << "loading bin " << filename << endl;

    /* Binary STL files have a meaningless 80 byte header
     * followed by the number of triangles */
    file.seekg(80, ios_base::beg);
    unsigned int num_triangles;
    unsigned char buffer[4];
    file.read(reinterpret_cast <char *> (buffer), 4);
    // Read platform independent 32-bit little-endian int.
    num_triangles = buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24;

    uint step = 1;
    if (max_triangles > 0 && max_triangles < num_triangles) {
      step = ceil(num_triangles/max_triangles);
      triangles.reserve(max_triangles);
    } else
      triangles.reserve(num_triangles);

    uint i = 0;
    for(; i < num_triangles; i+=step)
    {
      if (step>1)
	file.seekg(84 + 50*i, ios_base::beg);

      double a,b,c;
        a = read_double (file);
        b = read_double (file);
        c = read_double (file);
        Vector3d N(a,b,c);
        a = read_double (file);
        b = read_double (file);
        c = read_double (file);
        Vector3d Ax(a,b,c);
        a = read_double (file);
        b = read_double (file);
        c = read_double (file);
        Vector3d Bx(a,b,c);
        a = read_double (file);
        b = read_double (file);
        c = read_double (file);
        Vector3d Cx(a,b,c);

        if (file.eof()) {
            cerr << _("Unexpected EOF reading STL file - ") << filename << endl;
            break;
        }

        /* attribute byte count - sometimes contains face color
            information but is useless for our purposes */
        unsigned short byte_count;
        file.read(reinterpret_cast <char *> (buffer), 2);
	byte_count = buffer[0] | buffer[1] << 8;
	// Repress unused variable warning.
	(void)&byte_count;

	Triangle T = Triangle(Ax,Bx,Cx);
	if (readnormals)
	  if (T.Normal.dot(N) < 0) T.invertNormal();

	// cout << "bin triangle "<< N << ":\n\t" << Ax << "/\n\t"<<Bx << "/\n\t"<<Cx << endl;
        triangles.push_back(T);
    }
    file.close();

    return true;
    // cerr << "Read " << i << " triangles of " << num_triangles << " from file" << endl;
}
Ejemplo n.º 6
0
		void Mesh::addTriangle(dword v0, dword v1, dword v2, dword uv0, dword uv1, dword uv2)
		{
			addTriangle(Triangle(v0, v1, v2, uv0, uv1, uv2, material, texture));
		}
Ejemplo n.º 7
0
void Terrain::GenerateHeightMap(int Iterations, double Height, double HDecay)
{
	HeightMap.calculate(Iterations, Height, HDecay);	
	int Select = 1 + rand() % (4 - 1 + 1);		
	// Load .3DS file into model structure	
	if(Select == 1)
	{
		GenerateTerrainObjects(50, 2 , 40, 10);
		g_Load3ds.Import3DS(&g_3DModel, "Textures/Tilesets/Desert/Models/PILLAR.3DS");
		double Ratio = 0.25;
		O1Offset = 0.0f;
		BuildLists(Ratio, 1, g_3DModel);		
		for(int i = 0; i < g_3DModel.numOfObjects; i++)
		{
			// Free the faces, normals, vertices, and texture coordinates.
			delete [] g_3DModel.pObject[i].pFaces;
			delete [] g_3DModel.pObject[i].pNormals;
			delete [] g_3DModel.pObject[i].pVerts;
			delete [] g_3DModel.pObject[i].pTexVerts;
		}	
		
		g_Load3ds.Import3DS(&g_3DModel1, "Textures/Tilesets/Desert/Models/STATUE.3DS");
		Ratio = 0.25;
		O1Offset = 0.0f;
		BuildLists(Ratio, 2, g_3DModel1);

		// Go through all the objects in the scene
		for(int i = 0; i < g_3DModel1.numOfObjects; i++)
		{
			// Free the faces, normals, vertices, and texture coordinates.
			delete [] g_3DModel1.pObject[i].pFaces;
			delete [] g_3DModel1.pObject[i].pNormals;
			delete [] g_3DModel1.pObject[i].pVerts;
			delete [] g_3DModel1.pObject[i].pTexVerts;
		}			
	}
	else if(Select == 2)
	{		
		GenerateTerrainObjects(100, 2 , 50, 50);
		g_Load3ds.Import3DS(&g_3DModel, "Textures/Tilesets/Mountains/Models/PINE.3DS");
		double Ratio = 0.25;
		O1Offset = 15.5f;
		BuildLists(Ratio, 1, g_3DModel);		
		for(int i = 0; i < g_3DModel.numOfObjects; i++)
		{
			// Free the faces, normals, vertices, and texture coordinates.
			delete [] g_3DModel.pObject[i].pFaces;
			delete [] g_3DModel.pObject[i].pNormals;
			delete [] g_3DModel.pObject[i].pVerts;
			delete [] g_3DModel.pObject[i].pTexVerts;
		}	
		
		g_Load3ds.Import3DS(&g_3DModel1, "Textures/Tilesets/Mountains/Models/MAPLE.3DS");
		Ratio = 5.0;
		O2Offset = 0.0f;
		BuildLists(Ratio, 2, g_3DModel1);

		// Go through all the objects in the scene
		for(int i = 0; i < g_3DModel1.numOfObjects; i++)
		{
			// Free the faces, normals, vertices, and texture coordinates.
			delete [] g_3DModel1.pObject[i].pFaces;
			delete [] g_3DModel1.pObject[i].pNormals;
			delete [] g_3DModel1.pObject[i].pVerts;
			delete [] g_3DModel1.pObject[i].pTexVerts;
		}		
	}
	else if(Select == 3)
	{
		GenerateTerrainObjects(100, 2 , 50, 50);
		g_Load3ds.Import3DS(&g_3DModel, "Textures/Tilesets/Tropics/Models/TREE3.3DS");
		double Ratio = 0.5;
		O1Offset = 0.0f;
		BuildLists(Ratio, 1, g_3DModel);		
		for(int i = 0; i < g_3DModel.numOfObjects; i++)
		{
			// Free the faces, normals, vertices, and texture coordinates.
			delete [] g_3DModel.pObject[i].pFaces;
			delete [] g_3DModel.pObject[i].pNormals;
			delete [] g_3DModel.pObject[i].pVerts;
			delete [] g_3DModel.pObject[i].pTexVerts;
		}	
		
		g_Load3ds.Import3DS(&g_3DModel1, "Textures/Tilesets/Tropics/Models/PALM.3DS");
		Ratio = 0.75;
		O2Offset = 10.0f;
		BuildLists(Ratio, 2, g_3DModel1);

		// Go through all the objects in the scene
		for(int i = 0; i < g_3DModel1.numOfObjects; i++)
		{
			// Free the faces, normals, vertices, and texture coordinates.
			delete [] g_3DModel1.pObject[i].pFaces;
			delete [] g_3DModel1.pObject[i].pNormals;
			delete [] g_3DModel1.pObject[i].pVerts;
			delete [] g_3DModel1.pObject[i].pTexVerts;
		}		
	
	}
	else if(Select == 4)
	{		
		GenerateTerrainObjects(100, 2 , 75, 15);
		g_Load3ds.Import3DS(&g_3DModel, "Textures/Tilesets/Volcanic/Models/DEADTREE.3DS");
		double Ratio = 0.1;
		O1Offset = -1.0f;
		BuildLists(Ratio, 1, g_3DModel);		
		for(int i = 0; i < g_3DModel.numOfObjects; i++)
		{
			// Free the faces, normals, vertices, and texture coordinates.
			delete [] g_3DModel.pObject[i].pFaces;
			delete [] g_3DModel.pObject[i].pNormals;
			delete [] g_3DModel.pObject[i].pVerts;
			delete [] g_3DModel.pObject[i].pTexVerts;
		}	
		
		g_Load3ds.Import3DS(&g_3DModel1, "Textures/Tilesets/Volcanic/Models/TREE1.3DS");
		Ratio = 0.15;
		O2Offset = 2.0f;
		BuildLists(Ratio, 2, g_3DModel1);

		// Go through all the objects in the scene
		for(int i = 0; i < g_3DModel1.numOfObjects; i++)
		{
			// Free the faces, normals, vertices, and texture coordinates.
			delete [] g_3DModel1.pObject[i].pFaces;
			delete [] g_3DModel1.pObject[i].pNormals;
			delete [] g_3DModel1.pObject[i].pVerts;
			delete [] g_3DModel1.pObject[i].pTexVerts;
		}	
	
	}
	SurfaceCreator s1 = SurfaceCreator(HeightMap.Height_Map, HeightMap.getTerrainSize() - 1, static_cast<float>(Height), Select);
	multitextureSupported = initMultitexture();

	TriangleTree.ExpandNode(TriangleTree.root);
	Node* Current = TriangleTree.root;
	
	//Create Triangle t1	
	Vector Apex = Vector(0, 0, HeightMap.Height_Map[0][0]);
	Vector Left = Vector(0, static_cast<float>(HeightMap.getTerrainSize() - 1), HeightMap.Height_Map[0][HeightMap.getTerrainSize() - 1]);
	Vector Right = Vector(static_cast<float>(HeightMap.getTerrainSize() - 1), 0,HeightMap.Height_Map[HeightMap.getTerrainSize() - 1][0] );
	Triangle t = Triangle(Apex, Left, Right);
	for(int i = 0; i < 100; i++)
	{	
		if(PointInTriangle(Vector(Forests[i].x, Forests[i].y), Apex, Left, Right))	
		{
			t.Tree.push_back(Forests[i]);
		}
	}
	double E = CalculateError(Left, Right);		
	Current->LeftChild->BaseNeighbour = Current->RightChild;
	TriangleTree.InsertAtNode(Current->LeftChild, t, E);	

	// Create Triangle t2	
	Apex.set(static_cast<float>(HeightMap.getTerrainSize() - 1) , static_cast<float>(HeightMap.getTerrainSize() - 1), HeightMap.Height_Map[HeightMap.getTerrainSize() - 1][HeightMap.getTerrainSize() - 1]);
	Left.set(static_cast<float>(HeightMap.getTerrainSize() - 1), 0, HeightMap.Height_Map[HeightMap.getTerrainSize() - 1][0]);
	Right.set(0, static_cast<float>(HeightMap.getTerrainSize() - 1), HeightMap.Height_Map[0][HeightMap.getTerrainSize() - 1]);
	Triangle t2 = Triangle(Apex, Left, Right);	
	for(int i = 0; i < 100; i++)
	{	
		if(PointInTriangle(Vector(Forests[i].x, Forests[i].y), Apex, Left, Right))
		{
			t2.Tree.push_back(Forests[i]);
		}
	}	
	Current->RightChild->BaseNeighbour = Current->LeftChild;
	TriangleTree.InsertAtNode(Current->RightChild, t2, E);	

	LoadTGA(&SkyBoxTexture, "SkyBox/CLOUDS.tga");
	LoadGLTextures(&WaterTexture, "Textures/WATER1.bmp");
	LoadGLTextures(&SurfaceTexture , "Data/Surface.bmp");
	LoadGLTextures(&ShadowTexture  , "Data/Shadows.bmp");	
}
Ejemplo n.º 8
0
void Terrain::SplitTriangle(Node* T)
{
	Triangle t = TriangleTree.getCurrentNode(T);
	TriangleTree.ExpandNode(T);
	
	// Step 1 : Get the old triangles points		
	Vector Apex = t.Apex;
	Vector Left = t.Left;
	Vector Right = t.Right;

	// Step 2 : Get new Apex point which is the midpoint between Left and Right		
	int lx = static_cast<int>(Left.x);
	int ly = static_cast<int>(Left.y);
	int rx = static_cast<int>(Right.x);
	int ry = static_cast<int>(Right.y);
	Vector newApex = Vector(static_cast<float>((lx + rx) / 2), static_cast<float>((ly + ry) / 2));    

	// Step 3 : Create first triangle and add to tree ( This is left half of old triangle )	
	double TriangleLeft = CalculateError(Apex , Left);				
	Triangle NewTLeft = Triangle(newApex, Apex, Left); // Apex = new Apex, Left = old Left, Right = Old Apex			
	for(int i = 0; (unsigned)i < t.Tree.size(); i++)
	{	
		Vector Current = t.Tree[i];
		if(PointInTriangle(Vector(Current.x, Current.y), Vector(newApex.x, newApex.y), Vector(Apex.x, Apex.y), Vector(Left.x, Left.y)))		
		{
			NewTLeft.Tree.push_back(Current);			
		}
	}

	// Step 4 : Create the second triangle and add to tree	
	double TriangleRight = CalculateError(Right , Apex);				
	Triangle NewTRight = Triangle(newApex, Right, Apex);	
	for(int i = 0; (unsigned)i < t.Tree.size(); i++)
	{	
		Vector Current = t.Tree[i];
		if(PointInTriangle(Vector(Current.x, Current.y), Vector(newApex.x, newApex.y), Vector(Right.x, Right.y), Vector(Apex.x, Apex.y) ))	
		{
			NewTRight.Tree.push_back(Current);			
		}
	}


	T->LeftChild->LeftNeighbour = T->RightChild;
	T->RightChild->RightNeighbour = T->LeftChild;	
	T->LeftChild->BaseNeighbour = T->LeftNeighbour;	
	T->RightChild->BaseNeighbour = T->RightNeighbour;
	
	if(T->LeftNeighbour != NULL)
	{		    
	   	if(T->LeftNeighbour->BaseNeighbour == T)
		{	
          	T->LeftNeighbour->BaseNeighbour = T->LeftChild;
			T->LeftNeighbour->Parent->RightNeighbour = T->LeftChild;		
		}
		else
		{		 
			T->LeftNeighbour->RightNeighbour = T->LeftChild;
		}
	}
	if(T->RightNeighbour != NULL)
	{
		if(T->RightNeighbour->BaseNeighbour == T)
		{		    
			T->RightNeighbour->BaseNeighbour = T->RightChild;
			T->RightNeighbour->Parent->LeftNeighbour = T->RightChild;
		}
		else
		{ 			    
			T->RightNeighbour->LeftNeighbour = T->RightChild;
		}
	}	
	TriangleTree.InsertAtNode(T->LeftChild, NewTLeft, TriangleLeft);
	TriangleTree.InsertAtNode(T->RightChild, NewTRight, TriangleRight);	
}
	//! Slower Ray intersection check, can return intersection point
	bool CollisionUtils::AABBox3DSlowRayIntersectionCheck(const AABBox3D& box, const Vector3& rayStart, const Vector3& rayEnd, Vector3* pIntersection)
	{
		Vector3 vTop1 = Vector3::Create(box.Min().X, box.Max().Y, box.Min().Z); 
		Vector3 vTop2 = Vector3::Create(box.Max().X, box.Max().Y, box.Min().Z); 
		Vector3 vTop3 = Vector3::Create(box.Min().X, box.Max().Y, box.Max().Z); 
		Vector3 vTop4 = Vector3::Create(box.Max().X, box.Max().Y, box.Max().Z); 

		Vector3 vBottom1 = Vector3::Create(box.Min().X, box.Min().Y, box.Min().Z); 
		Vector3 vBottom2 = Vector3::Create(box.Max().X, box.Min().Y, box.Min().Z); 
		Vector3 vBottom3 = Vector3::Create(box.Min().X, box.Min().Y, box.Max().Z); 
		Vector3 vBottom4 = Vector3::Create(box.Max().X, box.Min().Y, box.Max().Z); 

		Vector3 rayDir = (rayEnd - rayStart).Normalize();

		Plane Planes[6] = 
		{
			Plane(vTop1, vTop2, vTop3),
			Plane(vBottom1, vBottom2, vBottom3),			
			Plane(vTop3, vTop4, vBottom3),
			Plane(vTop1, vTop2, vBottom1),
			Plane(vTop1, vTop3, vBottom1),
			Plane(vTop2, vTop4, vBottom2)
		};

		Triangle Triangles[12] =
		{
			Triangle(vTop1, vTop2, vTop3),
			Triangle(vTop2, vTop3, vTop4),
			Triangle(vBottom1, vBottom2, vBottom3),
			Triangle(vBottom2, vBottom3, vBottom4),
			Triangle(vTop3, vTop4, vBottom3),
			Triangle(vBottom3, vTop4, vBottom4),
			Triangle(vTop1, vTop2, vBottom1),
			Triangle(vBottom1, vTop2, vBottom2),
			Triangle(vTop1, vTop3, vBottom1),
			Triangle(vBottom1, vTop3, vBottom3),
			Triangle(vTop2, vTop4, vBottom2),
			Triangle(vBottom2, vTop4, vBottom4)
		};

		// TODO: register all intersections, sort them, and pick closest to ray start
		for(u32 i=0; i<6; ++i)
		{
			if(Planes[i].IntersectWithRay(rayStart, rayDir, pIntersection))
			{
				if(Triangles[i*2+0].IsPointInside(*pIntersection)
				|| Triangles[i*2+1].IsPointInside(*pIntersection))
				{
					return true;
				}
			}
		}
		return false;
	}