Mesh::Mesh(vector<Vertex> vertices, vector<Texture> textures, vector<glm::uvec3> indices, float max_X, float max_Y, float max_Z/*, vector<int>  edgeIndicesToIndices*/)
{
    this->vertices = vertices;
    this->textures = textures;
    this->indices = indices;
    //this->faceEdgeIndicesToIndices = edgeIndicesToIndices;

    //create_indices();
    //shrink_vertices();
    getAdjacentFacesVector();
    //calcMax();
    maxX = max_X;
    maxY = max_Y;
    maxZ = max_Z;
    calculateVertexNormals();
}
int CObject::loadObject(std::string path){

	std::fstream file(path, std::fstream::in | std::fstream::out);
	if (!file.is_open()){
		std::cout << "No se pudo abrir el archivo" << std::endl; 
		return 0;
	}
		int i, j, indexMinMax = 0, numF;
		GLfloat point;
		std::vector <GLuint> fc,ft;
		GLuint pt;
		std::string type;
		file >> type;
		j = 0;
		fc.clear();
		while (!file.eof()){
			std::string subtype = type.substr(0, 1);
			std::string line;
			if (subtype == "#"){
				std::getline(file, line);
			}
			if (type == "vt"){
				std::getline(file, line);
			}
			if (type == "vn"){
				std::getline(file, line);
			} //List of Vertex
			if (type == "v"){
				for (i = 0; i < 3; i++){
					file >> point;
					mVertex.push_back(point);
					switch (i){
					case 0:
						if (xmin == NULL){
							xmin = point;
						}
						else{
							if (point < xmin) xmin = point;
						}
						if (xmax == NULL){
							xmax = point;
						}
						else{
							if (point > xmax) xmax = point;
						}
						break;
					case 1:
						if (ymin == NULL){
							ymin = point;
						}
						else{
							if (point < ymin) ymin = point;
						}
						if (ymax == NULL){
							ymax = point;
						}
						else{
							if (point > ymax) ymax = point;
						}
						break;
					case 2:
						if (zmin == NULL){
							zmin = point;
						}
						else{
							if (point < zmin) zmin = point;
						}
						if (zmax == NULL){
							zmax = point;
						}
						else{
							if (point > zmax) zmax = point;
						}
						break;
					}

				}
				mColor.push_back(0);
				mColor.push_back(1);
				mColor.push_back(0);
				nVertex++;
				//
				//calculateMinMax(indexMinMax);
				indexMinMax++;
				//
				}//List of Faces
				if (type == "f"){
					std::getline(file, line);
					char * tok = strtok(&line[0u], " ");
					while (tok != NULL){
						std::string num = tok;
						std::size_t pos = num.find("/");
						num = num.substr(0, pos);
						pt = stoi(num);
						fc.push_back(pt);
						tok = strtok(NULL, " ");
					}
					nFaces++;
					for (j = 1; j < fc.size() - 1; j++){
						mIndexes.push_back(fc[0] - 1);
						mIndexes.push_back(fc[j] - 1);
						mIndexes.push_back(fc[j + 1] - 1);
					}
					fc.clear();
				}
				file >> type;
			}

		xmid = (xmin + xmax) / 2;
		ymid = (ymin + ymax) / 2;
		zmid = (zmin + zmax) / 2;

		calculateFaceNormals();
		calculateVertexNormals();

		//Initialize buffer

		file.close();
		std::cout << "Object loaded" << std::endl;
		return 1;
}
//function to pass all the array buffers into the openGL vertex buffers
//P.S - This function has to be called in the end, once all the attributes for the objects have been set.
void Object::initBuffers(const GLuint& program){

	cout << "Normals Size: " << normals.size() << endl;
	cout << "Tangents Size: " << tangents.size() << endl;

	//get the attribute ids
	GLuint vertexAttributeID = glGetAttribLocation(program, "vPosition");
	GLuint normalAttributeID = glGetAttribLocation(program, "vNormal");
	GLuint uvAttributeID = glGetAttribLocation(program, "vTexCoord");
	GLuint tangentAttributeID = glGetAttribLocation(program, "vTangent");

	outVertices = new float[faces.size() * 3 * 3];
	outNormals = new float[faces.size() * 3 * 3];
	Vec3f v, n, t;
	int index = 0;
	for(unsigned i = 0; i < faces.size(); i++){
		n = normals.at(faces.at(i)->n);
		if (tangents.size() > 0){
			t = tangents.at(faces.at(i)->t);
		}

		for (unsigned j = 0; j < 3; j++){
			v = points.at((*faces.at(i))[j]);
			outVertices[index] = v.x;
			outVertices[index + 1] = v.y;
			outVertices[index + 2] = v.z;

			if(!smooth){
				outNormals[index] = n.x;
				outNormals[index + 1] = n.y;
				outNormals[index + 2] = n.z;

				if (t != Vec3f()){
					outTangents[index] = t.x;
					outTangents[index + 1] = t.y;
					outTangents[index + 2] = t.z;
				}
			}

			index += 3;
		}
	}

	if (smooth){
		calculateVertexNormals();
		if (tangents.size() > 0){
			calculateVertexTangents();
		}
	}

	glBindVertexArray(vao);

	glGenBuffers(4, vbo);

	//pass the vertex buffers
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glBufferData(GL_ARRAY_BUFFER, faces.size() * 3 * 3 * sizeof(float), outVertices, GL_STATIC_DRAW);
	glEnableVertexAttribArray(vertexAttributeID);
	glVertexAttribPointer(vertexAttributeID, 3, GL_FLOAT, GL_FALSE, 0, 0);

	//pass the normal buffers (face or vertex)
	glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
	if(smooth)
		glBufferData(GL_ARRAY_BUFFER, faces.size() * 3 * 3 * sizeof(float), outVertexNormals, GL_STATIC_DRAW);
	else
		glBufferData(GL_ARRAY_BUFFER, faces.size() * 3 * 3 * sizeof(float), outNormals, GL_STATIC_DRAW);
	glEnableVertexAttribArray(normalAttributeID);
	glVertexAttribPointer(normalAttributeID, 3, GL_FLOAT, GL_FALSE, 0, 0);

	if(uv.size() > 0){

		outUV = new float[uv.size() * 2];
		index = 0;

		for(unsigned i = 0; i < uv.size(); i++){
			outUV[index] = uv.at(i).x;
			outUV[index + 1] = uv.at(i).y;
			index += 2;
		}
		//pass the uv coord buffers
		glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
		glBufferData(GL_ARRAY_BUFFER, uv.size() * 2 * sizeof(float), outUV, GL_STATIC_DRAW);
		glEnableVertexAttribArray(uvAttributeID);
		glVertexAttribPointer(uvAttributeID, 2, GL_FLOAT, GL_FALSE, 0, 0);
	}

	if (tangents.size() > 0){
		glBindBuffer(GL_ARRAY_BUFFER, vbo[3]);
		if (smooth)
			glBufferData(GL_ARRAY_BUFFER, faces.size() * 3 * 3 * sizeof(float), outVertexTangents, GL_STATIC_DRAW);
		else
			glBufferData(GL_ARRAY_BUFFER, faces.size() * 3 * 3 * sizeof(float), outTangents, GL_STATIC_DRAW);
		glEnableVertexAttribArray(tangentAttributeID);
		glVertexAttribPointer(tangentAttributeID, 3, GL_FLOAT, GL_FALSE, 0, 0);
	}

}
IndexedFaceSetNode::IndexedFaceSetNode(VRMLParser& parser)
	:ccw(true),solid(true),convex(true),
	 colorPerVertex(true),
	 normalPerVertex(true),creaseAngle(0.0f)
	{
	/* Check for the opening brace: */
	if(!parser.isToken("{"))
		Misc::throwStdErr("IndexedFaceSetNode::IndexedFaceSetNode: Missing opening brace in node definition");
	parser.getNextToken();
	
	/* Process attributes until closing brace: */
	while(!parser.isToken("}"))
		{
		if(parser.isToken("ccw"))
			{
			parser.getNextToken();
			ccw=SFBool::parse(parser);
			}
		else if(parser.isToken("solid"))
			{
			parser.getNextToken();
			solid=SFBool::parse(parser);
			}
		else if(parser.isToken("convex"))
			{
			parser.getNextToken();
			convex=SFBool::parse(parser);
			}
		else if(parser.isToken("colorPerVertex"))
			{
			parser.getNextToken();
			colorPerVertex=SFBool::parse(parser);
			}
		else if(parser.isToken("normalPerVertex"))
			{
			parser.getNextToken();
			normalPerVertex=SFBool::parse(parser);
			}
		else if(parser.isToken("creaseAngle"))
			{
			parser.getNextToken();
			creaseAngle=SFFloat::parse(parser);
			}
		else if(parser.isToken("texCoord"))
			{
			/* Parse the texture coordinate node: */
			parser.getNextToken();
			texCoord=parser.getNextNode();
			}
		else if(parser.isToken("color"))
			{
			/* Parse the color node: */
			parser.getNextToken();
			color=parser.getNextNode();
			}
		else if(parser.isToken("normal"))
			{
			/* Parse the normal node: */
			parser.getNextToken();
			normal=parser.getNextNode();
			}
		else if(parser.isToken("coord"))
			{
			/* Parse the coordinate node: */
			parser.getNextToken();
			coord=parser.getNextNode();
			}
		else if(parser.isToken("texCoordIndex"))
			{
			/* Parse the texture coordinate index array: */
			parser.getNextToken();
			texCoordIndices=MFInt32::parse(parser);
			}
		else if(parser.isToken("colorIndex"))
			{
			/* Parse the color index array: */
			parser.getNextToken();
			colorIndices=MFInt32::parse(parser);
			}
		else if(parser.isToken("normalIndex"))
			{
			/* Parse the normal vector index array: */
			parser.getNextToken();
			normalIndices=MFInt32::parse(parser);
			}
		else if(parser.isToken("coordIndex"))
			{
			/* Parse the coordinate index array: */
			parser.getNextToken();
			coordIndices=MFInt32::parse(parser);
			
			/* Terminate the coordinate index array: */
			if(coordIndices.back()>=0)
				coordIndices.push_back(-1);
			}
		else
			Misc::throwStdErr("IndexedFaceSetNode::IndexedFaceSetNode: unknown attribute \"%s\" in node definition",parser.getToken());
		}
	
	/* Skip the closing brace: */
	parser.getNextToken();
	
	/* Create normal vectors if necessary: */
	CoordinateNode* c=dynamic_cast<CoordinateNode*>(coord.getPointer());
	NormalNode* n=dynamic_cast<NormalNode*>(normal.getPointer());
	if(coord!=0&&n==0)
		{
		/* Create a new normal node and clear the normal index array: */
		n=new NormalNode;
		normal=n;
		normalIndices.clear();
		
		/* Create normal vectors and normal indices: */
		if(normalPerVertex)
			calculateVertexNormals(c,coordIndices,Math::cos(creaseAngle),n,normalIndices);
		else
			calculateFaceNormals(c,coordIndices,n);
		}
	}
