Προς το περιεχόμενο

[share] 3d console


παπι

Προτεινόμενες αναρτήσεις

Απλα λεω να μοιρασω αυτο το περιεργο πραγμα που εφτιαξα.

 

 

//papi

#define USEWIN 0



#define NOMINMAX 
#include <Windows.h>
#include <algorithm>
#include <iterator>
#include <string>
#include <vector>
#include <iostream>


class Console2D
{
	int height,width;
	char background;
	struct {float x,y;} cursor;
	std::vector<char> buffer;
	std::vector<char> backbuffer;
public:
	Console2D(int height, int width,char background = ' ') : 
	  height(height), width(width), background(background)
		, buffer(height*width)
	{
		cursor.x = 0.0f;
		cursor.y = 0.0f;
		std::fill(buffer.begin(),buffer.end(),background);
	}
	void Clear()
	{
		std::fill(buffer.begin(),buffer.end(),background);
		system("cls");
	}
	void Present()
	{
		PresentEx();
		return;
		int pad = 1;
		for(auto it = buffer.begin(); it != buffer.end(); it++,pad++)
		{
			std::cout<<*it;
			if(!(pad % width))
				std::cout<<std::endl;
		}
	}
	void PresentEx()
	{
		//h console pio argh kai apo to 8anato....
		int pad = 1;
		std::string tmp;
		for(auto it = buffer.begin(); it != buffer.end(); it++,pad++)
		{
			tmp.push_back(*it);
			if(!(pad % width))
			{
				std::string tmp1;
				std::reverse(tmp.begin(),tmp.end());
				for(auto t = tmp.begin(); t!= tmp.end(); ++t)
				{
					if(*t == ' ')
						continue;
					tmp1.assign(t,tmp.end());
					break;
				}
				std::reverse(tmp1.begin(),tmp1.end());
				std::cout<<tmp1<<std::endl;
				tmp.clear();
			}
		}
	}
	void Plot(int x, int y)
	{
		int p =  y * width + x ;
		if(x < 0 || x > width ||y < 0 || y > height)
			return;
		buffer[p] = '*';
	}
	void LineTo(float x,float y)
	{
		Line(cursor.x,cursor.y,x,y);
		SetCursor(x,y);
	}
	void SetCursor(float x,float y)
	{
		cursor.x = x;
		cursor.y = y;
	}
	void Line(float x0,float y0,float x1,float y1)
	{
		float x = x1-x0;
		float y = y1-y0;
		float len = std::sqrt(x*x+y*y);
		x /= len;
		y /= len;
		for(float i = 0.f -len; i < 0.f; i+= 1.f)
			Plot((x0 + x * (len + i))  , (y0 + y * ( len +i ))  );
	}
	int Height(){return this->height;}
	int Width(){return this->width;}
};
struct Vector3
{
	float x,y,z;
	Vector3()(0.f),y(0.f),z(0.f)
	{
	}
	Vector3(float x, float y, float z) :
	x(x),y(y),z(z)
	{
	}
	Vector3 operator/ (float n)
	{
		if(n)
			return Vector3(x/n,y/n,z/n);
		return Vector3();
	}
	Vector3 operator- (const Vector3& r) const
	{
		return Vector3(x-r.x,y-r.y,z-r.z);
	}
	Vector3& operator/= (float n)
	{
		*this = *this / n;
		return *this;
	}
	Vector3& Normalize()
	{
		*this /= this->Len();
		return *this;
	}
	Vector3 Cross(const Vector3& r) const
	{
		return Vector3(
			y * r.z - z * r.y,
			z * r.x - x * r.z,
			x * r.y - y * r.x);
	}
	float Dot(const Vector3& r) const
	{
		return x * r.x + y * r.y + z * r.z;
	}
	float Len() const
	{
		return std::sqrt(x*x + y*y + z*z);
	}
};

