Пример #1
0
STreeMesh* CTreeGenerator::generateTree( s32 radialSegments, s32 seed, bool addLeaves, s32 cutoffLevel )
{
    STreeMesh* treeMesh = new STreeMesh();
    
    Seed = seed;
    LeafSeed = seed;
    RadialSegments = radialSegments;
    CutoffLevel = cutoffLevel;
    AddLeaves = addLeaves;
    
    SMeshBuffer* buffer = new SMeshBuffer();
    
    treeMesh->setMeshBuffer( buffer );
    
    SBranch* root = getBranchWithId( RootIdRef );
    
    if ( root != 0 )
    {
        appendBranch( core::matrix4(), root, 1.0f, 1.0f, Levels, buffer, treeMesh->Leaves );
    }
    
    buffer->drop();
    
    return treeMesh;
}
Пример #2
0
Sprite::Sprite(std::string const& name, bool const& center)
    :Object(name), center_(center), thismesh_(0)
{
    if( !sprite_plane_ptr_ ) {
        S3DVertex vertices[4];
        u16 indices[6] = {0,2,3,3,1,0};

        vertices[0].Pos = vector3df(0,-1,0);
        vertices[1].Pos = vector3df(1,-1,0);
        vertices[2].Pos = vector3df(0, 0,0);
        vertices[3].Pos = vector3df(1, 0,0);

        vertices[0].Normal = vector3df(0,0,-1);
        vertices[1].Normal = vector3df(0,0,-1);
        vertices[2].Normal = vector3df(0,0,-1);
        vertices[3].Normal = vector3df(0,0,-1);

        vertices[0].TCoords = vector2df(0,1);
        vertices[1].TCoords = vector2df(1,1);
        vertices[2].TCoords = vector2df(0,0);
        vertices[3].TCoords = vector2df(1,0);

        SMeshBuffer* buf = new SMeshBuffer();
        buf->append(vertices, 4, indices, 6);

        sprite_plane_.addMeshBuffer( buf );
        sprite_plane_.recalculateBoundingBox();

        sprite_plane_ptr_ = &sprite_plane_;
        buf->drop(); //the addMeshBuffer method will grab it, so we can drop this ptr.
    }
}
Пример #3
0
IMesh* MeshTools::createMeshFromSoftBody(btSoftBody* softBody)
{
	SMeshBuffer* buffer = new SMeshBuffer();
	video::S3DVertex vtx;
	vtx.Color.set(255,255,255,255);

    /* Each soft body contain an array of vertices (nodes/particles_mass)   */
    btSoftBody::tNodeArray&   nodes(softBody->m_nodes);

    // Convert bullet nodes to vertices
    for(int i=0;i<nodes.size();++i)
    {
        const btSoftBody::Node&	n=nodes[i];
        const btVector3 normal=n.m_n;
        const btVector3 pos=n.m_x;

        vtx.Pos.set(pos.getX(), pos.getY(), pos.getZ());
		vtx.Normal.set(normal.getX(), normal.getY(), normal.getZ());

        // TODO: calculate texture coords
        //vtx.TCoords.set(tsx, tsy);

        buffer->Vertices.push_back(vtx);
    }

    // Convert triangles of the softbody to an index list
    for(int i=0;i<softBody->m_faces.size();++i)
    {
        auto	faces = softBody->m_faces;

        btSoftBody::Node*   node_0=faces[i].m_n[0];
        btSoftBody::Node*   node_1=faces[i].m_n[1];
        btSoftBody::Node*   node_2=faces[i].m_n[2];

        const int indices[] =
        {
            int(node_0-&nodes[0]),
            int(node_1-&nodes[0]),
            int(node_2-&nodes[0])
        };

        for(int j=0;j<3;++j)
            buffer->Indices.push_back(indices[j]);
    }

	buffer->recalculateBoundingBox();

	// Default the mesh to stream because most likely we will be updating
	// the vertex positions every frame to deal with softbody movement.
	buffer->setHardwareMappingHint(EHM_STREAM);

	SMesh* mesh = new SMesh();
	mesh->addMeshBuffer(buffer);
	mesh->recalculateBoundingBox();
	buffer->drop();
	return mesh;
}
Пример #4
0
void MeshBuffer_SetVertex(IntPtr meshb, unsigned int nr, IntPtr vert)
{
	SMeshBuffer *mb = ((SMeshBuffer*)meshb);
	if(nr >= mb->getVertexCount())
	{
		mb->Vertices.push_back(*((S3DVertex*)vert));
		MeshBuffer_SetVertex(meshb, nr, vert);
	}
	else
		(((S3DVertex*)(mb->getVertices()))[nr]) = *((S3DVertex*)vert);
}
Пример #5
0
	void addstrip(const HeightMap &hm, colour_func cf, u16 y0, u16 y1, u32 bufNum)
	{
		SMeshBuffer *buf = 0;
		if (bufNum<Mesh->getMeshBufferCount())
		{
			buf = (SMeshBuffer*)Mesh->getMeshBuffer(bufNum);
		}
		else
		{
			// create new buffer
			buf = new SMeshBuffer();
			Mesh->addMeshBuffer(buf);
			// to simplify things we drop here but continue using buf
			buf->drop();
		}
		buf->Vertices.set_used((1 + y1 - y0) * Width);

		u32 i=0;
		for (u16 y = y0; y <= y1; ++y)
		{
			for (u16 x = 0; x < Width; ++x)
			{
				const f32 z = hm.get(x, y);
				const f32 xx = (f32)x/(f32)Width;
				const f32 yy = (f32)y/(f32)Height;

				S3DVertex& v = buf->Vertices[i++];
				v.Pos.set(x, Scale * z, y);
				v.Normal.set(hm.getnormal(x, y, Scale));
				v.Color=cf(xx, yy, z);
				v.TCoords.set(xx, yy);
			}
		}

		buf->Indices.set_used(6 * (Width - 1) * (y1 - y0));
		i=0;
		for(u16 y = y0; y < y1; ++y)
		{
			for(u16 x = 0; x < Width - 1; ++x)
			{
				const u16 n = (y-y0) * Width + x;
				buf->Indices[i]=n;
				buf->Indices[++i]=n + Width;
				buf->Indices[++i]=n + Width + 1;
				buf->Indices[++i]=n + Width + 1;
				buf->Indices[++i]=n + 1;
				buf->Indices[++i]=n;
				++i;
			}
		}

		buf->recalculateBoundingBox();
	}
Пример #6
0
void MeshBuffer_SetColor(IntPtr meshb, M_SCOLOR color)
{
	SMeshBuffer *mb = ((SMeshBuffer*)meshb);
	int cnt = mb->getVertexCount();
	//mb->grab();
	for (int i=0;i<cnt;i++)
	{

		mb->Vertices[i].Color = MU_SCOLOR(color);
		
	}
	mb->setDirty(irr::scene::EBT_VERTEX);

}
Пример #7
0
//! constructor
CBillboardTextSceneNode::CBillboardTextSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
	gui::IGUIFont* font,const wchar_t* text,
	const core::vector3df& position, const core::dimension2d<f32>& size,
	video::SColor colorTop,video::SColor shade_bottom )
