Προς το περιεχόμενο
  • 0
Συνδεθείτε  
παπι

[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

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

0 απαντήσεις σε αυτή την ερώτηση

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

Δεν υπάρχουν απαντήσεις σε αυτήν την ερώτηση ακόμη

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

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

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

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

Εγγραφείτε για έναν νέο λογαριασμό

Σύνδεση

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

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

Χρήσιμες πληροφορίες

Με την περιήγησή σας στο insomnia.gr, αποδέχεστε τη χρήση cookies που ενισχύουν σημαντικά την εμπειρία χρήσης.