struct Matrix4
{
	float m[4][4];
	Matrix4()
	{
		for(int i = 0; i < 4;i++)
			for(int j = 0; j < 4; j++)
				m[i][j] = 0.0f;
	}
	void Identity()
	{
		/* identity matrix
		[ 1 0 0 0 ]
		[ 0 1 0 0 ]
		[ 0 0 1 0 ]
		[ 0 0 0	1 ]
		*/
		for(int i = 0; i < 4;i++)
			for(int j = 0; j < 4; j++)
			{
				if(j == i) //diagwnios
					m[i][j] = 1.0f;
				else
					m[i][j] = 0.0f;
			}
	}

	Vector3 TransformVec3(const Vector3& v) const
	{
		Vector3 res;
		float n = m[0][3]*v.x + m[1][3] * v.y + m[2][3] * v.z + m[3][3];
		if(n)
		{
			res.x = (m[0][0]*v.x + m[1][0]*v.y + m[2][0]*v.z + m[3][0]) / n;
			res.y = (m[0][1]*v.x + m[1][1]*v.y + m[2][1]*v.z + m[3][1]) / n;
			res.z = (m[0][2]*v.x + m[1][2]*v.y + m[2][2]*v.z + m[3][2]) / n;
		}
		else
			res.x = res.y = res.z = 0.0f;
		
		return res;
	}
	//3d left handed!!!!!!
	void RotateX(float r)
	{
		/*
		     [ 1,      0,     0, 0]
		Rx = [ 0, cos(r),sin(r), 0]
			 [ 0,-sin(r),cos(r), 0]
			 [ 0,      0,     0, 1]
		*/
		this->Identity();
		m[1][1] = std::cos(r);
		m[1][2] = std::sin(r);
		m[2][1] = -std::sin(r);
		m[2][2] = std::cos(r);
	}
	void RotateY(float r)
	{
		/*
		     [cos(r), 0,-sin(r), 0]
		Ry = [   0,   1,   0,    0]
			 [sin(r), 0, cos(r), 0]
			 [   0,   0,   0,    1]
		*/
		this->Identity();
		m[0][0] = std::cos(r);
		m[0][2] = -std::sin(r);
		m[2][0] = std::sin(r);
		m[2][2] = std::cos(r);
	}
	void RotateZ(float r)
	{
		/*
		     [ cos(r),sin(r), 0, 0]
		Rz = [-sin(r),cos(r), 0, 0]
			 [      0,     0, 1, 0]
			 [      0,     0, 0, 1]
		*/
		this->Identity();
		m[0][0] = std::cos(r);
		m[0][1] = std::sin(r);
		m[1][0] = -std::sin(r);
		m[1][1] = std::cos(r);
	}
	void Scaling(float x,float y,float z)
	{
		this->Identity();
		m[0][0] = x;
		m[1][1] = y;
		m[2][2] = z;
	}
	void Translation(float x, float y, float z)
	{
		this->Identity();
		m[0][3] = x;
		m[1][3] = y;
		m[2][3] = z;
	}
	void ProjectionPerspectiveLH(float nearp, float farp, float aspect,float fovy)
	{
		/*http://msdn.microsoft.com/en-us/library/bb205350(VS.85).aspx
			xScale     0          0               0
			0        yScale       0               0
			0          0       zf/(zf-zn)         1
			0          0       -zn*zf/(zf-zn)     0
			where:
			yScale = cot(fovY/2)

			xScale = yScale / aspect ratio
			*/
		float yScale = 1.0f / std::tan(fovy / 2.0f);
		float xScale = yScale / aspect;
	

		m[0][0] = xScale;
		m[1][1] = yScale;
		m[2][2] = farp / (farp-nearp);
		m[2][3] = 1.0f;
		m[3][2] = -(nearp*farp)/(farp-nearp); 
	}
	void LookAtLH(const Vector3& eye,const Vector3& at, const Vector3& up)
	{
		/*http://msdn.microsoft.com/en-us/library/windows/desktop/bb205342(v=vs.85).aspx
		
		zaxis = normal(At - Eye)
		xaxis = normal(cross(Up, zaxis))
		yaxis = cross(zaxis, xaxis)
    
		 xaxis.x           yaxis.x           zaxis.x          0
		 xaxis.y           yaxis.y           zaxis.y          0
		 xaxis.z           yaxis.z           zaxis.z          0
		-dot(xaxis, eye)  -dot(yaxis, eye)  -dot(zaxis, eye)  1
		*/
		this->Identity();
		Vector3 z = at-eye;
		Vector3 x = up.Cross(z.Normalize());
		Vector3 y = z.Cross(x);

		m[0][0] = x.x;	m[0][1] = y.x;	m[0][2] = z.x;
		m[1][0] = x.y;	m[1][1] = y.y;	m[1][2] = z.y;
		m[2][0] = x.z;	m[2][1] = y.z;	m[2][2] = z.z;
		
		m[3][0] = -x.Dot(eye);
		m[3][1] = -y.Dot(eye);
		m[3][2] = -z.Dot(eye);

	}
	void Viewport(int height, int widht)
	{
		/*
		http://msdn.microsoft.com/en-us/library/windows/desktop/bb206341(v=vs.85).aspx
		[ x 0 0 0]
		[ 0 y 0 0]
		[ 0 0 z 0]
		[ i j m 1]
		x = widht / 2
		y = -(height / 2)
		z = maxDepth - minDepth (z)
		i = X + widht / 2 (X = viewport corners)
		j = Y + height / 2 (Y = --//--)
		m = minZ
		*/
		
		this->Identity();
		m[0][0] = float(widht) / 2.0f;
		m[1][1] = -float(height) / 2.0f;
		m[2][2] = 1.0f; // max 1 min 0
		m[3][0] = float(widht) / 2.0f;
		m[3][1] = float(height) / 2.0f;
		m[3][2] = 0.0f; 
	}