: IBillboardTextSceneNode(parent, mgr, id, position),
	Font(0), ColorTop(colorTop), ColorBottom(shade_bottom), Mesh(0)
{
	#ifdef _DEBUG
	setDebugName("CBillboardTextSceneNode");
	#endif

	Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
	Material.MaterialTypeParam = 1.f / 255.f;
	Material.BackfaceCulling = false;
	Material.Lighting = false;
	Material.ZBuffer = video::ECFN_LESSEQUAL;
	Material.ZWriteEnable = false;

	if (font)
	{
		// doesn't support other font types
		if (font->getType() == gui::EGFT_BITMAP)
		{
			Font = (gui::IGUIFontBitmap*)font;
			Font->grab();

			// mesh with one buffer per texture
			Mesh = new SMesh();
			for (u32 i=0; i<Font->getSpriteBank()->getTextureCount(); ++i)
			{
				SMeshBuffer *mb = new SMeshBuffer();
				mb->Material = Material;
				mb->Material.setTexture(0, Font->getSpriteBank()->getTexture(i));
				Mesh->addMeshBuffer(mb);
				mb->drop();
			}
		}
		else
		{
			os::Printer::log("Sorry, CBillboardTextSceneNode does not support this font type", ELL_INFORMATION);
		}
	}

	setText(text);
	setSize(size);

	setAutomaticCulling ( scene::EAC_BOX );
}
IMeshSceneNode* CustomSceneNodeManager::CreateConeSceneNode(scene::ISceneManager* sceneManager, s32 id, SColor& color, unsigned int resolution, float radius, float height)
{
	if (resolution >= 4)
	{
		/*IMesh* newConeMesh = sceneManager->getGeometryCreator()->createConeMesh(radius, height, resolution, color, color);

		IMeshSceneNode* node = sceneManager->addMeshSceneNode(newConeMesh);

		sceneManager->getMeshCache()->addMesh(irr::io::path("ConeMesh"), (irr::scene::IAnimatedMesh*)newConeMesh);
		newConeMesh->drop();*/

		SMesh* newConeMesh = new SMesh();

		SMeshBuffer* buf = new SMeshBuffer();
	
		newConeMesh->addMeshBuffer(buf);
		buf->MappingHint_Vertex = EHM_STATIC;
		buf->MappingHint_Index = EHM_STATIC;
		buf->drop();

		int noWarningSignedResolution = resolution;

		float currentTheta = 0.0f;
		float skipAmount = 2.0f*PI / (float)resolution;
		float halfHeight = height / 2.0f;

		S3DVertex temp1 = S3DVertex(Vector3(0.0f, halfHeight, 0.0f), Vector3_Zero, color, vector2d<f32>(0.0f, 0.0f));
		S3DVertex temp2 = S3DVertex(Vector3(0.0f, -halfHeight, 0.0f), Vector3_Zero, color, vector2d<f32>(0.0f, 1.0f));
		for(int i = 0; i < noWarningSignedResolution; i++)
		{
			float x = cosf(currentTheta) * radius;
			float z = sinf(currentTheta) * radius;

			temp2.Pos.X = x;
			temp2.Pos.Z = z;
			temp2.TCoords.X = currentTheta / 2.0f*PI;

			buf->Vertices.push_back(temp2);

			currentTheta += skipAmount;
		}
		
		buf->Vertices.push_back(temp1);

		//Get side indices
		for(int i = 0; i < noWarningSignedResolution - 1; i++)
		{
			buf->Indices.push_back(i);
			buf->Indices.push_back(buf->Vertices.size()-1);
			buf->Indices.push_back(i+1);
		}

		buf->Indices.push_back(buf->Vertices.size()-2);
		buf->Indices.push_back(buf->Vertices.size()-1);
		buf->Indices.push_back(0);

		temp2.Pos.X = 0.0f;
		temp2.Pos.Z = 0.0f;
		buf->Vertices.push_back(temp2);

		//Get bottom indices
		for(int i = 0; i < noWarningSignedResolution - 1; i++)
		{
			buf->Indices.push_back(i);
			buf->Indices.push_back(i+1);
			buf->Indices.push_back(buf->Vertices.size()-1);
		}

		buf->Indices.push_back(buf->Vertices.size()-1);
		buf->Indices.push_back(buf->Vertices.size()-3);
		buf->Indices.push_back(0);

		//Calculate normals
		CalculateNormals(buf->Vertices, buf->Indices);

		buf->recalculateBoundingBox();
		newConeMesh->recalculateBoundingBox();

		IMeshSceneNode* node = sceneManager->addMeshSceneNode(newConeMesh);

		newConeMesh->drop();

		return node;
	}

	return NULL;
}
IAnimatedMesh* CGeometryCreator::createTerrainMesh(video::IImage* texture,
        video::IImage* heightmap, const core::dimension2d<f32>& stretchSize,
        f32 maxHeight, video::IVideoDriver* driver,
        const core::dimension2d<s32> maxVtxBlockSize,
        bool debugBorders)
{
    u32 tm = os::Timer::getRealTime()/1000;

    if (!texture || !heightmap)
        return 0;

    video::SMaterial material;
    c8 textureName[64];
    c8 tmp[255];


    // debug border
    s32 borderSkip = debugBorders ? 0 : 1;

    video::S3DVertex vtx;
    vtx.Color.set(255,255,255,255);

    SMesh* mesh = new SMesh();

    core::dimension2d<s32> hMapSize= heightmap->getDimension();
    core::dimension2d<s32> tMapSize= texture->getDimension();
    core::position2d<f32> thRel((f32)tMapSize.Width / (s32)hMapSize.Width, (f32)tMapSize.Height / (s32)hMapSize.Height);
    core::position2d<s32> processed(0,0);

    while (processed.Y<hMapSize.Height)
    {
        while(processed.X<hMapSize.Width)
        {
            core::dimension2d<s32> blockSize = maxVtxBlockSize;
            if (processed.X + blockSize.Width > hMapSize.Width)
                blockSize.Width = hMapSize.Width - processed.X;
            if (processed.Y + blockSize.Height > hMapSize.Height)
                blockSize.Height = hMapSize.Height - processed.Y;

            SMeshBuffer* buffer = new SMeshBuffer();
            s32 x,y;

            // add vertices of vertex block
            for (y=0; y<blockSize.Height; ++y)
                for (x=0; x<blockSize.Width; ++x)
                {
                    video::SColor clr = heightmap->getPixel(x+processed.X, y+processed.Y);
                    f32 height = ((clr.getRed() + clr.getGreen() + clr.getBlue()) / 3.0f)/255.0f * maxHeight;

                    vtx.Pos.set((f32)(x+processed.X) * stretchSize.Width,
                                height, (f32)(y+processed.Y) * stretchSize.Height);

                    vtx.TCoords.set((f32)(x+0.5f) / ((f32)blockSize.Width),
                                    (f32)(y+0.5f) / ((f32)blockSize.Height));

                    buffer->Vertices.push_back(vtx);
                }

            // add indices of vertex block
            for (y=0; y<blockSize.Height-1; ++y)
                for (x=0; x<blockSize.Width-1; ++x)
                {
                    s32 c = (y*blockSize.Width) + x;

                    buffer->Indices.push_back(c);
                    buffer->Indices.push_back(c + blockSize.Width);
                    buffer->Indices.push_back(c + 1);

                    buffer->Indices.push_back(c + 1);
                    buffer->Indices.push_back(c + blockSize.Width);
                    buffer->Indices.push_back(c + 1 + blockSize.Width);
                }

            // recalculate normals
            for (s32 i=0; i<(s32)buffer->Indices.size(); i+=3)
            {
                core::plane3d<f32> p(
                    buffer->Vertices[buffer->Indices[i+0]].Pos,
                    buffer->Vertices[buffer->Indices[i+1]].Pos,
                    buffer->Vertices[buffer->Indices[i+2]].Pos);
                p.Normal.normalize();

                buffer->Vertices[buffer->Indices[i+0]].Normal = p.Normal;
                buffer->Vertices[buffer->Indices[i+1]].Normal = p.Normal;
                buffer->Vertices[buffer->Indices[i+2]].Normal = p.Normal;
            }

            if (buffer->Vertices.size())
            {
                // create texture for this block
                video::IImage* img = new video::CImage(texture,
                                                       core::position2d<s32>((s32)(processed.X*thRel.X), (s32)(processed.Y*thRel.Y)),
                                                       core::dimension2d<s32>((s32)(blockSize.Width*thRel.X), (s32)(blockSize.Height*thRel.Y)));

                sprintf(textureName, "terrain%d_%d", tm, mesh->getMeshBufferCount());

                material.Texture1 = driver->addTexture(textureName, img);

                if (material.Texture1)
                {
                    sprintf(tmp, "Generated terrain texture (%dx%d): %s",
                            material.Texture1->getSize().Width,
                            material.Texture1->getSize().Height,
                            textureName);
                    os::Printer::log(tmp);
                }
                else
                    os::Printer::log("Could not create terrain texture.", textureName, ELL_ERROR);

                buffer->Material = material;
                img->drop();
            }

            buffer->recalculateBoundingBox();
            mesh->addMeshBuffer(buffer);
            buffer->drop();

            // keep on processing
            processed.X += maxVtxBlockSize.Width - borderSkip;
        }

        // keep on processing
        processed.X = 0;
        processed.Y += maxVtxBlockSize.Height - borderSkip;
    }

    SAnimatedMesh* animatedMesh = new SAnimatedMesh();
    mesh->recalculateBoundingBox();
    animatedMesh->addMesh(mesh);
    animatedMesh->recalculateBoundingBox();

    mesh->drop();

    return animatedMesh;
}
Пример #10
0
PlayerFrame::PlayerFrame(FrameInfo info, bool load_volumic)
{
	// increase total number of loaded frames
	PlayerFrame::totalLoadedFrames++;
	device->getLogger()->log((stringw("Loading frame number ")+stringw(info.id)+L". Total of frames loaded : "+stringw(PlayerFrame::totalLoadedFrames)).c_str());

	core::array<stringc> _lastEleFileNames;
	core::array<stringc> _lastFaceFileNames;
	core::array<scene::SMeshBuffer*> _lastBuffers;

	// initialize some variables
	this->id = info.id;

	for (u32 o=0; o < info.nodefiles.size(); o++)
	{
		SMeshBuffer* buffer = new SMeshBuffer();
		IMeshSceneNode* node = NULL;
		stringc nodeFileName = info.nodefiles[o];
		stringc faceFileName = info.facefiles[o];
		stringc eleFileName = info.elefiles[o];

		// LOADING
		ifstream innode;
		ifstream inele;
		ifstream inface;

		int nb_of_points, nb_of_tetrahedra, nb_of_faces;
		int p1, p2, p3, p4;
		yohan::base::DATA x, y, z;

		// used to know if an error occured in the while loop
		bool error = false;


		// -----------------------------------------------------------------------
		// - POINTS --------------------------------------------------------------
		// -----------------------------------------------------------------------
		innode.open(nodeFileName.c_str(), ios::in | ios::binary); // opens the nodes file
		if (!innode || !innode.good())
		{
			device->getLogger()->log(( stringc("ERROR: This node file could not be opened : ") + nodeFileName ).c_str());
			buffer->drop();
			continue;
		}

		// first line data : innode >> nb_of_points >> dim >> nb_of_attr >> boundary_marker;
		innode.read(reinterpret_cast < char * > (&nb_of_points), sizeof(int));

		// we should have at least one tetrahedra (4 points) and each point should have 3 coordinates
		if (nb_of_points > 65535 || nb_of_points < 4)
		{
			device->getLogger()->log("ERROR: a node file should not contain more than 65535 points and less than 4 points.");
			buffer->drop();
			continue;
		}
		device->getLogger()->log((stringw("Loading ")+stringw(nb_of_points)+L" points from "+stringw(nodeFileName.c_str())+L"...").c_str());

		// default color
		video::SColor clr(255,100,100,200);

		// lets add the vertices to the buffer
		buffer->Vertices.reallocate( nb_of_points );

		// this is one line : innode >> index >> x >> y >> z;
		innode.read(reinterpret_cast < char * > (&x), sizeof(yohan::base::DATA));
		innode.read(reinterpret_cast < char * > (&y), sizeof(yohan::base::DATA));
		innode.read(reinterpret_cast < char * > (&z), sizeof(yohan::base::DATA));
		while (!innode.eof() && innode.good())// && (int)buffer->Vertices.size() < nb_of_points)
		{
			buffer->Vertices.push_back(video::S3DVertex((f32)x, (f32)y, (f32)z, 1,0,0, clr, 0,0));
			// this is one line : innode >> index >> x >> y >> z;
			innode.read(reinterpret_cast < char * > (&x), sizeof(yohan::base::DATA));
			innode.read(reinterpret_cast < char * > (&y), sizeof(yohan::base::DATA));
			innode.read(reinterpret_cast < char * > (&z), sizeof(yohan::base::DATA));
		}

		innode.close();
		innode.clear();
		// -----------------------------------------------------------------------

		// lets check if verticies have been added well
		if (buffer->Vertices.size() != nb_of_points)
		{
			device->getLogger()->log("ERROR: the node file does not seem to be valid.");
			buffer->drop();
			continue;
		}





		if (load_volumic)
		{
			// -----------------------------------------------------------------------
			// - TETRAHEDRAS ---------------------------------------------------------
			// -----------------------------------------------------------------------
			// at first we check if the ele file has not been already opened
			s32 eleLoadedIndex = -1;
			for (u32 e=0; e < PlayerFrame::lastEleFileNames.size(); e++)
			{
				if (PlayerFrame::lastEleFileNames[e] == eleFileName)
				{
					eleLoadedIndex = e;
					device->getLogger()->log("The ele file is already in memory. We do not need to reload it.");
					break;
				}
			}

			// if is not in memory, load it from file
			if (!PlayerFrame::last_was_volumic || eleLoadedIndex == -1 || PlayerFrame::lastBuffers[eleLoadedIndex]->Vertices.size() != buffer->Vertices.size())
			{
				if (eleLoadedIndex != -1)
					device->getLogger()->log((stringc(PlayerFrame::lastBuffers[eleLoadedIndex]->Vertices.size())+
					" This is weird: the ele file which is already in memory don't have the same number of vertices than this one.").c_str());

				inele.open(eleFileName.c_str(), ios::in | ios::binary); // opens the ele file
				if (!inele || !inele.good())
				{
					device->getLogger()->log(( stringc("ERROR: This ele file could not be opened : ") + eleFileName ).c_str());
					buffer->drop();
					continue;
				}

				// first line data : inele >> nb_of_tetrahedra >> dim >> nb_of_attr;
				inele.read(reinterpret_cast < char * > (&nb_of_tetrahedra), sizeof(int));
				device->getLogger()->log((stringw("Loading ")+stringw(nb_of_tetrahedra)+L" tetrahedras from "+stringw(eleFileName.c_str())+L"...").c_str());

				// we should have at least one tetrahedra and each tetrahedra should have 4 points
				if (nb_of_tetrahedra < 1)
				{
					buffer->drop();
					continue;
				}

				// lets add the indices to the buffer
				buffer->Indices.set_used( (u32)(3 * 4 * nb_of_tetrahedra) );
				u32 i = 0;

				// this is one line : inele >> index >> p1 >> p2 >> p3 >> p4;
				inele.read(reinterpret_cast < char * > (&p1), sizeof(int));
				inele.read(reinterpret_cast < char * > (&p2), sizeof(int));
				inele.read(reinterpret_cast < char * > (&p3), sizeof(int));
				inele.read(reinterpret_cast < char * > (&p4), sizeof(int));
				while (!inele.eof() && inele.good())// && i < 3 * 4 * nb_of_tetrahedra - 12)
				{
					// check if we are not out of bounds
					if (i > (u32)(3 * 4 * nb_of_tetrahedra - 12) || p1 > nb_of_points || p2 > nb_of_points || p3 > nb_of_points || p4 > nb_of_points)
					{
						device->getLogger()->log("ERROR: the ele file does not seem to be valid. ");
						buffer->drop();
						error = true;
						break;
					}

					// add 4 polygons per tetrahedra. Not optimized !
					s32 ajust_index = 0;
					buffer->Indices[(u32)(i+0)] = (u32)(p1 + ajust_index);
					buffer->Indices[(u32)(i+1)] = (u32)(p3 + ajust_index);
					buffer->Indices[(u32)(i+2)] = (u32)(p2 + ajust_index);
					core::triangle3df t4(
						buffer->Vertices[(u32)(p1 + ajust_index)].Pos,
						buffer->Vertices[(u32)(p3 + ajust_index)].Pos,
						buffer->Vertices[(u32)(p2 + ajust_index)].Pos);
					i += 3;

					buffer->Indices[(u32)(i+0)] = (u32)(p1 + ajust_index);
					buffer->Indices[(u32)(i+1)] = (u32)(p2 + ajust_index);
					buffer->Indices[(u32)(i+2)] = (u32)(p4 + ajust_index);
					core::triangle3df t3(
						buffer->Vertices[(u32)(p1 + ajust_index)].Pos,
						buffer->Vertices[(u32)(p2 + ajust_index)].Pos,
						buffer->Vertices[(u32)(p4 + ajust_index)].Pos);
					i += 3;

					buffer->Indices[(u32)(i+0)] = (u32)(p3 + ajust_index);
					buffer->Indices[(u32)(i+1)] = (u32)(p4 + ajust_index);
					buffer->Indices[(u32)(i+2)] = (u32)(p2 + ajust_index);
					core::triangle3df t1(
						buffer->Vertices[(u32)(p3 + ajust_index)].Pos,
						buffer->Vertices[(u32)(p4 + ajust_index)].Pos,
						buffer->Vertices[(u32)(p2 + ajust_index)].Pos);
					i += 3;

					buffer->Indices[(u32)(i+0)] = (u32)(p1 + ajust_index);
					buffer->Indices[(u32)(i+1)] = (u32)(p4 + ajust_index);
					buffer->Indices[(u32)(i+2)] = (u32)(p3 + ajust_index);
					core::triangle3df t2(
						buffer->Vertices[(u32)(p1 + ajust_index)].Pos,
						buffer->Vertices[(u32)(p4 + ajust_index)].Pos,
						buffer->Vertices[(u32)(p3 + ajust_index)].Pos);
					i += 3;

					buffer->Vertices[(u32)(p1 + ajust_index)].Normal = t1.getNormal();
					buffer->Vertices[(u32)(p2 + ajust_index)].Normal = t2.getNormal();
					buffer->Vertices[(u32)(p3 + ajust_index)].Normal = t3.getNormal();
					buffer->Vertices[(u32)(p4 + ajust_index)].Normal = t4.getNormal();

					// this is one line : inele >> index >> p1 >> p2 >> p3 >> p4;
					inele.read(reinterpret_cast < char * > (&p1), sizeof(int));
					inele.read(reinterpret_cast < char * > (&p2), sizeof(int));
					inele.read(reinterpret_cast < char * > (&p3), sizeof(int));
					inele.read(reinterpret_cast < char * > (&p4), sizeof(int));
				}

				inele.close();
				inele.clear();
			}
			else // we do not need to reload from the file !
			{
				buffer->Indices.reallocate(PlayerFrame::lastBuffers[eleLoadedIndex]->Indices.size());
				buffer->Indices = PlayerFrame::lastBuffers[eleLoadedIndex]->Indices;
				for (u32 j=0; j < buffer->Vertices.size(); j++)
					buffer->Vertices[j].Normal = PlayerFrame::lastBuffers[eleLoadedIndex]->Vertices[j].Normal;
			}
			// -----------------------------------------------------------------------
		}
		else // load_volumic == false
		{
			// -----------------------------------------------------------------------
			// - FACES ---------------------------------------------------------------
			// -----------------------------------------------------------------------
			// at first we check if the ele file has not been already opened
			s32 faceLoadedIndex = -1;
			for (u32 e=0; e < PlayerFrame::lastFaceFileNames.size(); e++)
			{
				if (PlayerFrame::lastFaceFileNames[e] == faceFileName)
				{
					faceLoadedIndex = e;
					device->getLogger()->log("The face file is already in memory. We do not need to reload it.");
					break;
				}
			}
			// if is not in memory, load it from file
			if (PlayerFrame::last_was_volumic || faceLoadedIndex == -1 || PlayerFrame::lastBuffers[faceLoadedIndex]->Vertices.size() != buffer->Vertices.size())
			{
				inface.open(faceFileName.c_str(), ios::in | ios::binary); // opens the face file
				if (!inface || !inface.good())
				{
					device->getLogger()->log(( stringc("ERROR: This face file could not be opened : ") + faceFileName ).c_str());
					buffer->drop();
					continue;
				}

				// first line data : inface >> nb_of_tetrahedra >> dim >> nb_of_attr;
				inface.read(reinterpret_cast < char * > (&nb_of_faces), sizeof(int));
				device->getLogger()->log((stringw("Loading ")+stringw(nb_of_faces)+L" faces from "+stringw(faceFileName.c_str())+L"...").c_str());

				// we should have at least one face
				if (nb_of_faces < 1)
				{
					buffer->drop();
					continue;
				}

				// lets add the indices to the buffer
				buffer->Indices.set_used( (u32)(3 * nb_of_faces) );
				u32 i = 0;

				// this is one line : inface >> index >> p1 >> p2 >> p3;
				inface.read(reinterpret_cast < char * > (&p1), sizeof(int));
				inface.read(reinterpret_cast < char * > (&p2), sizeof(int));
				inface.read(reinterpret_cast < char * > (&p3), sizeof(int));
				while (!inface.eof() && inface.good())
				{
					// check if we are not out of bounds
					if (i > (u32)(3 * nb_of_faces - 3) || p1 > nb_of_points || p2 > nb_of_points || p3 > nb_of_points)
					{
						device->getLogger()->log("ERROR: the face file does not seem to be valid. ");
						buffer->drop();
						error = true;
						break;
					}

					// add 1 polygon per face.
					s32 ajust_index = -1;
					buffer->Indices[(u32)(i+0)] = (u32)(p1 + ajust_index);
					buffer->Indices[(u32)(i+1)] = (u32)(p3 + ajust_index);
					buffer->Indices[(u32)(i+2)] = (u32)(p2 + ajust_index);
					core::triangle3df t(
						buffer->Vertices[(u32)(p1 + ajust_index)].Pos,
						buffer->Vertices[(u32)(p3 + ajust_index)].Pos,
						buffer->Vertices[(u32)(p2 + ajust_index)].Pos);
					i += 3;

					buffer->Vertices[(u32)(p1 + ajust_index)].Normal = t.getNormal();
					buffer->Vertices[(u32)(p2 + ajust_index)].Normal = t.getNormal();
					buffer->Vertices[(u32)(p3 + ajust_index)].Normal = t.getNormal();

					// this is one line : inface >> index >> p1 >> p2 >> p3;
					inface.read(reinterpret_cast < char * > (&p1), sizeof(int));
					inface.read(reinterpret_cast < char * > (&p2), sizeof(int));
					inface.read(reinterpret_cast < char * > (&p3), sizeof(int));
				}

				inface.close();
				inface.clear();
			}
			else // we do not need to reload from the file !
			{
				buffer->Indices.reallocate(PlayerFrame::lastBuffers[faceLoadedIndex]->Indices.size());
				buffer->Indices = PlayerFrame::lastBuffers[faceLoadedIndex]->Indices;
				for (u32 j=0; j < buffer->Vertices.size(); j++)
					buffer->Vertices[j].Normal = PlayerFrame::lastBuffers[faceLoadedIndex]->Vertices[j].Normal;
			}
			// -----------------------------------------------------------------------
		}

		if (error)
			continue;

		// lets recalculate the bounding box and create the mesh
		for (u32 j=0; j < buffer->Vertices.size(); ++j)
			buffer->BoundingBox.addInternalPoint(buffer->Vertices[j].Pos);

		SMesh* mesh = new SMesh;
		mesh->addMeshBuffer(buffer);
		mesh->recalculateBoundingBox();

		// here we go, lets create the node that will owns the mesh data
		node = smgr->addMeshSceneNode( mesh );
		mesh->drop();
		if (!node)
		{
			node = NULL;
			continue;
		}
		node->setVisible(false);
		//node->setMaterialFlag(video::EMF_WIREFRAME, true);

		this->nodes.push_back( node );

		// updating last
		_lastEleFileNames.push_back( eleFileName );
		_lastFaceFileNames.push_back( faceFileName );
		_lastBuffers.push_back( buffer );
	}

	// clean history and update it
	PlayerFrame::lastEleFileNames = _lastEleFileNames;
	PlayerFrame::lastFaceFileNames = _lastFaceFileNames;
	for (u32 e=0; e < lastBuffers.size(); e++)
	{
		if (_lastBuffers.binary_search(PlayerFrame::lastBuffers[e]) == -1)
		{
			PlayerFrame::lastBuffers[e]->drop();
		}
	}
	PlayerFrame::lastBuffers = _lastBuffers;
	PlayerFrame::last_was_volumic = load_volumic;


	// that's it !
	device->getLogger()->log("Loaded.");
}
IMeshSceneNode* CustomSceneNodeManager::CreateCapsuleSceneNode(scene::ISceneManager* sceneManager, s32 id, SColor& color, unsigned int resolution, float radius, float heightFromSphereCenters)
{
	if (resolution >= 4)
	{
		SMesh* newCapsuleMesh = new SMesh();

		SMeshBuffer* buf = new SMeshBuffer();
	
		newCapsuleMesh->addMeshBuffer(buf);
		buf->MappingHint_Vertex = EHM_STATIC;
		buf->MappingHint_Index = EHM_STATIC;
		buf->drop();

		int noWarningSignedResolution = resolution;

		float thetaSkipAmount = 2.0f*PI / (float)resolution;
		float halfHeight = heightFromSphereCenters / 2.0f;
		float phiSkipAmount = PI*0.5f / (float)resolution;
		
		S3DVertex temp1 = S3DVertex(Vector3(0.0f, halfHeight, 0.0f), Vector3_Zero, color, vector2d<f32>(0.0f, 0.0f));
		S3DVertex temp2 = S3DVertex(Vector3(0.0f, -halfHeight, 0.0f), Vector3_Zero, color, vector2d<f32>(0.0f, 1.0f));

		float currentTheta = 0.0f;		
		float currentPhi = phiSkipAmount;
		temp1.Pos.Y = halfHeight + radius;
		buf->Vertices.push_back(temp1);

		//Semi-sphere Tips
		for(unsigned int i = 1; i < resolution; i++)
		{
			for(unsigned int j = 0; j < resolution; j++)
			{
				float x = sinf(currentPhi) * cosf(currentTheta) * radius;
				float y = cosf(currentPhi) * radius;
				float z = sinf(currentPhi) * sinf(currentTheta) * radius;

				temp1.Pos.X = x;
				temp1.Pos.Y = y + halfHeight;
				temp1.Pos.Z = z;
				temp1.TCoords.X = currentTheta / 2.0f*PI;
				temp1.TCoords.Y = currentPhi / PI;

				buf->Vertices.push_back(temp1);

				currentTheta += thetaSkipAmount;
			}

			currentTheta = 0.0f;
			currentPhi += phiSkipAmount;
		}

		currentTheta = 0.0f;		
		currentPhi = PI/2.0f;

		//Semi-sphere Tips
		for(unsigned int i = 1; i < resolution; i++)
		{
			for(unsigned int j = 0; j < resolution; j++)
			{
				float x = sinf(currentPhi) * cosf(currentTheta) * radius;
				float y = cosf(currentPhi) * radius;
				float z = sinf(currentPhi) * sinf(currentTheta) * radius;

				temp1.Pos.X = x;
				temp1.Pos.Y = y - halfHeight;
				temp1.Pos.Z = z;
				temp1.TCoords.X = currentTheta / 2.0f*PI;
				temp1.TCoords.Y = currentPhi / PI;

				buf->Vertices.push_back(temp1);

				currentTheta += thetaSkipAmount;
			}

			currentTheta = 0.0f;
			currentPhi += phiSkipAmount;
		}
		temp1.Pos.X = 0.0f;
		temp1.Pos.Y = -(halfHeight + radius);
		temp1.Pos.Z = 0.0f;
		buf->Vertices.push_back(temp1);

		//Top vertex indices
		for(unsigned int i = 1; i <= resolution; i++)
		{
			if (i == resolution)
			{
				buf->Indices.push_back(i);
				buf->Indices.push_back(0);
				buf->Indices.push_back(1);
			}
			else
			{
				buf->Indices.push_back(i);
				buf->Indices.push_back(0);
				buf->Indices.push_back(i + 1);
			}
		}

		//Get indices
		int i  = 1 + resolution;

		while(i < buf->Vertices.size() - 1)
		{
			for(unsigned int j = 1; j < resolution; j++)
			{
				buf->Indices.push_back(i);
				buf->Indices.push_back(i - noWarningSignedResolution);
				buf->Indices.push_back(i - noWarningSignedResolution + 1);

				buf->Indices.push_back(i);
				buf->Indices.push_back(i - noWarningSignedResolution + 1);
				buf->Indices.push_back(i + 1);

				i++;
			}

			buf->Indices.push_back(i);
			buf->Indices.push_back(i - noWarningSignedResolution);
			buf->Indices.push_back(i - noWarningSignedResolution + 1 - resolution);

			buf->Indices.push_back(i);
			buf->Indices.push_back(i - noWarningSignedResolution + 1 - resolution);
			buf->Indices.push_back(i + 1 - resolution);

			i++;
		}

		//Bottom vertex indices
		for(int i = resolution; i >= 1 ; i--)
		{
			if (i == 1)
			{
				/*buf->Indices.push_back(i);
				buf->Indices.push_back(0);
				buf->Indices.push_back(1);*/

				buf->Indices.push_back(buf->Vertices.size() -1);
				buf->Indices.push_back(buf->Vertices.size() -1 - i);
				buf->Indices.push_back(buf->Vertices.size() - 1 - resolution);
			}
			else
			{
				buf->Indices.push_back(buf->Vertices.size() -1);
				buf->Indices.push_back(buf->Vertices.size() -1 - i);
				buf->Indices.push_back(buf->Vertices.size() - i);
			}
		}




		//Calculate normals
		CalculateNormals(buf->Vertices, buf->Indices);

		buf->recalculateBoundingBox();
		newCapsuleMesh->recalculateBoundingBox();

		IMeshSceneNode* node = sceneManager->addMeshSceneNode(newCapsuleMesh);

		newCapsuleMesh->drop();

		return node;
	}

	return NULL;
}
IMeshSceneNode* CustomSceneNodeManager::CreateCylinderSceneNode(scene::ISceneManager* sceneManager, s32 id, SColor& color, unsigned int resolution, float radius, float height)
{
	/*if (!cylinderMesh)
	{*/
		if (resolution >= 4)
		{
			SMesh* newCylinderMesh = new SMesh();

			SMeshBuffer* buf = new SMeshBuffer();
		
			newCylinderMesh->addMeshBuffer(buf);
			buf->MappingHint_Vertex = EHM_STATIC;
			buf->MappingHint_Index = EHM_STATIC;
			buf->drop();

			int noWarningSignedResolution = resolution;

			float currentTheta = 0.0f;
			float skipAmount = 2.0f*PI / (float)resolution;
			float halfHeight = height / 2.0f;

			S3DVertex temp1 = S3DVertex(Vector3(0.0f, halfHeight, 0.0f), Vector3_Zero, color, vector2d<f32>(0.0f, 0.0f));
			S3DVertex temp2 = S3DVertex(Vector3(0.0f, -halfHeight, 0.0f), Vector3_Zero, color, vector2d<f32>(0.0f, 1.0f));
			for(int i = 0; i < noWarningSignedResolution; i++)
			{
				float x = cosf(currentTheta) * radius;
				float z = sinf(currentTheta) * radius;

				temp1.Pos.X = x;
				temp1.Pos.Z = z;
				temp1.TCoords.X = currentTheta / 2.0f*PI;
				temp2.Pos.X = x;
				temp2.Pos.Z = z;
				temp2.TCoords.X = currentTheta / 2.0f*PI;

				buf->Vertices.push_back(temp1);
				buf->Vertices.push_back(temp2);

				currentTheta += skipAmount;
			}

			temp1.Pos.X = 0.0f;
			temp1.Pos.Z = 0.0f;
			temp1.TCoords.X = 0.0f;
			temp2.Pos.X = 0.0f;
			temp2.Pos.Z = 0.0f;
			temp1.TCoords.X = 0.0f;
			buf->Vertices.push_back(temp1);
			buf->Vertices.push_back(temp2);

			//Get indices
			for(int i = 0; i < noWarningSignedResolution - 1; i++)
			{
				buf->Indices.push_back(i*2);
				buf->Indices.push_back(i*2+2);
				buf->Indices.push_back(i*2+1);

				buf->Indices.push_back(i*2+1);
				buf->Indices.push_back(i*2+2);
				buf->Indices.push_back(i*2+3);

				buf->Indices.push_back(i*2);
				buf->Indices.push_back(buf->Vertices.size()-2);
				buf->Indices.push_back(i*2+2);

				buf->Indices.push_back(i*2+1);
				buf->Indices.push_back(i*2+3);
				buf->Indices.push_back(buf->Vertices.size()-1);
			}

			buf->Indices.push_back(buf->Vertices.size()-4);
			buf->Indices.push_back(0);
			buf->Indices.push_back(buf->Vertices.size()-3);

			buf->Indices.push_back(buf->Vertices.size()-3);
			buf->Indices.push_back(0);
			buf->Indices.push_back(1);

			buf->Indices.push_back(buf->Vertices.size()-4);
			buf->Indices.push_back(buf->Vertices.size()-2);
			buf->Indices.push_back(0);

			buf->Indices.push_back(buf->Vertices.size()-3);
			buf->Indices.push_back(1);
			buf->Indices.push_back(buf->Vertices.size()-1);

			//Calculate normals
			CalculateNormals(buf->Vertices, buf->Indices);

			buf->recalculateBoundingBox();
			newCylinderMesh->recalculateBoundingBox();

			IMeshSceneNode* node = sceneManager->addMeshSceneNode(newCylinderMesh);

			newCylinderMesh->drop();

			return node;
		}

	/*	return NULL;
	}
	else
	{
		IMeshSceneNode* node = sceneManager->addMeshSceneNode(cylinderMesh);
		node->setScale(Vector3(radius, height, radius));

		return node;
	}*/

	return NULL;
}
Пример #13
0
void drawFrame()
{
    u32 i,color = 0;
    Matrix4 rotX,rotY;
    Vector4 objEyePos,objLightPos;
    Matrix4 viewMatrix,modelMatrix,modelMatrixIT,modelViewMatrix;
    Point3 lightPos = Point3(250.0f,150.0f,150.0f);
    f32 globalAmbientColor[3] = {0.1f,0.1f,0.1f};
    f32 lightColor[3] = {0.95f,0.95f,0.95f};
    f32 materialColorDiffuse[3] = {0.5f,0.0f,0.0f};
    f32 materialColorSpecular[3] = {0.7f,0.6f,0.6f};
    f32 shininess = 17.8954f;
    static f32 rot = 0.0f;
    SMeshBuffer *mesh = NULL;

    setTexture();
    setDrawEnv();

    rsxSetClearColor(context,color);
    rsxSetClearDepthValue(context,0xffff);
    rsxClearSurface(context,GCM_CLEAR_R |
                    GCM_CLEAR_G |
                    GCM_CLEAR_B |
                    GCM_CLEAR_A |
                    GCM_CLEAR_S |
                    GCM_CLEAR_Z);

    rsxZControl(context,0,1,1);

    for(i=0; i<8; i++)
        rsxSetViewportClip(context,i,display_width,display_height);

    viewMatrix = Matrix4::lookAt(eye_pos,eye_dir,up_vec);

    mesh = sphere;
    rotX = Matrix4::rotationX(DEGTORAD(30.0f));
    rotY = Matrix4::rotationY(DEGTORAD(rot));
    modelMatrix = rotX*rotY;
    modelMatrixIT = inverse(modelMatrix);
    modelViewMatrix = transpose(viewMatrix*modelMatrix);

    objEyePos = modelMatrixIT*eye_pos;
    objLightPos = modelMatrixIT*lightPos;

    wait_signal_spu();

    rsxBindVertexArrayAttrib(context,vertexPosition_id,mesh->pos_off,sizeof(S3DVertex),3,GCM_VERTEX_DATA_TYPE_F32,GCM_LOCATION_RSX);
    rsxBindVertexArrayAttrib(context,vertexNormal_id,mesh->nrm_off,sizeof(S3DVertex),3,GCM_VERTEX_DATA_TYPE_F32,GCM_LOCATION_RSX);
    rsxBindVertexArrayAttrib(context,vertexTexcoord_id,mesh->uv_off,sizeof(S3DVertex),2,GCM_VERTEX_DATA_TYPE_F32,GCM_LOCATION_RSX);

    rsxLoadVertexProgram(context,vpo,vp_ucode);
    rsxSetVertexProgramParameter(context,vpo,projMatrix_id,(float*)&P);
    rsxSetVertexProgramParameter(context,vpo,modelViewMatrix_id,(float*)&modelViewMatrix);

    rsxSetFragmentProgramParameter(context,fpo,eyePosition_id,(float*)&objEyePos,fp_offset);
    rsxSetFragmentProgramParameter(context,fpo,globalAmbient_id,globalAmbientColor,fp_offset);
    rsxSetFragmentProgramParameter(context,fpo,lightPosition_id,(float*)&objLightPos,fp_offset);
    //rsxSetFragmentProgramParameter(context,fpo,lightColor_id,lightColor,fp_offset);
    rsxSetFragmentProgramParameter(context,fpo,shininess_id,&shininess,fp_offset);

    rsxSetFragmentProgramParameter(context,fpo,Kd_id,materialColorDiffuse,fp_offset);
    rsxSetFragmentProgramParameter(context,fpo,Ks_id,materialColorSpecular,fp_offset);

    rsxLoadFragmentProgramLocation(context,fpo,fp_offset,GCM_LOCATION_RSX);

    rsxSetUserClipPlaneControl(context,GCM_USER_CLIP_PLANE_DISABLE,
                               GCM_USER_CLIP_PLANE_DISABLE,
                               GCM_USER_CLIP_PLANE_DISABLE,
                               GCM_USER_CLIP_PLANE_DISABLE,
                               GCM_USER_CLIP_PLANE_DISABLE,
                               GCM_USER_CLIP_PLANE_DISABLE);

    rsxDrawIndexArray(context,GCM_TYPE_TRIANGLES,mesh->ind_off,mesh->getIndexCount(),GCM_INDEX_TYPE_32B,GCM_LOCATION_RSX);

    mesh = donut;
    rotX = Matrix4::rotationX(DEGTORAD(rot));
    rotY = Matrix4::rotationY(DEGTORAD(30.0f));
    modelMatrix = rotX*rotY;
    modelMatrix.setTranslation(Vector3(3.0f,5.0f,-8.0f));

    modelMatrixIT = inverse(modelMatrix);
    modelViewMatrix = transpose(viewMatrix*modelMatrix);

    objEyePos = modelMatrixIT*eye_pos;
    objLightPos = modelMatrixIT*lightPos;

    rsxBindVertexArrayAttrib(context,vertexPosition_id,mesh->pos_off,sizeof(S3DVertex),3,GCM_VERTEX_DATA_TYPE_F32,GCM_LOCATION_RSX);
    rsxBindVertexArrayAttrib(context,vertexNormal_id,mesh->nrm_off,sizeof(S3DVertex),3,GCM_VERTEX_DATA_TYPE_F32,GCM_LOCATION_RSX);
    rsxBindVertexArrayAttrib(context,vertexTexcoord_id,mesh->uv_off,sizeof(S3DVertex),2,GCM_VERTEX_DATA_TYPE_F32,GCM_LOCATION_RSX);

    rsxLoadVertexProgram(context,vpo,vp_ucode);
    rsxSetVertexProgramParameter(context,vpo,projMatrix_id,(float*)&P);
    rsxSetVertexProgramParameter(context,vpo,modelViewMatrix_id,(float*)&modelViewMatrix);

    rsxSetFragmentProgramParameter(context,fpo,eyePosition_id,(float*)&objEyePos,fp_offset);
    rsxSetFragmentProgramParameter(context,fpo,globalAmbient_id,globalAmbientColor,fp_offset);
    rsxSetFragmentProgramParameter(context,fpo,lightPosition_id,(float*)&objLightPos,fp_offset);
    rsxSetFragmentProgramParameter(context,fpo,lightColor_id,lightColor,fp_offset);
    rsxSetFragmentProgramParameter(context,fpo,shininess_id,&shininess,fp_offset);

    rsxSetFragmentProgramParameter(context,fpo,Kd_id,materialColorDiffuse,fp_offset);
    rsxSetFragmentProgramParameter(context,fpo,Ks_id,materialColorSpecular,fp_offset);

    rsxLoadFragmentProgramLocation(context,fpo,fp_offset,GCM_LOCATION_RSX);

    rsxSetUserClipPlaneControl(context,GCM_USER_CLIP_PLANE_DISABLE,
                               GCM_USER_CLIP_PLANE_DISABLE,
                               GCM_USER_CLIP_PLANE_DISABLE,
                               GCM_USER_CLIP_PLANE_DISABLE,
                               GCM_USER_CLIP_PLANE_DISABLE,
                               GCM_USER_CLIP_PLANE_DISABLE);

    rsxDrawIndexArray(context,GCM_TYPE_TRIANGLES,mesh->ind_off,mesh->getIndexCount(),GCM_INDEX_TYPE_32B,GCM_LOCATION_RSX);

    clear_signal_spu();
    signal_spu_rsx();

    rot += 4.0f;
    if(rot>=360.0f) rot = 0.0f;
}
Пример #14
0
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
IAnimatedMesh* CSTLMeshFileLoader::createMesh(io::IReadFile* file)
{
	const long filesize = file->getSize();
	if (filesize < 6) // we need a header
		return 0;

	const u32 WORD_BUFFER_LENGTH = 512;

	SMesh* mesh = new SMesh();
	SMeshBuffer* meshBuffer = new SMeshBuffer();
	mesh->addMeshBuffer(meshBuffer);
	meshBuffer->drop();

	core::vector3df vertex[3];
	core::vector3df normal;

	c8 buffer[WORD_BUFFER_LENGTH];

	bool binary = false;
	file->read(buffer, 5);
	if (strncmp("solid", buffer, 5))
		binary = true;
	// read/skip header
	u32 binFaceCount = 0;
	if (binary)
	{
		file->seek(80);
		file->read(&binFaceCount, 4);
#ifdef __BIG_ENDIAN__
		binFaceCount = os::Byteswap::byteswap(binFaceCount);
#endif
	}
	else
		goNextLine(file);

	u16 attrib=0;
	core::stringc token;
	token.reserve(32);

	while (file->getPos() < filesize)
	{
		if (!binary)
		{
			if (getNextToken(file, token) != "facet")
			{
				if (token=="endsolid")
					break;
				mesh->drop();
				return 0;
			}
			if (getNextToken(file, token) != "normal")
			{
				mesh->drop();
				return 0;
			}
		}
		getNextVector(file, normal, binary);
		if (!binary)
		{
			if (getNextToken(file, token) != "outer")
			{
				mesh->drop();
				return 0;
			}
			if (getNextToken(file, token) != "loop")
			{
				mesh->drop();
				return 0;
			}
		}
		for (u32 i=0; i<3; ++i)
		{
			if (!binary)
			{
				if (getNextToken(file, token) != "vertex")
				{
					mesh->drop();
					return 0;
				}
			}
			getNextVector(file, vertex[i], binary);
		}
		if (!binary)
		{
			if (getNextToken(file, token) != "endloop")
			{
				mesh->drop();
				return 0;
			}
			if (getNextToken(file, token) != "endfacet")
			{
				mesh->drop();
				return 0;
			}
		}
		else
		{
			file->read(&attrib, 2);
#ifdef __BIG_ENDIAN__
			attrib = os::Byteswap::byteswap(attrib);
#endif
		}

		SMeshBuffer* mb = reinterpret_cast<SMeshBuffer*>(mesh->getMeshBuffer(mesh->getMeshBufferCount()-1));
		u32 vCount = mb->getVertexCount();
		video::SColor color(0xffffffff);
		if (attrib & 0x8000)
			color = video::A1R5G5B5toA8R8G8B8(attrib);
		if (normal==core::vector3df())
			normal=core::plane3df(vertex[2],vertex[1],vertex[0]).Normal;
		mb->Vertices.push_back(video::S3DVertex(vertex[2],normal,color, core::vector2df()));
		mb->Vertices.push_back(video::S3DVertex(vertex[1],normal,color, core::vector2df()));
		mb->Vertices.push_back(video::S3DVertex(vertex[0],normal,color, core::vector2df()));
		mb->Indices.push_back(vCount);
		mb->Indices.push_back(vCount+1);
		mb->Indices.push_back(vCount+2);
	}	// end while (file->getPos() < filesize)
	mesh->getMeshBuffer(0)->recalculateBoundingBox();

	// Create the Animated mesh if there's anything in the mesh
	SAnimatedMesh* pAM = 0;
	if ( 0 != mesh->getMeshBufferCount() )
	{
		mesh->recalculateBoundingBox();
		pAM = new SAnimatedMesh();
		pAM->Type = EAMT_OBJ;
		pAM->addMesh(mesh);
		pAM->recalculateBoundingBox();
	}

	mesh->drop();

	return pAM;
}
Пример #15
0
irr::scene::IMesh* MeshTools::createHillMesh(SurfaceQuadTree& tree, rectf section, double min_height, double max_height)
{
    std::vector<PsblVertPtr> triangles;

    /*
    tree.split(1);

    auto ptr = tree.child[1];
    for (int i=0; i<2; ++i)
    {
        ptr->split(1);
        ptr = ptr->child[3*(i+1)%4];
    }

    ptr = tree.child[2];
    for (int i=0; i<5; ++i)
    {
        ptr->split(1);
        ptr = ptr->child[3*(i+1)%4];
    }
    */

    struct Visitor : public SurfaceQuadTree::Visitor
    {
        vector<pair<QuadTreePtr, QuadTreePtr>> pairs;

        typedef tuple<QuadTreePtr, QuadTreePtr> edge;

        typedef vector<edge> triangle;
        vector<triangle> triangles;

        typedef vector<triangle>::const_iterator triangle_iter;
        std::map<edge, vector<triangle>> edge_to_triangle;

        bool crosses(edge e1, edge e2)
        {
            // Ignore if the edges share a vertex; that is not a crossing.
            if (
                get<0>(e1)->vert == get<0>(e2)->vert ||
                get<0>(e1)->vert == get<1>(e2)->vert ||
                get<1>(e1)->vert == get<0>(e2)->vert ||
                get<1>(e1)->vert == get<1>(e2)->vert
            )
                return false;

            // line2d(T xa, T ya, T xb, T yb)
            vector3df pos1a = get<0>(e1)->vert->getPos();
            vector3df pos1b = get<1>(e1)->vert->getPos();
            line2df line1(pos1a.X, pos1a.Y, pos1b.X, pos1b.Y);

            vector3df pos2a = get<0>(e2)->vert->getPos();
            vector3df pos2b = get<1>(e2)->vert->getPos();
            line2df line2(pos2a.X, pos2a.Y, pos2b.X, pos2b.Y);

            vector2df out;
            return line1.intersectWith(line2, out);
        }

        bool compareEdge(edge e, std::string from, std::string to)
        {
            return
                get<0>(e)->getPath() == from &&
                get<1>(e)->getPath() == to;
        }

        bool findEdge(triangle t, std::string from, std::string to)
        {
            return compareEdge(t[0], from, to) || compareEdge(t[1], from, to) || compareEdge(t[2], from, to);
        }

        virtual void addTriangle(QuadTreePtr a, QuadTreePtr b, QuadTreePtr c)
        {
            // If a,b,c already in triangles, duplicate triangle error.

            // foreach edge in the new triangle,
            // find other triangles that share one edge with this one
            // test the other 2x2 edges for intersection.
            triangle new_triangle(
            {
                make_tuple(a,b), make_tuple(b,c), make_tuple(c,a)
            });

            //if (findEdge(new_triangle, "Root SW SW SW NW SE", "Root SW SW SW NW NW"))
            //    cout << "found" << endl;

            //if (findEdge(new_triangle, "Root SW SW SW NW NE", "Root SW SW SW NW SW"))
            //    cout << "found" << endl;

            for (edge e_same : new_triangle)
                for (edge e_check : new_triangle)
                    if (e_same != e_check)
                        for (triangle contiguous : edge_to_triangle[e_same])
                            for (edge e_existing : contiguous)
                                if (e_existing != e_same)
                                    if (crosses(e_check, e_existing))
                                    {
                                        cout << "detected crossing, new is " << get<0>(e_check)->getPath() << "-" << get<1>(e_check)->getPath()
                                            << " old is " << get<0>(e_existing)->getPath() << "-" << get<1>(e_existing)->getPath() << endl;
                                    }

            triangles.push_back(new_triangle);
            edge_to_triangle[make_tuple(a,b)].push_back(new_triangle);
            edge_to_triangle[make_tuple(b,c)].push_back(new_triangle);
            edge_to_triangle[make_tuple(c,a)].push_back(new_triangle);
            edge_to_triangle[make_tuple(b,a)].push_back(new_triangle);
            edge_to_triangle[make_tuple(c,b)].push_back(new_triangle);
            edge_to_triangle[make_tuple(a,c)].push_back(new_triangle);
        }

        virtual void check(QuadTreePtr a1, QuadTreePtr a2, QuadTreePtr b1, QuadTreePtr b2)
        {
        }
    };

    Visitor visitor;
    tree.triangulate(triangles, section, min_height, max_height, &visitor);
    //tree.sweep(triangles, section, &visitor);

   //cout << "num triangle points: " << triangles.size() << endl;

    vector<QuadTreePtr> leaves;
    tree.dumpLeaves(leaves);

    //cout << "num leaves: " << leaves.size() << endl;

/*
    for (QuadTreePtr p1 : leaves)
        for (QuadTreePtr p2 : leaves)
            if (p1 != p2)
                if (p1->isAdjacent(p2))
                    if (!visitor.has(p1, p2))
                    {
                        auto sz1 = p1->region.getSize();
                        auto sz2 = p2->region.getSize();
                        auto c1 = p1->region.getCenter();
                        auto c2 = p2->region.getCenter();
                        char const* path1 = p1->getPath().c_str();
                        char const* path2 = p2->getPath().c_str();
                        cout << path1 << endl;
                        cout << path2 << endl;
                        cout << "Missing pair of adjacent vertices." << endl;
                    }

    float x1 = section.UpperLeftCorner.X;
    float x2 = section.LowerRightCorner.X;
    float y1 = section.UpperLeftCorner.Y;
    float y2 = section.LowerRightCorner.Y;
*/
    /*
        d---c
        | / |
        a---b
    */

    /*
    S3DVertex sa;
    sa.Pos = vector3df(x1, y1, 0);
    PsblVertPtr a = new PossibleVertex(sa);

    S3DVertex sb;
    sb.Pos = vector3df(x2, y1, 0);
    PsblVertPtr b = new PossibleVertex(sb);

    S3DVertex sc;
    sc.Pos = vector3df(x2, y2, 0);
    PsblVertPtr c = new PossibleVertex(sc);

    S3DVertex sd;
    sd.Pos = vector3df(x1, y2, 0);
    PsblVertPtr d = new PossibleVertex(sd);

    // a-b-c
    // a-c-d
    triangles.push_back(a);
    triangles.push_back(b);
    triangles.push_back(c);

    triangles.push_back(a);
    triangles.push_back(c);
    triangles.push_back(d);

    triangles.push_back(c);
    triangles.push_back(b);
    triangles.push_back(a);

    triangles.push_back(d);
    triangles.push_back(c);
    triangles.push_back(a);
    */

	SMeshBuffer* buffer = new SMeshBuffer();

    for (auto pv : triangles)
        pv->addToMeshBuf(buffer, vector3df());

    if (buffer->getIndexCount() % 3 > 0)
        throw std::logic_error("SurfaceQuadTree triangulation added a 'triangle' with less than 3 vertices in it.");

    //cout << "num vertices " << buffer->getVertexCount() << endl;
    //cout << "num indices " << buffer->getIndexCount() << endl;

	buffer->recalculateBoundingBox();
	buffer->setHardwareMappingHint(EHM_STATIC);

	SMesh* mesh = new SMesh();
	mesh->addMeshBuffer(buffer);
	mesh->recalculateBoundingBox();
	buffer->drop();

	return mesh;
}
Пример #16
0
IMesh* MeshTools::createMeshFromHeightmap(IImage* image, dimension2du tileSizeInPixels, vector2di tilePosInTiles, bool extraStripsOnEdges)
{
    // Use top corner of image to get bias for centering the Z axis.
    float imageZeroBias = image->getPixel(0,0).getAverage();

    dimension2du imageDimension = image->getDimension();

    // Easier to think of script working in whole tile units, so handle conversion to pixel pos in this method:
    vector2di startAtPixel = tilePosInTiles * vector2di(tileSizeInPixels.Width, tileSizeInPixels.Height);

    // However we're going to invert the image Y axis so that the bottom of the picture will be at 0,0 in world space,
    // and the top of the picture will be at +Y in world space.
    startAtPixel.Y = (imageDimension.Height-1) - startAtPixel.Y;

    // Return nothing if the tile is outside the image, or if the resulting mesh would have only 0 or 1 rows or columns.
    // Doing this check early prevents getting underflow when we clip the tile size to the image dimensions a few statements down.
    if (startAtPixel.X < 0 || startAtPixel.X >= (imageDimension.Width-1) || startAtPixel.Y <= 0 || startAtPixel.Y > (imageDimension.Height-1))
        return NULL;

    // Calculate whether to use tile size or tile size + 1 (for generating overlap)
    // Adding the extra strip amount before clipping to image dimensions prevents overflowing the image edges after clipping.
    dimension2du useTileSize = tileSizeInPixels + (extraStripsOnEdges? dimension2du(1,1) : dimension2du(0,0));

    // Clip the tile size if we're dealing with a "leftover" amount at the edge that's not a whole tile's width or height.
    // Most heightmap implementations require exactly a power of 2 + 1 square dimensions like 257x257, but supporting
    // image sizes that are not whole multiples of tile size is as simple as this one line of code and supporting
    // image sizes that are not square is a nice feature for a platformer game so you can have levels that are longer
    // than they are tall.
    useTileSize.set(min(useTileSize.Width, imageDimension.Width-startAtPixel.X), min(useTileSize.Height, (u32)startAtPixel.Y+1));

	SMeshBuffer* buffer = new SMeshBuffer();

	// Preallocate vertex buffer to the size we know we'll need.
	buffer->Vertices.set_used(useTileSize.Width*useTileSize.Height);

	// Amount of TCoord per unit of x,y in image.
    vector2df tCoordsScale(1.0f / useTileSize.Width, 1.0f / useTileSize.Height);

    // Whether we put y on the outside or x on the outside, doesn't matter, because we are
    // using getIndex() to find where x and y map too.  However, I happen to know I made getIndex
    // put x's together, y in rows, and looping in the same rank order might have better cache performance
    // because it should access the vertices in the same order they are in the array.
    for (u32 y=0; y < useTileSize.Height; ++y)
    {
        for (u32 x=0; x < useTileSize.Width; ++x)
        {
            u32 index = getIndex(useTileSize, x, y);
            S3DVertex& vert = buffer->Vertices[index];

            // No special coloration
            vert.Color = SColor(255,255,255,255);

            // Scale texture to tile.
            vert.TCoords = vector2df(x,y) * tCoordsScale;

            // y axis starts with 0 at image bottom and goes up.
            vector2di pixelPos(
                startAtPixel.X+x,
                startAtPixel.Y-y
            );

            SColor heightColor = image->getPixel(pixelPos.X, pixelPos.Y);
            float thisHeight = imageZeroBias - heightColor.getAverage();

            vert.Pos.set(x, y, thisHeight);

            // I'm only averaging normals along the 4 compass directions.  It's
            // arguable whether diagonals should count; I chose to ignore diagonals.
            // Ignoring diagonals allows me to assume the "run" in rise/run is always
            // just one unit; if you add diagonals here you'll also need to change
            // the slope calculation to use the actual distance instead of assuming 1.
            vector2di offsetsArray[] = {
                vector2di( 1, 0),  //  3 o'clock
                vector2di( 0, 1),  // 12 o'clock
                vector2di(-1, 0),  //  9 o'clock
                vector2di( 0,-1)   //  6 o'clock
            };

            // Calculate the normals of the surrounding slopes.
            // Uses the image, not just the tile patch size, so it will
            // calculate correct normals for vertices on tile edges.
            for (size_t i=-0; i < 4; ++i)
            {
                vector2di offset = vector2di(x,y) + offsetsArray[i];

                // Skip this offset if it's outside the image
                if (offset.X < 0 || offset.Y < 0 || offset.X >= (s32)imageDimension.Width || offset.Y >= (s32)imageDimension.Height)
                    continue;

                vector2di otherPixelPos(
                    startAtPixel.X+x+offset.X,
                    startAtPixel.Y-y-offset.Y
                );
                float otherHeight = 255 - image->getPixel((u32)otherPixelPos.X, (u32)otherPixelPos.Y).getAverage();

                // The code Irrlicht's in terrain scene node does all kinds of complicated
                // business with cross products and such - waaay over complicated.  You don't need
                // all that stuff.  Dude it' s a heightmap: all you need to worray about is
                // rise over run on unit intervals!  Algebra 1 type stuff, y = mx + c

                // Calculate the rise of the line over the run, taking into account the fact
                // that the offset could be in either direction.
                float rise = (offset.X < 0 || offset.Y < 0)? thisHeight - otherHeight : otherHeight - thisHeight;

                // Assuming that run = 1, m = rise / run is just m = rise.
                float m = rise;

                // The the slope of the normal is just the negative of the reciprocal of the line slope.
                float n = -1.0f / rise;

                // The X,Y of the normal vector is just going to be the X and Y of the offset
                // (think about it - obviously the normal of the slope must tilt in the direction of the run)
                // and the Z of the normal vector is just the slope of the normal over that run.
                vector3df normVect(offset.X, offset.Y, n);

                //vert.Normal += normVect;
            }

            //vert.Normal.normalize();
            vert.Normal.set(0,0,-1.0f);
        }
    }

    // Pre-allocate index data to 2*3*Width*Height for triangles.
    // There is actually 1 less square per count of vertices though,
    // for instance if you had 2x2 vertices, you only have 1 square.
    buffer->Indices.set_used(2*3*(useTileSize.Width-1)*(useTileSize.Height-1));

    // Start with 1 and generate all the triangles from their top right corners.
    // Like this (A is top right corner at x,y):
    //
    //              y=1  B---A
    //                   | / |
    //              y=0  C---D
    //                  x=0 x=1
    for (u32 dst=0, x=1; x < useTileSize.Width; ++x)
    {
        for (u32 y=1; y < useTileSize.Height; ++y)
        {
            u32 A = getIndex(useTileSize, x,   y   );
            u32 B = getIndex(useTileSize, x-1, y   );
            u32 C = getIndex(useTileSize, x-1, y-1 );
            u32 D = getIndex(useTileSize, x,   y-1 );

            buffer->Indices[dst++] = C;
            buffer->Indices[dst++] = B;
            buffer->Indices[dst++] = A;

            buffer->Indices[dst++] = D;
            buffer->Indices[dst++] = C;
            buffer->Indices[dst++] = A;
        }
    }

	buffer->recalculateBoundingBox();
	buffer->setHardwareMappingHint(EHM_STATIC);

	SMesh* mesh = new SMesh();
	mesh->addMeshBuffer(buffer);
	mesh->recalculateBoundingBox();
	buffer->drop();
	return mesh;
}
// creates a hill plane
IAnimatedMesh* CGeometryCreator::createHillPlaneMesh(const core::dimension2d<f32>& tileSize, const core::dimension2d<s32>& tc,
        video::SMaterial* material,     f32 hillHeight, const core::dimension2d<f32>& ch,
        const core::dimension2d<f32>& textureRepeatCount)
{
    core::dimension2d<s32> tileCount = tc;
    tileCount.Height += 1;
    tileCount.Width += 1;

    core::dimension2d<f32> countHills = ch;

    SMeshBuffer* buffer = new SMeshBuffer();
    SMesh* mesh = new SMesh();
    video::S3DVertex vtx;
    vtx.Color.set(255,255,255,255);
    vtx.Normal.set(0,0,0);

    if (countHills.Width < 0.01f) countHills.Width = 1;
    if (countHills.Height < 0.01f) countHills.Height = 1;

    f32 halfX = (tileSize.Width * tileCount.Width) / 2;
    f32 halfY = (tileSize.Height * tileCount.Height) / 2;

    // create vertices

    s32 x = 0;
    s32 y = 0;

    core::dimension2d<f32> tx;
    tx.Width = 1.0f / (tileCount.Width / textureRepeatCount.Width);
    tx.Height = 1.0f / (tileCount.Height / textureRepeatCount.Height);


    for (x=0; x<tileCount.Width; ++x)
        for (y=0; y<tileCount.Height; ++y)
        {
            vtx.Pos.set(tileSize.Width * x - halfX, 0, tileSize.Height * y - halfY);
            vtx.TCoords.set(-(f32)x * tx.Width, (f32)y * tx.Height);

            if (hillHeight)
                vtx.Pos.Y = (f32)(sin(vtx.Pos.X * countHills.Width * engine::core::PI / halfX) *
                                  cos(vtx.Pos.Z * countHills.Height * engine::core::PI / halfY))
                            *hillHeight;

            buffer->Vertices.push_back(vtx);
        }

    // create indices

    for (x=0; x<tileCount.Width-1; ++x)
        for (y=0; y<tileCount.Height-1; ++y)
        {
            s32 current = y*tileCount.Width + x;

            buffer->Indices.push_back(current);
            buffer->Indices.push_back(current + 1);
            buffer->Indices.push_back(current + tileCount.Width);

            buffer->Indices.push_back(current + 1);
            buffer->Indices.push_back(current + 1 + tileCount.Width);
            buffer->Indices.push_back(current + tileCount.Width);
        }

    // recalculate normals
    for (s32 i=0; i<(s32)buffer->Indices.size(); i+=3)
    {
        core::plane3d<f32> p(
            buffer->Vertices[buffer->Indices[i+0]].Pos,
            buffer->Vertices[buffer->Indices[i+1]].Pos,
            buffer->Vertices[buffer->Indices[i+2]].Pos);

        p.Normal.normalize();

        buffer->Vertices[buffer->Indices[i+0]].Normal = p.Normal;
        buffer->Vertices[buffer->Indices[i+1]].Normal = p.Normal;
        buffer->Vertices[buffer->Indices[i+2]].Normal = p.Normal;
    }

    if (material)
        buffer->Material = *material;

    buffer->recalculateBoundingBox();

    SAnimatedMesh* animatedMesh = new SAnimatedMesh();
    mesh->addMeshBuffer(buffer);
    mesh->recalculateBoundingBox();
    animatedMesh->addMesh(mesh);
    animatedMesh->recalculateBoundingBox();

    mesh->drop();
    buffer->drop();

    return animatedMesh;
}
Пример #18
0
MeshTools::SplitMeshResult MeshTools::splitMeshZ(IMesh* oldMesh, float zCut, float zInsert, bool marginalTrisInLeft, bool marginalTrisInRight)
{
    IMeshBuffer* oldMeshBuf = oldMesh->getMeshBuffer(0);
    u16* oldInd = oldMeshBuf->getIndices();
	SMeshBuffer* leftMeshBuf = new SMeshBuffer();
	SMeshBuffer* rightMeshBuf = new SMeshBuffer();
    LinkSplitter linkSplitter(oldMeshBuf, zCut);

    vector3df const offset(0,0, zInsert);

    set<pair<PsblVertPtr, PsblVertPtr>> leftEdgeLinks;
    set<pair<PsblVertPtr, PsblVertPtr>> rightEdgeLinks;

    for (u32 i=0; i < oldMeshBuf->getIndexCount(); i += 3)
    {
        // Calling these shapes instead of triangles because they could be triangle or a quad after slice,
        // (it could also be a degenerate case of a line or a point - those will be discarded by addConvexShape)
        vector<PsblVertPtr> leftShape;
        vector<PsblVertPtr> rightShape;

        int a = oldInd[i];
        int b = oldInd[i+1];
        int c = oldInd[i+2];

        PsblVertPtr mid1;
        PsblVertPtr mid2;
        PsblVertPtr mid3;

        // Don't create a copy just for a triangle that is just kissing the edge.  Leave it in the background.
        if (linkSplitter.compareZ(a)==0 && linkSplitter.compareZ(b)==0 && linkSplitter.compareZ(c)==0)
        {
            if (marginalTrisInLeft)
            {
                leftShape.push_back(linkSplitter.getVert(a));
                leftShape.push_back(linkSplitter.getVert(b));
                leftShape.push_back(linkSplitter.getVert(c));
            }

            if (marginalTrisInRight)
            {
                rightShape.push_back(linkSplitter.getVert(a));
                rightShape.push_back(linkSplitter.getVert(b));
                rightShape.push_back(linkSplitter.getVert(c));
            }
        }
        else
        {
            // This is something I had to think hard about so I'm writing this comment so I don't
            // have to think it through again or forget it:
            //
            // Both the left shape and the right shape, and both the triangle and the quad, "magically"
            // come out with correct winding order when the triangle is split.  Here's why:
            //  Let the original triangle vertices be A-B-C.
            //  Let the split midpoints be AB' and CA' as A-B is split and C-A are split respectively.
            // The shapes (ignore which shape is left or right, call them P and Q instead)
            // will be filled in the following order:
            //
            //  round       P   Q       Comment
            //  1           A   -       A is not in Q at all
            //  1 cont.     AB' AB'     AB' replaces B in P
            //  2           -   B       B proper is in Q and not in P
            //  2 cont.     -   -       Link B-C is not split
            //  3           -   C       C proper is in Q and not in P
            //  3 cont.     CA' CA'     CA' replaces C in P
            //
            // Now, read the columns P and Q vertically top to bottom to see the resultant vertex order.
            // The triangle P is trivially still the correct winding order; it is just a smaller triangle now.
            // The new quad Q retains the old triangle's winding order property for the following reason:
            //  As you wrapped around a full circle in old triangle A-B-C you would have traversed C-A then A-B.
            //      The link C-A has been cut and vertex CA' inserted.
            //      The link A-B has been cut and vertex AB' inserted.
            //  If you traverse the new shape starting from the _middle_ you follow the following path:
            //      B-C     C-CA'   CA'-AB'    AB'-B    B-C (again)
            //  Compare to old triangle:
            //      B-C          C-A        A-B         B-C (again)
            //  Even though vertex A has been cut off and replaced with two vertices, the two
            //  new vertices lie along the path that the old links took and are in the new shape in the right order.

            mid1 = linkSplitter.processLink(leftShape, rightShape, a, b);
            mid2 = linkSplitter.processLink(leftShape, rightShape, b, c);
            mid3 = linkSplitter.processLink(leftShape, rightShape, c, a);
        }

        // If a triangle was split then two of those three midpoints are inhabited by a vertex.
        // We want to get them both in mid1 and mid2 AND we need them in correct order.
        PsblVertPtr cut1 = (mid1 && mid2)? mid1 : mid2;
        PsblVertPtr cut2 = (mid2 && mid3)? mid3 : mid2;

        if (cut1 && cut2)
        {
            vector<PsblVertPtr> chain = linkSplitter.chopLink(cut1, cut2, 1);
            linkSplitter.insertPoints(leftShape, cut1, cut2, chain);
            linkSplitter.insertPoints(rightShape, cut1, cut2, chain);
        }

        linkSplitter.addConvexShape(leftShape, leftMeshBuf,   -offset/2);
        linkSplitter.addConvexShape(rightShape, rightMeshBuf,  offset/2);

        // Add any edges of the left shape that lie along the border.
        linkSplitter.addEdgeLinks(leftShape, leftEdgeLinks);

        // Right side polys that share a border with left side ones will have
        // opposite winding order.  In order for set_intersection to consider them
        // as matches, we'll store the right side links in reversed order.
        std::reverse(rightShape.begin(), rightShape.end());
        linkSplitter.addEdgeLinks(rightShape, rightEdgeLinks);
    }

	SMesh* leftMesh = new SMesh();
	leftMeshBuf->recalculateBoundingBox();
	leftMeshBuf->setHardwareMappingHint(EHM_STATIC);
    leftMesh->addMeshBuffer(leftMeshBuf);
	leftMesh->recalculateBoundingBox();
	leftMeshBuf->drop();  // we drop the buf, mesh obj has it now

	SMesh* rightMesh = new SMesh();
	rightMeshBuf->recalculateBoundingBox();
	rightMeshBuf->setHardwareMappingHint(EHM_STATIC);
    rightMesh->addMeshBuffer(rightMeshBuf);
	rightMesh->recalculateBoundingBox();
	rightMeshBuf->drop();  // we drop the buf, mesh obj has it now

    SMesh* middleMesh = NULL;
    if (zInsert > 0)
    {
        set<pair<PsblVertPtr,PsblVertPtr>> result;
        std::set_intersection(
            leftEdgeLinks.begin(), leftEdgeLinks.end(),
            rightEdgeLinks.begin(), rightEdgeLinks.end(),
            std::inserter(result, result.begin())
        );

        size_t debugsize = result.size();

        if (result.size() > 0)
        {
            SMeshBuffer* middleMeshBuf = new SMeshBuffer();

            vector<PsblVertPtr> shape(4);
            for (auto it=result.begin(); it!=result.end(); ++it)
            {
                shape[0] = it->second;
                shape[1] = it->first;
                shape[2] = it->first->duplicate(offset);
                shape[3] = it->second->duplicate(offset);
                linkSplitter.addConvexShape(shape, middleMeshBuf, -offset/2);
            }

            middleMesh = new SMesh();
            middleMeshBuf->recalculateBoundingBox();
            middleMeshBuf->setHardwareMappingHint(EHM_STATIC);
            middleMesh->addMeshBuffer(middleMeshBuf);
            middleMesh->recalculateBoundingBox();
            middleMeshBuf->drop();  // we drop the buf, mesh obj has it now
        }
    }

	return SplitMeshResult {leftMesh, middleMesh, rightMesh};
}
Пример #19
0
    GLlink(ISceneNode *i_parent, ISceneManager *i_mgr, s32 i_id,
           const LinkInfo &i_li, BodyInfo_var i_binfo) :
        ISceneNode(i_parent, i_mgr, i_id),
        m_jointId(i_li.jointId) {
        setAutomaticCulling(scene::EAC_OFF);


        setPosition(vector3df( i_li.translation[0],
                               -i_li.translation[1],
                               i_li.translation[2]));
        Vector3 axis(i_li.rotation[0],
                     i_li.rotation[1],
                     i_li.rotation[2]);
        Matrix33 R;
        hrp::calcRodrigues(R, axis, i_li.rotation[3]);
        Vector3 rpy(rpyFromRot(R));
        //std::cout << "rpy:" << rpy << std::endl;
        setRotation(vector3df(-180/M_PI*rpy[0],
                              180/M_PI*rpy[1],
                              -180/M_PI*rpy[2]));

        m_axis << i_li.jointAxis[0], i_li.jointAxis[1], i_li.jointAxis[2];

        ShapeInfoSequence_var sis = i_binfo->shapes();
        AppearanceInfoSequence_var ais = i_binfo->appearances();
        MaterialInfoSequence_var mis = i_binfo->materials();
        TextureInfoSequence_var txs = i_binfo->textures();
        const TransformedShapeIndexSequence& tsis = i_li.shapeIndices;


        core::vector3df vertex;
        core::vector3df normal;

        for (unsigned int l=0; l<tsis.length(); l++) {
            SMesh* mesh = new SMesh();
            SMeshBuffer* meshBuffer = new SMeshBuffer();
            mesh->addMeshBuffer(meshBuffer);
            meshBuffer->drop();

            const TransformedShapeIndex &tsi = tsis[l];
            short index = tsi.shapeIndex;
            ShapeInfo& si = sis[index];
            const float *vertices = si.vertices.get_buffer();
            const LongSequence& triangles = si.triangles;
            const AppearanceInfo& ai = ais[si.appearanceIndex];
            const float *normals = ai.normals.get_buffer();
            //std::cout << "length of normals = " << ai.normals.length() << std::endl;
            const LongSequence& normalIndices = ai.normalIndices;
            //std::cout << "length of normalIndices = " << normalIndices.length() << std::endl;
            const int numTriangles = triangles.length() / 3;
            //std::cout << "numTriangles = " << numTriangles << std::endl;

            video::SColor color(0xffffffff);
            if (ai.colors.length()) {
                color.set(0xff,
                          0xff*ai.colors[0],
                          0xff*ai.colors[1],
                          0xff*ai.colors[2]);
            } else if (ai.materialIndex >= 0) {
                const MaterialInfo& mi = mis[ai.materialIndex];
                color.set(0xff,
                          0xff*mi.diffuseColor[0],
                          0xff*mi.diffuseColor[1],
                          0xff*mi.diffuseColor[2]);
            } else {
                std::cout << "no material" << std::endl;
            }


            SMeshBuffer* mb = reinterpret_cast<SMeshBuffer*>(mesh->getMeshBuffer(mesh->getMeshBufferCount()-1));
            u32 vCount = mb->getVertexCount();

            const DblArray12& tfm = tsi.transformMatrix;
            CMatrix4<f32> cmat;
            for (int i=0; i<3; i++) {
                for (int j=0; j<4; j++) {
                    cmat[j*4+i] = tfm[i*4+j];
                }
            }
            cmat[3] = cmat[7] = cmat[11] = 0.0;
            cmat[15] = 1.0;
            vector3df pos = cmat.getTranslation();
            pos.Y *= -1;
            vector3df rpy = cmat.getRotationDegrees();
            rpy.X *= -1;
            rpy.Z *= -1;
            vector3df scale = cmat.getScale();

            const float *textureCoordinate = NULL;
            if (ai.textureIndex >= 0) {
                textureCoordinate = ai.textureCoordinate.get_buffer();
                //std::cout << "length of textureCoordinate:" << ai.textureCoordinate.length() << std::endl;
                //std::cout << "length of vertices:" << si.vertices.length() << std::endl;

            }

            for(int j=0; j < numTriangles; ++j) {
                if (!ai.normalPerVertex) {
                    int p;
                    if (normalIndices.length() == 0) {
                        p = j*3;
                    } else {
                        p = normalIndices[j]*3;
                    }
                    if ( normals != NULL ) {
                        normal.X =  normals[p];
                        normal.Y = -normals[p+1]; //left-handed->right-handed
                        normal.Z =  normals[p+2];
                    } else {
                        normal.X = 0;
                        normal.Y = 0;
                        normal.Z = 1;
                    }
                }
                for(int k=0; k < 3; ++k) {
                    long orgVertexIndex = si.triangles[j * 3 + k];
                    if (ai.normalPerVertex) {
                        int p;
                        if (normalIndices.length()) {
                            p = normalIndices[j*3+k]*3;
                        } else {
                            p = orgVertexIndex*3;
                        }
                        normal.X =  normals[p];
                        normal.Y = -normals[p+1]; //left-handed -> right-handed
                        normal.Z =  normals[p+2];
                    }
                    int p = orgVertexIndex * 3;
                    vertex.X =  scale.X*vertices[p];
                    vertex.Y = -scale.Y*vertices[p+1]; // left-handed -> right-handed
                    vertex.Z =  scale.Z*vertices[p+2];
                    //std::cout << vertices[p] <<"," << vertices[p+1] << "," << vertices[p+2] << std::endl;
                    vector2df texc;
                    if (textureCoordinate) {

                        texc.X = textureCoordinate[ai.textureCoordIndices[j*3+k]*2];
                        texc.Y = textureCoordinate[ai.textureCoordIndices[j*3+k]*2+1];
                    }
                    // redundant vertices
                    mb->Vertices.push_back(video::S3DVertex(vertex,normal,color, texc));
                }
                mb->Indices.push_back(vCount);
                mb->Indices.push_back(vCount+2);
                mb->Indices.push_back(vCount+1);
                vCount += 3;
            }
            mesh->getMeshBuffer(0)->recalculateBoundingBox();

            // Create the Animated mesh if there's anything in the mesh
            SAnimatedMesh* pAM = 0;
            if ( 0 != mesh->getMeshBufferCount() )
            {
                mesh->recalculateBoundingBox();
                pAM = new SAnimatedMesh();
                pAM->Type = EAMT_OBJ;
                pAM->addMesh(mesh);
                pAM->recalculateBoundingBox();
            }

            mesh->drop();

            vector3df noscale(1,1,1);

            IMeshSceneNode *node
                = i_mgr->addMeshSceneNode(mesh, this, -1,
                                          pos,
                                          rpy,
                                          noscale);

            if (ai.textureIndex >= 0) {
                const TextureInfo& ti = txs[ai.textureIndex];
                //std::cout << "url:" << ti.url << std::endl;
                video::IVideoDriver* driver = i_mgr->getVideoDriver();
                const char *path = ti.url;
                SMaterial& mat = node->getMaterial(0);
                ITexture *texture = driver->getTexture(path);
                mat.setTexture( 0, texture);
            }

        }

        const SensorInfoSequence& sensors = i_li.sensors;
        for (unsigned int i=0; i<sensors.length(); i++) {
            const SensorInfo& si = sensors[i];
            std::string type(si.type);
            if (type == "Vision") {
                //std::cout << si.name << std::endl;
                ISceneNode *camera = i_mgr->addEmptySceneNode(this);
                camera->setName(si.name);
                camera->setPosition(vector3df( si.translation[0],
                                               -si.translation[1],
                                               si.translation[2]));
                Vector3 axis(si.rotation[0],
                             si.rotation[1],
                             si.rotation[2]);
                Matrix33 R;
                hrp::calcRodrigues(R, axis, si.rotation[3]);
                Vector3 rpy(rpyFromRot(R));
                camera->setRotation(vector3df(-180/M_PI*rpy[0],
                                              180/M_PI*rpy[1],
                                              -180/M_PI*rpy[2]));
                m_cameraInfos.push_back(new GLcamera(si, camera));
            }
        }
    }