Beispiel #5
0
Model::Model(const char* filename)
{
  char lineBuf[1024];

  FILE* f = fopen(filename, "r");

  // Initialize the extents - hopefully 1e10 is big enough!
  mExtents.minX = 1e10;
  mExtents.maxX = -1e10;
  mExtents.minY = 1e10;
  mExtents.maxY = -1e10;
  mExtents.minZ = 1e10;
  mExtents.maxZ = -1e10;

  // Read the list of points
  while(!feof(f)){
    // Read the first character, ignoring whitespace
    char type1, type2;
    fscanf(f, " %c%c", &type1, &type2);
    if(type1 == 'v' && type2 == ' '){ // Vertex
      float x, y, z;
      fscanf(f, "%f %f %f", &x, &y, &z); // Read the three coordinates
      mVertices.push_back(point3(x, y, z)); // Save them in the vector
      if(x < mExtents.minX){ mExtents.minX = x; }
      if(y < mExtents.minY){ mExtents.minY = y; }
      if(z < mExtents.minZ){ mExtents.minZ = z; }
      if(x > mExtents.maxX){ mExtents.maxX = x; }
      if(y > mExtents.maxY){ mExtents.maxY = y; }
      if(z > mExtents.maxZ){ mExtents.maxZ = z; }
    }
    else if(type1 == 'v' && type2 == 'n'){ // Vertex normal
      float x, y, z;
      fscanf(f, "%f %f %f", &x, &y, &z);
      mVertexNormals.push_back(point3(x, y, z));
    }
    else if(type1 == 'v' && type2 == 't'){ // Texture coordinate
      float x, y, z;
      fscanf(f, "%f %f %f", &x, &y, &z);
      mTextureCoords.push_back(point3(x, y, z));
    }
    else if(type1 == 'f'){ // Face
      // This could be specified as either "f A B C" or as "f A/Anorm/Atex B/Bnorm/Btex ..."
      fscanf(f, " %[^\n]", lineBuf);
      if(strchr(lineBuf, '/')){
        unsigned int a, aNorm, aTex, b, bNorm, bTex, c, cNorm, cTex;
        sscanf(lineBuf, "%d/%d/%d %d/%d/%d %d/%d/%d", 
                        &a, &aNorm, &aTex, &b, &bNorm, &bTex, &c, &cNorm, &cTex);
        mTriangles.push_back(triangle(a-1, b-1, c-1));
      }
      else{
        unsigned int a, b, c;
        sscanf(lineBuf, "%d %d %d", &a, &b, &c); // Read the three indices
        mTriangles.push_back(triangle(a-1, b-1, c-1)); // Save them in the vector
      }
    }
    else if(type1 == '#'){
      // Comment; eat up the whole line
      fscanf(f, " %[^\n]", lineBuf);
    }
    else{
      LOGI("Unexpected input character '%c' while reading OBJ file %s\n", type1, filename);
      fscanf(f, " %[^\n]", lineBuf); // Eat the whole line
    }
  }

  LOGI("Loaded model %s with %ld vertices, %ld faces\n", filename, mVertices.size(), mTriangles.size());

  calculateFaceNormals();
  if(mVertexNormals.size() == 0){
    calculateVertexNormals();
  }

  // Create buffer handles for all of our vertex attribute buffers
  glGenBuffers(4, mAttributeBuffers);

  loadVertexBuffers();

  mFlatShading = true;
  mUseTexture = false; // Not ready to use texture until we've loaded one
}
Beispiel #6
0
void Ivy::birth()
{
	//evolve a gaussian filter over the adhesian vectors

	float gaussian[11] = {1.0f, 2.0f, 4.0f, 7.0f, 9.0f, 10.0f, 9.0f, 7.0f, 4.0f, 2.0f, 1.0f };

    for(unsigned int r=0; r < roots.size(); r++)
    {
        for(int g = 0; g <5; ++g)
        {
            IvyRoot root = roots[r];
            for(unsigned int n=0; n < root.nodes.size(); n++)
            {
                Vector3d e;

                for (int i = -5; i <= 5; ++i)
                {
                    Vector3d tmpAdhesion;

                    if ((n + i) < 0)
                        tmpAdhesion = root.nodes.front().adhesionVector;
                    if ((n + i) >= root.nodes.size())
                        tmpAdhesion = root.nodes.back().adhesionVector;
                    if (((n + i) >= 0) && ((n + i) < root.nodes.size()))
                        tmpAdhesion = root.nodes[n + i].adhesionVector;

                    e += tmpAdhesion * gaussian[i+5];
                }

               root.nodes[n].smoothAdhesionVector = e / 56.0f;
            }

            for(unsigned int n=0; n < root.nodes.size(); n++)
            {
                root.nodes[n].adhesionVector = root.nodes[n].smoothAdhesionVector;
            }
        }
    }

//	for (std::vector<IvyRoot>::iterator root = roots.begin(); root != roots.end(); ++root)
//	{
//		for (int g = 0; g < 5; ++g)
//		{
//			for (std::vector<IvyNode>::iterator node = root->nodes.begin(); node != root->nodes.end(); ++node)
//			{
//				Vector3d e;

//				for (int i = -5; i <= 5; ++i)
//				{
//					Vector3d tmpAdhesion;

//                    if ((node + i) < root->nodes.begin())
//                        tmpAdhesion = root->nodes.front().adhesionVector;
//                    if ((node + i) >= root->nodes.end())
//                        tmpAdhesion = root->nodes.back().adhesionVector;
//                    if (((node + i) >= root->nodes.begin()) && ((node + i) < root->nodes.end()))
//                        tmpAdhesion = (node + i)->adhesionVector;

//					e += tmpAdhesion * gaussian[i+5];
//				}

//				node->smoothAdhesionVector = e / 56.0f;
//			}

//            for (std::vector<IvyNode>::iterator node = root->nodes.begin(); node != root->nodes.end(); ++node)
//            {
//                node->adhesionVector = node->smoothAdhesionVector;
//            }
//		}
//	}


	//parameters that depend on the scene object bounding sphere
	float local_ivyLeafSize = Common::mesh.boundingSphereRadius * ivySize * ivyLeafSize;

	float local_ivyBranchSize = Common::mesh.boundingSphereRadius * ivySize * ivyBranchSize;


	//reset existing geometry
	BasicMesh::reset();


	//set data path
    path = "../textures/";


	//create material for leafs
	BasicMaterial tmpMaterial;

	tmpMaterial.id = 1;
	tmpMaterial.name = "leaf_adult";
	tmpMaterial.texFile = "efeu1.png";

	materials.push_back( tmpMaterial );


	//create second material for leafs
	tmpMaterial.id = 2;
	tmpMaterial.name = "leaf_young";
	tmpMaterial.texFile = "efeu0.png";

	materials.push_back( tmpMaterial );


	//create material for branches
	tmpMaterial.id = 3;
	tmpMaterial.name = "branch";
	tmpMaterial.texFile = "efeu_branch.png";

	materials.push_back( tmpMaterial );


	//create leafs
	for (std::vector<IvyRoot>::iterator root = roots.begin(); root != roots.end(); ++root)
	{
		//simple multiplier, just to make it a more dense
		for (int i = 0; i < 10; ++i)
		{
			//srand(i + (root - roots.begin()) * 10);

			for (std::vector<IvyNode>::iterator node = root->nodes.begin(); node != root->nodes.end(); ++node)
			{
				//weight depending on ratio of node length to total length
				float weight = pow(node->length / root->nodes.back().length, 0.7f);

				//test: the probability of leaves on the ground is increased
				float groundIvy = std::max<float>(0.0f, -Vector3d::dotProduct( Vector3d(0.0f, 1.0f, 0.0f), Vector3d::getNormalized(node->adhesionVector) ));
				weight += groundIvy * pow(1.0f - node->length / root->nodes.back().length, 2.0f);

				//random influence
				float probability = rand()/(float)RAND_MAX;

				if (probability * weight > leafProbability)
				{
					//alignment weight depends on the adhesion "strength"
					float alignmentWeight = node->adhesionVector.length();

					//horizontal angle (+ an epsilon vector, otherwise there's a problem at 0� and 90�... mmmh)
					float phi = Vector2d::vectorToPolar( Vector2d::getNormalized( Vector2d(node->adhesionVector.z, node->adhesionVector.x) ) + Vector2d::getEpsilon() ) - PI * 0.5f;

					//vertical angle, trimmed by 0.5
					float theta = Vector3d::getAngle( node->adhesionVector, Vector3d(0.0f, -1.0f, 0.0f) ) * 0.5f;

					//center of leaf quad
					Vector3d center = node->pos + Vector3d::getRandomized() * local_ivyLeafSize;

					//size of leaf
					float sizeWeight = 1.5f - (cos(weight * 2.0f * PI) * 0.5f + 0.5f);


					//random influence
					phi += (rand()/(float)RAND_MAX - 0.5f) * (1.3f - alignmentWeight);

					theta += (rand()/(float)RAND_MAX - 0.5f) * (1.1f - alignmentWeight);



					//create vertices
					BasicVertex tmpVertex;

					tmpVertex.pos = center + Vector3d(-local_ivyLeafSize * sizeWeight, 0.0f, local_ivyLeafSize * sizeWeight);
					tmpVertex.pos = Vector3d::rotateAroundAxis(tmpVertex.pos, center, Vector3d(0.0f, 0.0f, 1.0f), theta);
					tmpVertex.pos = Vector3d::rotateAroundAxis(tmpVertex.pos, center, Vector3d(0.0f, 1.0f, 0.0f), phi);
					tmpVertex.pos += Vector3d::getRandomized() * local_ivyLeafSize * sizeWeight * 0.5f;
					vertices.push_back( tmpVertex );

					tmpVertex.pos = center + Vector3d( local_ivyLeafSize * sizeWeight, 0.0f, local_ivyLeafSize * sizeWeight);
					tmpVertex.pos = Vector3d::rotateAroundAxis(tmpVertex.pos, center, Vector3d(0.0f, 0.0f, 1.0f), theta);
					tmpVertex.pos = Vector3d::rotateAroundAxis(tmpVertex.pos, center, Vector3d(0.0f, 1.0f, 0.0f), phi);
					tmpVertex.pos += Vector3d::getRandomized() * local_ivyLeafSize * sizeWeight * 0.5f;
					vertices.push_back( tmpVertex );

					tmpVertex.pos = center + Vector3d(-local_ivyLeafSize * sizeWeight, 0.0f, -local_ivyLeafSize * sizeWeight);
					tmpVertex.pos = Vector3d::rotateAroundAxis(tmpVertex.pos, center, Vector3d(0.0f, 0.0f, 1.0f), theta);
					tmpVertex.pos = Vector3d::rotateAroundAxis(tmpVertex.pos, center, Vector3d(0.0f, 1.0f, 0.0f), phi);
					tmpVertex.pos += Vector3d::getRandomized() * local_ivyLeafSize * sizeWeight * 0.5f;
					vertices.push_back( tmpVertex );

					tmpVertex.pos = center + Vector3d( local_ivyLeafSize * sizeWeight, 0.0f, -local_ivyLeafSize * sizeWeight);
					tmpVertex.pos = Vector3d::rotateAroundAxis(tmpVertex.pos, center, Vector3d(0.0f, 0.0f, 1.0f), theta);
					tmpVertex.pos = Vector3d::rotateAroundAxis(tmpVertex.pos, center, Vector3d(0.0f, 1.0f, 0.0f), phi);
					tmpVertex.pos += Vector3d::getRandomized() * local_ivyLeafSize * sizeWeight * 0.5f;
					vertices.push_back( tmpVertex );


					//create texCoords
					BasicTexCoord tmpTexCoord;

					tmpTexCoord.pos = Vector2d( 0.0f, 1.0f);
					texCoords.push_back( tmpTexCoord );

					tmpTexCoord.pos = Vector2d( 1.0f, 1.0f);
					texCoords.push_back( tmpTexCoord );

					tmpTexCoord.pos = Vector2d( 0.0f, 0.0f);
					texCoords.push_back( tmpTexCoord );

					tmpTexCoord.pos = Vector2d( 1.0f, 0.0f);
					texCoords.push_back( tmpTexCoord );


					//create triangle
					BasicTriangle tmpTriangle;

					tmpTriangle.matid = 1;

					float probability = rand()/(float)RAND_MAX;
					if (probability * weight > leafProbability) tmpTriangle.matid = 2;

                    tmpTriangle.v0id = (unsigned int)vertices.size()-1;
                    tmpTriangle.v1id = (unsigned int)vertices.size()-3;
                    tmpTriangle.v2id = (unsigned int)vertices.size()-2;

                    tmpTriangle.t0id = (unsigned int)vertices.size()-1;
                    tmpTriangle.t1id = (unsigned int)vertices.size()-3;
                    tmpTriangle.t2id = (unsigned int)vertices.size()-2;

					triangles.push_back( tmpTriangle );

                    tmpTriangle.v0id = (unsigned int)vertices.size()-2;
                    tmpTriangle.v1id = (unsigned int)vertices.size()-0;
                    tmpTriangle.v2id = (unsigned int)vertices.size()-1;

                    tmpTriangle.t0id = (unsigned int)vertices.size()-2;
                    tmpTriangle.t1id = (unsigned int)vertices.size()-0;
                    tmpTriangle.t2id = (unsigned int)vertices.size()-1;

					triangles.push_back( tmpTriangle );
				}
			}
		}
	}



	//branches
	for (std::vector<IvyRoot>::iterator root = roots.begin(); root != roots.end(); ++root)
	{
		//process only roots with more than one node
		if (root->nodes.size() == 1) continue;


		//branch diameter depends on number of parents
		float local_ivyBranchDiameter = 1.0f / (float)(root->parents + 1) + 1.0f;


        for (std::vector<IvyNode>::iterator node = root->nodes.begin(); node != root->nodes.end()-1; ++node)
		{
			//weight depending on ratio of node length to total length
			float weight = node->length / root->nodes.back().length;


			//create trihedral vertices
			Vector3d up = Vector3d(0.0f, -1.0f, 0.0f);

			Vector3d basis = Vector3d::getNormalized((node + 1)->pos - node->pos);

			Vector3d b0 = Vector3d::getNormalized( Vector3d::crossProduct(up, basis) ) * local_ivyBranchDiameter * local_ivyBranchSize * (1.3f - weight) + node->pos;

			Vector3d b1 = Vector3d::rotateAroundAxis(b0, node->pos, basis, 2.09f);

			Vector3d b2 = Vector3d::rotateAroundAxis(b0, node->pos, basis, 4.18f);


			//create vertices
			BasicVertex tmpVertex;

			tmpVertex.pos = b0;
			vertices.push_back( tmpVertex );

			tmpVertex.pos = b1;
			vertices.push_back( tmpVertex );

			tmpVertex.pos = b2;
			vertices.push_back( tmpVertex );


			//create texCoords
			BasicTexCoord tmpTexCoord;

			float texV = (node - root->nodes.begin()) % 2 == 0 ? 1.0f : 0.0f;

			tmpTexCoord.pos = Vector2d( 0.0f, texV);
			texCoords.push_back( tmpTexCoord );

			tmpTexCoord.pos = Vector2d( 0.3f, texV);
			texCoords.push_back( tmpTexCoord );

			tmpTexCoord.pos = Vector2d( 0.6f, texV);
			texCoords.push_back( tmpTexCoord );


			if (node == root->nodes.begin()) continue;


			//create triangle
			BasicTriangle tmpTriangle;

			tmpTriangle.matid = 3;

            tmpTriangle.v0id = (unsigned int)vertices.size()-3;
            tmpTriangle.v1id = (unsigned int)vertices.size()-0;
            tmpTriangle.v2id = (unsigned int)vertices.size()-4;

            tmpTriangle.t0id = (unsigned int)vertices.size()-3;
            tmpTriangle.t1id = (unsigned int)vertices.size()-0;
            tmpTriangle.t2id = (unsigned int)vertices.size()-4;

			triangles.push_back( tmpTriangle );


            tmpTriangle.v0id = (unsigned int)vertices.size()-4;
            tmpTriangle.v1id = (unsigned int)vertices.size()-0;
            tmpTriangle.v2id = (unsigned int)vertices.size()-1;

            tmpTriangle.t0id = (unsigned int)vertices.size()-4;
            tmpTriangle.t1id = (unsigned int)vertices.size()-0;
            tmpTriangle.t2id = (unsigned int)vertices.size()-1;

			triangles.push_back( tmpTriangle );


            tmpTriangle.v0id = (unsigned int)vertices.size()-4;
            tmpTriangle.v1id = (unsigned int)vertices.size()-1;
            tmpTriangle.v2id = (unsigned int)vertices.size()-5;

            tmpTriangle.t0id = (unsigned int)vertices.size()-4;
            tmpTriangle.t1id = (unsigned int)vertices.size()-1;
            tmpTriangle.t2id = (unsigned int)vertices.size()-5;

			triangles.push_back( tmpTriangle );


            tmpTriangle.v0id = (unsigned int)vertices.size()-5;
            tmpTriangle.v1id = (unsigned int)vertices.size()-1;
            tmpTriangle.v2id = (unsigned int)vertices.size()-2;

            tmpTriangle.t0id = (unsigned int)vertices.size()-5;
            tmpTriangle.t1id = (unsigned int)vertices.size()-1;
            tmpTriangle.t2id = (unsigned int)vertices.size()-2;

			triangles.push_back( tmpTriangle );


            tmpTriangle.v0id = (unsigned int)vertices.size()-5;
            tmpTriangle.v1id = (unsigned int)vertices.size()-2;
            tmpTriangle.v2id = (unsigned int)vertices.size()-0;

            tmpTriangle.t0id = (unsigned int)vertices.size()-5;
            tmpTriangle.t1id = (unsigned int)vertices.size()-2;
            tmpTriangle.t2id = (unsigned int)vertices.size()-0;

			triangles.push_back( tmpTriangle );


            tmpTriangle.v0id = (unsigned int)vertices.size()-5;
            tmpTriangle.v1id = (unsigned int)vertices.size()-0;
            tmpTriangle.v2id = (unsigned int)vertices.size()-3;

            tmpTriangle.t0id = (unsigned int)vertices.size()-5;
            tmpTriangle.t1id = (unsigned int)vertices.size()-0;
            tmpTriangle.t2id = (unsigned int)vertices.size()-3;

			triangles.push_back( tmpTriangle );
		}
	}


	//initialize ivy mesh
	loadTextures();

	prepareData();

	calculateVertexNormals();

	prepareData();

	createDisplayList(true);
}