	//operators
	float& operator() (int i,int j)
	{
		return m[i][j];
	}
	float operator() (int i,int j) const
	{
		return m[i][j];
	}
	Matrix4 operator* (const Matrix4& r)
	{
		/* matrix mul
		[a b]	[1 2] = [ a1 + b3   a2 + b4 ]
		[c d] * [3 4]	[ c1 + d3	d2 + d4 ]
		*/
		Matrix4 res;
		for(int i = 0; i < 4; i++)//row
			for(int j = 0; j < 4; j++)//col
				for(int c = 0; c < 4; c++)//cross
					res(i,j) += m[i][c] * r(c,j);
		return res;
	}
	Matrix4& operator*= (const Matrix4& r)
	{
		*this = *this * r;
		return *this;
	}
};




#if USEWIN
//win interface
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam, LPARAM lParam);
void RenderTriangleTopology(HDC hdc, const std::vector<Vector3>& vertices,const std::vector<unsigned>& indices, const Matrix4& wvp);
#endif
void RenderTriangleTopology(Console2D& console,const std::vector<Vector3>& vertices,const std::vector<unsigned>& indices, const Matrix4& wvp);
void InitBuffers();

std::vector<Vector3> g_verticesBuffer;
std::vector<unsigned> g_indicesBuffer;
int height	= 600;
int width	= 600;