Пример #20
0
SMeshBuffer* createRainbowMeshBuffer( // XY-plane, normale is -Z
		f32 outerRadius,
		f32 innerRadius,
		f32 zAngleStart,
		f32 zAngleEnd,
		u32 segments,
		const core::vector3df& pos)
{
	SMeshBuffer* buffer = new SMeshBuffer();
	if (!buffer)
		return 0;

	//! outer-cylinder material
	buffer->Material.Lighting = false;
	buffer->Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
	buffer->Material.Wireframe = false;
	buffer->Material.FogEnable = false;
	buffer->Material.BackfaceCulling = true;
	buffer->Vertices.clear();
	buffer->Indices.clear();
//	buffer->Vertices.reallocate();
//	buffer->Vertices.set_used(0);
//	buffer->Indices.reallocate();
//	buffer->Indices.set_used(0);

	//! Constants
	const f32 phi = 2.0f*core::PI * (zAngleEnd-zAngleStart) / (360.0f * (f32)segments);
	const f32 phiStart = 2.0f*core::PI * (zAngleStart-90.0f) / 360.0f;
	const f32 z = pos.Z;

	//! Locals
	f32 x0,y0,x1,y1,x2,y2,x3,y3,sinPhi,cosPhi;

	//! Tables
	f32* sinTable = new f32[segments+1];
	f32* cosTable = new f32[segments+1];

	for (u32 i=0; i<segments+1; ++i)
	{
		const f32 angle = (f32)i*phi + phiStart;
		sinTable[i] = sinf(angle);
		cosTable[i] = cosf(angle);
	}

	//! build MeshBuffer (each segment consists of 2 triangles, important for texturing, each segment contains one complete texture)
	for (u32 i=0; i<segments; ++i)
	{
		x0 = pos.X - innerRadius * sinTable[i+1];
		y0 = pos.Y + innerRadius * cosTable[i+1];
		x1 = pos.X - outerRadius * sinTable[i+1];
		y1 = pos.Y + outerRadius * cosTable[i+1];
		x2 = pos.X - outerRadius * sinTable[i];
		y2 = pos.Y + outerRadius * cosTable[i];
		x3 = pos.X - innerRadius * sinTable[i];
		y3 = pos.Y + innerRadius * cosTable[i];

		buffer->Vertices.push_back(video::S3DVertex(x0,y0,z,0,0,-1,0xFFFFFFFF,0,1)); // A
		buffer->Vertices.push_back(video::S3DVertex(x1,y1,z,0,0,-1,0xFFFFFFFF,0,0)); // B
		buffer->Vertices.push_back(video::S3DVertex(x2,y2,z,0,0,-1,0xFFFFFFFF,1,0)); // C
		buffer->Vertices.push_back(video::S3DVertex(x3,y3,z,0,0,-1,0xFFFFFFFF,1,1)); // D
		buffer->Indices.push_back(4*i+0); // A
		buffer->Indices.push_back(4*i+1); // B
		buffer->Indices.push_back(4*i+2); // C
		buffer->Indices.push_back(4*i+0); // A
		buffer->Indices.push_back(4*i+2); // C
		buffer->Indices.push_back(4*i+3); // D
	}

	delete [] sinTable;
	delete [] cosTable;

	//! BBox
	buffer->recalculateBoundingBox();
	return buffer;

} // END FUNCTION