int main(int argc, char **argv)
{
	
	Console2D console(50,70,' ');
	InitBuffers();


#if USEWIN
	HWND hWnd;
	MSG	msg;
	WNDCLASSEX cl		= { 0 };
	cl.cbSize			= sizeof(cl);
	cl.hCursor			= LoadCursor(0,IDC_ARROW);
	cl.lpszClassName	= L"OutputWindow";
	cl.lpfnWndProc		= WndProc;
	RegisterClassEx(&cl);
	hWnd = CreateWindow(L"OutputWindow",L"Output",WS_VISIBLE,CW_USEDEFAULT,0,width,height,0,0,0,&console);
	ShowWindow(hWnd, SW_SHOW);
	while(GetMessage(&msg,0,0,0) > 0)
		DispatchMessage(&msg);
#else
	Matrix4 view,viewport,projecting,rotation,wvp;

	view.LookAtLH(Vector3(0.0f,0.0f,-4.0f),Vector3(0.0f,0.0f,0.0f),Vector3(0.0f,1.0f,0.0f));
	projecting.ProjectionPerspectiveLH(1.0f,1000.0f,console.Width()/console.Height(),3.14f/4.0f);
	viewport.Viewport(console.Height(),console.Width());

	for(float pi = 0.0f; pi <3.14f * 10; pi+= 0.1f)
	{
		
		rotation.RotateY(pi);
		wvp = rotation * view * projecting * viewport;
		RenderTriangleTopology(console,g_verticesBuffer,g_indicesBuffer,wvp);
		Sleep(100);

	}

#endif
	return 0;
}

void RenderTriangleTopology(Console2D& console,const std::vector<Vector3>& vertices,const std::vector<unsigned>& indices, const Matrix4& wvp)
{
	if(indices.size() % 3)
		throw std::exception("Mono set twn triwn");
	console.Clear();
	for(std::vector<unsigned>::const_iterator idx = indices.begin(); idx != indices.end(); ++idx)
	{
		Vector3 p1,p2,p3;
		p1 = wvp.TransformVec3(vertices[ *idx ]);
		idx++;
		p2 = wvp.TransformVec3(vertices[ *idx ]);
		idx++;
		p3 = wvp.TransformVec3(vertices[ *idx ]);
		
		console.Line(p1.x,p1.y,p2.x,p2.y);
		console.Line(p1.x,p1.y,p3.x,p3.y);
		console.Line(p3.x,p3.y,p2.x,p2.y);
	}
	console.Present();
}
void InitBuffers()
{
	//enas kybos
	
	//6 shmeia
	g_verticesBuffer.push_back(Vector3(-1.0f,-1.0f,-1.0f));
	g_verticesBuffer.push_back(Vector3(-1.0f,+1.0f,-1.0f));
	g_verticesBuffer.push_back(Vector3(+1.0f,+1.0f,-1.0f));
	g_verticesBuffer.push_back(Vector3(+1.0f,-1.0f,-1.0f));
	g_verticesBuffer.push_back(Vector3(-1.0f,-1.0f,+1.0f));
	g_verticesBuffer.push_back(Vector3(-1.0f,+1.0f,+1.0f));
	g_verticesBuffer.push_back(Vector3(+1.0f,+1.0f,+1.0f));
	g_verticesBuffer.push_back(Vector3(+1.0f,-1.0f,+1.0f));

	//syndesh shmeiwn

	//mpros
	g_indicesBuffer.push_back(0);
	g_indicesBuffer.push_back(1);
	g_indicesBuffer.push_back(2);
	g_indicesBuffer.push_back(0);
	g_indicesBuffer.push_back(2);
	g_indicesBuffer.push_back(3);

	//kwlos
	g_indicesBuffer.push_back(4);
	g_indicesBuffer.push_back(6);
	g_indicesBuffer.push_back(5);
	g_indicesBuffer.push_back(4);
	g_indicesBuffer.push_back(7);
	g_indicesBuffer.push_back(6);

	//Tsipras
	g_indicesBuffer.push_back(4);
	g_indicesBuffer.push_back(5);
	g_indicesBuffer.push_back(1);
	g_indicesBuffer.push_back(4);
	g_indicesBuffer.push_back(1);
	g_indicesBuffer.push_back(0);

	//kasidiaris
	g_indicesBuffer.push_back(3);
	g_indicesBuffer.push_back(2);
	g_indicesBuffer.push_back(6);
	g_indicesBuffer.push_back(3);
	g_indicesBuffer.push_back(6);
	g_indicesBuffer.push_back(7);

	//patos
	g_indicesBuffer.push_back(4);
	g_indicesBuffer.push_back(0);
	g_indicesBuffer.push_back(3);
	g_indicesBuffer.push_back(4);
	g_indicesBuffer.push_back(3);
	g_indicesBuffer.push_back(7);
}

#if USEWIN
void RenderTriangleTopology(HDC hdc, const std::vector<Vector3>& vertices,const std::vector<unsigned>& indices, const Matrix4& wvp)
{
	if(indices.size() % 3)
		throw std::exception("Mono set twn triwn");
	for(std::vector<unsigned>::const_iterator idx = indices.begin(); idx != indices.end(); ++idx)
	{
		Vector3 p1,p2,p3;
		p1 = wvp.TransformVec3(vertices[ *idx ]);
		idx++;
		p2 = wvp.TransformVec3(vertices[ *idx ]);
		idx++;
		p3 = wvp.TransformVec3(vertices[ *idx ]);
		
		MoveToEx(hdc,p1.x,p1.y,0);
		LineTo(hdc,p1.x,p1.y);
		LineTo(hdc,p2.x,p2.y);
		LineTo(hdc,p3.x,p3.y);
		LineTo(hdc,p1.x,p1.y);
	}
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	HGDIOBJ hOld,hPen;
	static Console2D *console;
	Matrix4 view,proj,projConsole,rot,scaling,viewport,viewportConsole,worldTransformationViewProjection,wvpConsole;
	static float pi = 0.0f;
	switch(msg)
	{
	case WM_TIMER:
		if(pi > 3.14f)
			pi = 0.0f;
		pi+= 0.01f;
		InvalidateRect(hWnd,0,1);
		break;
	case WM_CREATE:
		console = (Console2D*)((CREATESTRUCT*)lParam)->lpCreateParams;
		
		SetTimer(hWnd,0,300,0);
		break;
	case WM_PAINT:
		BeginPaint(hWnd,&ps);
		//clear bk
		FillRect(ps.hdc,& ps.rcPaint,(HBRUSH) (COLOR_WINDOW + 1));
		hPen = CreatePen(PS_SOLID,1,RGB(0,200,0));
		hOld = SelectObject(ps.hdc,hPen);
		//
		//camera
		view.LookAtLH(
			Vector3(0.0f,0.0f,-3.0f),// thesh
			Vector3(0.0f,0.0f,0.0f),// stoxos
			Vector3(0.0f,1.0f,0.0f)// y einai to panw
			);

		// perspective: dinei thn esthish toy xwroy (meros tis cameras kai ayto)
		// projection: provaloyme to 3d kosmo se ena "toixo" na to pw... 
		proj.ProjectionPerspectiveLH(1.0f,1000.0f,width/height,3.14f/4.0f);

		//gia thn console
		projConsole.ProjectionPerspectiveLH(1.0f,1000.0f,console->Width()/console->Height(),3.14f/4.0f);

		//viewport to teleiko soloupoma gia na xwresei sto output tou window
		viewport.Viewport(height,width);
		//allh mia gia thn console
		viewportConsole.Viewport(console->Height(),console->Width());
		
		//rotation
		rot.RotateY(pi);

		//scaling 
		scaling.Scaling(0.7f,0.7f,0.7f);
		//gia to window
		worldTransformationViewProjection = rot * scaling * view * proj * viewport;

		//gia th console
		wvpConsole = rot * scaling * view * projConsole * viewportConsole;

		RenderTriangleTopology(ps.hdc,g_verticesBuffer,g_indicesBuffer,worldTransformationViewProjection);
		RenderTriangleTopology(*console,g_verticesBuffer,g_indicesBuffer,wvpConsole);
		
		//
		DeleteObject(SelectObject(ps.hdc,hOld));
		EndPaint(hWnd,&ps);
		break;
	default:
		return DefWindowProc(hWnd,msg,wParam,lParam);
	}
	return 0;
}

#endif

 

 

  • Like 4
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...