Editor camera

    For Demo programm I need to add better camera. I want to move it using RMB, and rotate holding Alt

    Add new data into slCamera

    
    	// for Editor camera
    	enum class Direction : uint32_t
    	{
    		North,
    		NorthEast,
    		East,
    		SouthEast,
    		South,
    		SouthWest,
    		West,
    		NorthWest
    	};
    	enum CameraEditorType
    	{
    		Perspective,
    		Bottom, Left, Right, Back, Front, Top
    	};
    	slVec3f m_rotationPlatform;
    	slVec4 m_positionPlatform; // w = height, zoom, mouse wheel value
    	slVec4 m_positionCamera; // in world
    	Direction m_direction;
    	CameraEditorType m_editorCameraType = CameraEditorType::Perspective;
    	bool m_forceOrtho = false;
    	void EditorUpdate();
    	void EditorPanMove(slVec2f* mouseDelta, float timeDelta);
    	void EditorRotate(slVec2f* mouseDelta, float timeDelta);
    	void EditorZoom(int wheelDelta);
    	void EditorChangeFOV(slVec2f* mouseDelta, float timeDelta);
    	void EditorRotateZ(slVec2f* mouseDelta, float timeDelta);
    	void EditorReset();
    

    Move camera using m_positionPlatform. w component will move camera forward or backward so it will be zoom for camera

    
    void slCamera::_afterUpdate()
    {
    	slMath::mul(m_projectionMatrix, m_viewMatrix, m_viewProjectionMatrix);
    
    	m_viewMatrixInvert = m_viewMatrix;
    	slMath::invert(m_viewMatrixInvert);
    
    	auto pi = m_projectionMatrix;
    	slMath::invert(pi);
    	slMath::mul(m_viewMatrixInvert, pi, m_viewProjectionInvertMatrix);
    
    	m_frust.CalculateFrustum(m_projectionMatrix, m_viewMatrix);
    }
    void slCamera::EditorUpdate() {
    	if ((m_editorCameraType != CameraEditorType::Perspective) || m_forceOrtho)
    	{
    		float zoom = (float)m_positionPlatform.w;
    		slMath::orthoRH(
    			m_projectionMatrix,
    			zoom * m_aspect,
    			zoom,
    			-m_far,
    			m_far);
    
    	}
    	else
    	{
    		slMath::perspectiveRH(m_projectionMatrix, m_fov, m_aspect, m_near, m_far);
    	}
    
    	m_projectionMatrix.m_data[0].x = -m_projectionMatrix.m_data[0].x;
    
    	slMat4 MX(slQuaternion(m_rotationPlatform.x, 0.f, 0.f));
    	slMat4 MY(slQuaternion(0.f, m_rotationPlatform.y, 0.f));
    	//Mat4 MZ(Quat(0.f, 0.f, m_rotationPlatform.z));
    
    	m_positionCamera = slVec4(0.f, m_positionPlatform.w, 0.f, 0.f);
    	
    	slMath::mul((MY * MX), slVec4(m_positionCamera), m_positionCamera);
    
    	m_positionCamera += slVec4(m_positionPlatform.x, m_positionPlatform.y, m_positionPlatform.z, 0.f);
    
    	slMat4 T;
    	T.m_data[3].x = -m_positionCamera.x;
    	T.m_data[3].y = -m_positionCamera.y;
    	T.m_data[3].z = -m_positionCamera.z;
    	T.m_data[3].w = 1.f;
    
    	slMat4 P(slQuaternion(slVec4(-m_rotationPlatform.x + slMath::DegToRad(-90.f), 0.f, 0.f, 1.f)));
    	slMat4 Y(slQuaternion(slVec4(0.f, -m_rotationPlatform.y + slMath::DegToRad(0.f), 0.f, 1.f)));
    	slMat4 R(slQuaternion(slVec4(0.f, 0.f, m_rotationPlatform.z, 1.f)));
    
    	m_viewMatrix = (R * (P * Y)) * T;
    	m_viewProjectionMatrix = m_projectionMatrix * m_viewMatrix;
    
    	m_viewMatrixInvert = m_viewMatrix; m_viewMatrixInvert.invert();
    	auto pi = m_projectionMatrix; pi.invert();
    	m_viewProjectionInvertMatrix = m_viewMatrixInvert * pi;
    	m_frust.CalculateFrustum(m_projectionMatrix, m_viewMatrix);
    
    	m_direction = Direction::NorthEast;
    
    	if (m_rotationPlatform.y >= 2.7488936 && m_rotationPlatform.y <= 3.5342917)
    		m_direction = Direction::North;
    	else if (m_rotationPlatform.y >= 5.8904862 || m_rotationPlatform.y <= 0.3926991)
    		m_direction = Direction::South;
    	else if (m_rotationPlatform.y >= 1.1780972 && m_rotationPlatform.y <= 1.9634954)
    		m_direction = Direction::West;
    	else if (m_rotationPlatform.y >= 4.3196899 && m_rotationPlatform.y <= 5.1050881)
    		m_direction = Direction::East;
    	else if (m_rotationPlatform.y >= 1.9634954 && m_rotationPlatform.y <= 2.7488936)
    		m_direction = Direction::NorthWest;
    	else if (m_rotationPlatform.y >= 0.3926991 && m_rotationPlatform.y <= 1.1780972)
    		m_direction = Direction::SouthWest;
    	else if (m_rotationPlatform.y >= 5.1050881 && m_rotationPlatform.y <= 5.8904862)
    		m_direction = Direction::SouthEast;
    	_afterUpdate();
    }
    void slCamera::EditorPanMove(slVec2f* mouseDelta, float timeDelta)
    {
    	float speed = 10.f * ((float)m_positionPlatform.w * 0.01f);
    
    	slVec4 vec(
    		speed * mouseDelta->x * timeDelta,
    		0.f,
    		speed * -mouseDelta->y * timeDelta,
    		0.f);
    	slMat4 MX(slQuaternion(m_rotationPlatform.x, 0.f, 0.f));
    	slMat4 MY(slQuaternion(0.f, m_rotationPlatform.y, 0.f));
    	//Mat4 MZ(Quat(0.f, 0.f, m_rotationPlatform.z));
    	slMath::mul(MY * MX, slVec4(vec), vec);
    	m_positionPlatform += vec;
    }
    
    void slCamera::EditorRotate(slVec2f* mouseDelta, float timeDelta)
    {
    	const float speed = 0.69f * timeDelta;
    	m_rotationPlatform.x += mouseDelta->y * speed;
    	m_rotationPlatform.y += -mouseDelta->x * speed;
    
    	if (m_rotationPlatform.y < 0.f) m_rotationPlatform.y = m_rotationPlatform.y + (float)PIPI;
    
    	if (m_rotationPlatform.x > PIPI) m_rotationPlatform.x = 0.f;
    	if (m_rotationPlatform.y > PIPI) m_rotationPlatform.y = 0.f;
    	//if (m_rotationPlatform.x < -math::PIPI) m_rotationPlatform.x = 0.f;
    	//if (m_rotationPlatform.y < -math::PIPI) m_rotationPlatform.y = 0.f;
    
    
    	//if (m_type != miViewportCameraType::Perspective)
    	//	m_viewport->SetViewportName(L"Orthogonal");
    
    	//Update();
    }
    
    void slCamera::EditorZoom(int wheelDelta)
    {
    	float mult = 1.f;
    	//if (g_app->m_inputContext->m_kbm == miKeyboardModifier::Shift)
    		//mult = 3.f;
    
    	if (wheelDelta > 0)
    		m_positionPlatform.w *= 0.9f * (1.f / mult);
    	else
    		m_positionPlatform.w *= 1.1f * mult;
    
    	if (m_positionPlatform.w < 0.01f)
    		m_positionPlatform.w = 0.01f;
    
    	//Update();
    }
    
    void slCamera::EditorChangeFOV(slVec2f* mouseDelta, float timeDelta)
    {
    	m_fov += mouseDelta->x * timeDelta;
    	if (m_fov < 0.01f)
    		m_fov = 0.01f;
    	if (m_fov > PI)
    		m_fov = PI;
    }
    
    void slCamera::EditorRotateZ(slVec2f* mouseDelta, float timeDelta)
    {
    	m_rotationPlatform.z += mouseDelta->x * timeDelta;
    }
    
    void slCamera::EditorReset()
    {
    	m_near = 0.01f;
    	m_far = 2500.f;
    	m_fov = 0.683264f;
    	m_aspect = 800.f / 600.f;
    	m_positionPlatform = slVec4(0.f, 0.f, 0.f, 15.f);
    	switch (m_editorCameraType)
    	{
    	case CameraEditorType::Perspective:
    		m_rotationPlatform = slVec3f(slMath::DegToRad(-45.f), 0.f, 0.f);
    		break;
    	case CameraEditorType::Bottom:
    		m_rotationPlatform = slVec3f(slMath::DegToRad(-180.f), 0.f, 0.f);
    		break;
    	case CameraEditorType::Left:
    		m_rotationPlatform = slVec3f(slMath::DegToRad(-90.f), slMath::DegToRad(-90.f), 0.f);
    		break;
    	case CameraEditorType::Right:
    		m_rotationPlatform = slVec3f(slMath::DegToRad(-90.f), slMath::DegToRad(90.f), 0.f);
    		break;
    	case CameraEditorType::Back:
    		m_rotationPlatform = slVec3f(slMath::DegToRad(-90.f), slMath::DegToRad(180.f), 0.f);
    		break;
    	case CameraEditorType::Front:
    		m_rotationPlatform = slVec3f(slMath::DegToRad(-90.f), slMath::DegToRad(0.f), 0.f);
    		break;
    	case CameraEditorType::Top:
    		m_rotationPlatform = slVec3f();
    		break;
    	}
    
    	slVec2f rp;
    	EditorRotate(&rp, 1.f);
    }
    
    

    Text in 3D space

    I very need to draw text in 3d space. I can use sprite code for this

    
    void slGSD3D11::DrawText3D(const slVec4& _position, const char32_t* text, size_t textSz, slGUIFont* font, const slColor& c,
    	float sizeMultipler)
    {
    	SL_ASSERT_ST(text);
    	SL_ASSERT_ST(font);
    	SL_ASSERT_ST(textSz);
    	SL_ASSERT_ST(slFramework::GetMatrix(slMatrixType::ViewInvert));
    	//SL_ASSERT_ST(slFramework::GetMatrix(slMatrixType::World));
    	SL_ASSERT_ST(slFramework::GetMatrix(slMatrixType::View));
    	SL_ASSERT_ST(slFramework::GetMatrix(slMatrixType::Projection));
    
    	slVec2f textSzInPixels = slFramework::GetTextSize(text, font);
    	
    	slVec4 position;
    	position.x += (textSzInPixels.x * 0.5f)* sizeMultipler;
    	
    	auto oldW = slFramework::GetMatrix(slMatrixType::World);
    
    	static slMat4 W;
    	slFramework::SetMatrix(slMatrixType::World, &W);
    	W.m_data[3].set(_position.x, _position.y, _position.z, 1.f);
    
    	SetShader(slShaderType::Sprite, 0);
    
    	for (uint32_t i = 0; i < textSz; ++i)
    	{
    		slGUIFontGlyph* g = font->GetGlyphMap()[text[i]];
    
    		slVec4 rct;
    		rct.x = position.x - ((float)g->m_width * sizeMultipler);
    		rct.y = position.y;
    
    		rct.z = position.x;
    		rct.w = rct.y + ((float)g->m_height * sizeMultipler);
    
    		_drawSprite(c, rct, g->m_UV, 0.5f, dynamic_cast<slGSD3D11Texture*>(font->GetTexture(g->m_textureSlot)));
    
    		position.x -= ((float)g->m_width + g->m_overhang + g->m_underhang + font->m_characterSpacing) * sizeMultipler;
    
    		switch (text[i])
    		{
    		case U' ':
    			position.x -= font->m_spaceSize;
    			break;
    		case U'\t':
    			position.x -= font->m_tabSize;
    			break;
    		case U'\n':
    			position.y += font->GetMaxSize().y;
    			position.x = _position.x;
    			break;
    		}
    	}
    	slFramework::SetMatrix(slMatrixType::World, oldW);
    }
    

    Before using need to set matrices like when you draw sprite.

    I put common things for drawing a sprite into _drawSprite method.

    Mesh generation

    And last. For frustum culling I want to visualize bounding volume. Bounding volume is not only AABB but also sphere.

    Box, cube

    I am not sure about texture coordinates.

    
    void slPolygonMesh::AddCube(float size, const slMat4& m)
    {
    	SL_ASSERT_ST(size != 0.f);
    
    	float halfSize = size * 0.5f;
    
    	slAabb aabb;
    	aabb.m_min.set(-halfSize);
    	aabb.m_max.set(halfSize);
    	
    	AddBox(aabb, m);
    }
    
    
    /*
    * x - max
    * n - min
    
      nxx+______________+ xxx
    	 |\             \
    	 | \            .\
    	 |  \           . \
    	 |   \  nxn     .  \
    	 |    \+____________\+ xxn
    	 |     |        .    |
      nnx+.....|........+xnx |
    	  \    |         .   |
    	   \   |          .  |
    	    \  |           . |
    		 \ |            .|
    	  nnn \+_____________+ xnn
    */  
    
    void slPolygonMesh::AddBox(const slAabb& box, const slMat4& m)
    {
    	slPolygonCreator pc;
    	// maybe UV is not correct...
    	// top
    	pc.SetPosition(slVec3f((float)box.m_min.x, (float)box.m_max.y, (float)box.m_max.z));
    	pc.SetUV(slVec2f(0.f, 0.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_max.x, (float)box.m_max.y, (float)box.m_max.z));
    	pc.SetUV(slVec2f(1.f, 0.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_max.x, (float)box.m_max.y, (float)box.m_min.z));
    	pc.SetUV(slVec2f(1.f, 1.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_min.x, (float)box.m_max.y, (float)box.m_min.z));
    	pc.SetUV(slVec2f(0.f, 1.f));
    	pc.AddVertex();
    	pc.Mul(m);
    	AddPolygon(&pc, true);
    
    	// bottom
    	pc.Clear();
    	pc.SetPosition(slVec3f((float)box.m_min.x, (float)box.m_min.y, (float)box.m_min.z));
    	pc.SetUV(slVec2f(0.f, 0.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_max.x, (float)box.m_min.y, (float)box.m_min.z));
    	pc.SetUV(slVec2f(1.f, 0.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_max.x, (float)box.m_min.y, (float)box.m_max.z));
    	pc.SetUV(slVec2f(1.f, 1.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_min.x, (float)box.m_min.y, (float)box.m_max.z));
    	pc.SetUV(slVec2f(0.f, 1.f));
    	pc.AddVertex();
    	pc.Mul(m);
    	AddPolygon(&pc, true);
    
    	// left
    	pc.Clear();
    	pc.SetPosition(slVec3f((float)box.m_min.x, (float)box.m_max.y, (float)box.m_max.z));
    	pc.SetUV(slVec2f(0.f, 0.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_min.x, (float)box.m_max.y, (float)box.m_min.z));
    	pc.SetUV(slVec2f(1.f, 0.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_min.x, (float)box.m_min.y, (float)box.m_min.z));
    	pc.SetUV(slVec2f(1.f, 1.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_min.x, (float)box.m_min.y, (float)box.m_max.z));
    	pc.SetUV(slVec2f(0.f, 1.f));
    	pc.AddVertex();
    	pc.Mul(m);
    	AddPolygon(&pc, true);
    
    	// right
    	pc.Clear();
    	pc.SetPosition(slVec3f((float)box.m_max.x, (float)box.m_max.y, (float)box.m_max.z));
    	pc.SetUV(slVec2f(0.f, 0.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_max.x, (float)box.m_min.y, (float)box.m_max.z));
    	pc.SetUV(slVec2f(1.f, 0.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_max.x, (float)box.m_min.y, (float)box.m_min.z));
    	pc.SetUV(slVec2f(1.f, 1.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_max.x, (float)box.m_max.y, (float)box.m_min.z));
    	pc.SetUV(slVec2f(0.f, 1.f));
    	pc.AddVertex();
    	pc.Mul(m);
    	AddPolygon(&pc, true);
    
    	// back
    	pc.Clear();
    	pc.SetPosition(slVec3f((float)box.m_min.x, (float)box.m_max.y, (float)box.m_min.z));
    	pc.SetUV(slVec2f(0.f, 0.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_max.x, (float)box.m_max.y, (float)box.m_min.z));
    	pc.SetUV(slVec2f(1.f, 0.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_max.x, (float)box.m_min.y, (float)box.m_min.z));
    	pc.SetUV(slVec2f(1.f, 1.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_min.x, (float)box.m_min.y, (float)box.m_min.z));
    	pc.SetUV(slVec2f(0.f, 1.f));
    	pc.AddVertex();
    	pc.Mul(m);
    	AddPolygon(&pc, true);
    
    	// front
    	pc.Clear();
    	pc.SetPosition(slVec3f((float)box.m_min.x, (float)box.m_max.y, (float)box.m_max.z));
    	pc.SetUV(slVec2f(0.f, 0.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_min.x, (float)box.m_min.y, (float)box.m_max.z));
    	pc.SetUV(slVec2f(1.f, 0.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_max.x, (float)box.m_min.y, (float)box.m_max.z));
    	pc.SetUV(slVec2f(1.f, 1.f));
    	pc.AddVertex();
    	pc.SetPosition(slVec3f((float)box.m_max.x, (float)box.m_max.y, (float)box.m_max.z));
    	pc.SetUV(slVec2f(0.f, 1.f));
    	pc.AddVertex();
    	pc.Mul(m);
    	AddPolygon(&pc, true);
    }
    

    Sphere

    Generate 3D sphere. Segments from 3 to 30. I thought it hard, but actually easy. Generate points in 2D, only half circle. Then use this points for creating poligons. Create 2 rotation matrices for current latitude and for next latitude. Create points, for current latitude(red) and for next latitude (green), use them for creating polygon.

    
    void slPolygonMesh::AddSphere(float radius, uint32_t segments, const slMat4& m)
    {
    	if (radius == 0.f) radius = 1.f;
    	if (radius < 0.f) radius = 1.f;
    
    	if (segments < 3)
    		segments = 3;
    	if (segments > 30)
    		segments = 30;
    	
    	// 1. Generate points in 2D.
    	//    Generate from 90 to 270 degrees
    	//    2 points must be in 90 and in 270 degrees
    	slArray<slVec3> points;
    	float angle = 90.f;
    	float angleStep = 180.f / (segments-1);
    	for (uint32_t i = 0; i < segments; ++i)
    	{
    		if (i == segments - 1)
    			angle = 270.f;
    
    		auto sn = ::sin(slMath::DegToRad(angle));
    		auto cs = ::cos(slMath::DegToRad(angle));
    	//	printf("A[%f]: %f %f\n", angle, sn, cs);
    		points.push_back(slVec3((real_t)cs, (real_t)sn, 0.0));
    
    		angle += angleStep;
    	}
    
    	// 2. Create polygons. Take points, rotate them, use them to build new polygon.
    	/*
    	*                    +0
    	*                  / |       
    	*                /   |       
    	*              /     |       
    	*            /      /        
    	*          1+  -  - +1rotated
    	*           |       |        
    	*           |       |        
    	*           |       |
    	*           |       |
    	*          2+  -  - +2rotated
    	*            \      \
    	*              \     |
    	*                \   |
    	*                  \ |
    	*                   3+
    	*   Top and bottom polygons are triangles
    	*/
    
    	angle = 0.f;
    	angleStep = 360.f / (segments);
    	float nextAngle = angleStep;
    	slVec2f UV;
    	float UVstep = 1.f / (segments-1);
    	for (uint32_t i1 = 0; i1 < segments; ++i1)
    	{
    		slMat4 M, Mn;
    		M.set_rotation(slQuaternion(0.f, slMath::DegToRad(angle), 0.f));
    		Mn.set_rotation(slQuaternion(0.f, slMath::DegToRad(nextAngle), 0.f));
    
    		for (uint32_t i2 = 0; i2 < segments - 1; ++i2)
    		{
    			// top triangle
    			if (i2 == 0)
    			{
    				slVec3 v0 = points[i2];
    				slVec3 v1 = points[i2 + 1];
    				slVec3 v2 = v1;
    
    				slMath::mul(M, points[i2], v0);
    				slMath::mul(M, points[i2 + 1], v1);
    				slMath::mul(Mn, points[i2 + 1], v2);
    
    				slPolygonCreator pc;
    				pc.SetPosition(slVec3f((float)v1.x, (float)v1.y, (float)v1.z));
    				pc.SetUV(slVec2f(UV.x, UV.y + UVstep));
    				pc.AddVertex();
    				pc.SetPosition(slVec3f((float)v0.x, (float)v0.y, (float)v0.z));
    				pc.SetUV(slVec2f(UV.x + (UVstep * 0.5f), UV.y));
    				pc.AddVertex();
    				pc.SetPosition(slVec3f((float)v2.x, (float)v2.y, (float)v2.z));
    				pc.SetUV(slVec2f(UV.x + UVstep, UV.y + UVstep));
    				pc.AddVertex();
    				pc.Mul(m);
    				AddPolygon(&pc, true);
    			}
    			else if (i2 == segments - 2) // bottom
    			{
    				slVec3 v0 = points[i2];
    				slVec3 v1 = points[i2 + 1];
    				slVec3 v2 = points[i2];
    
    				slMath::mul(M, points[i2], v0);
    				slMath::mul(M, points[i2 + 1], v1);
    				slMath::mul(Mn, points[i2], v2);
    				
    				slPolygonCreator pc;
    				pc.SetPosition(slVec3f((float)v1.x, (float)v1.y, (float)v1.z));
    				pc.SetUV(slVec2f(UV.x + (UVstep * 0.5f), UV.y + UVstep));
    				pc.AddVertex();
    				pc.SetPosition(slVec3f((float)v0.x, (float)v0.y, (float)v0.z));
    				pc.SetUV(slVec2f(UV.x, UV.y));
    				pc.AddVertex();
    				pc.SetPosition(slVec3f((float)v2.x, (float)v2.y, (float)v2.z));
    				pc.SetUV(slVec2f(UV.x + UVstep, UV.y));
    				pc.AddVertex();
    				pc.Mul(m);
    				AddPolygon(&pc, true);
    			}
    			else
    			{
    				slVec3 v0 = points[i2];
    				slVec3 v1 = points[i2 + 1];
    				slVec3 v2 = v0;
    				slVec3 v3 = v1;
    
    				slMath::mul(M, points[i2], v0);
    				slMath::mul(M, points[i2 + 1], v1);
    				slMath::mul(Mn, points[i2], v2);
    				slMath::mul(Mn, points[i2 + 1], v3);
    
    				slPolygonCreator pc;
    				pc.SetPosition(slVec3f((float)v1.x, (float)v1.y, (float)v1.z));
    				pc.SetUV(slVec2f(UV.x, UV.y + UVstep));
    				pc.AddVertex();
    				pc.SetPosition(slVec3f((float)v0.x, (float)v0.y, (float)v0.z));
    				pc.SetUV(slVec2f(UV.x, UV.y));
    				pc.AddVertex();
    				pc.SetPosition(slVec3f((float)v2.x, (float)v2.y, (float)v2.z));
    				pc.SetUV(slVec2f(UV.x + UVstep, UV.y));
    				pc.AddVertex();
    				pc.SetPosition(slVec3f((float)v3.x, (float)v3.y, (float)v3.z));
    				pc.SetUV(slVec2f(UV.x + UVstep, UV.y + UVstep));
    				pc.AddVertex();
    				pc.Mul(m);
    				AddPolygon(&pc, true);
    			}
    
    			UV.y += UVstep;
    		}
    		
    		UV.x += UVstep;
    
    		angle += angleStep;
    		nextAngle += angleStep;
    	}
    }
    

    UV planar

    For hand created polygon need to calculate texture coordinates. First method is this. Later I will add more.

    
    void slPolygonMesh::GenerateUVPlanar(float scale)
    {
    	if (!m_first_polygon)
    		return;
    
    	slVec3f n;
    	auto cp = m_first_polygon;
    	auto lp = cp->m_left;
    	while (true)
    	{
    		n += cp->GetFaceNormalCalculateNew();
    
    		if (cp == lp)
    			break;
    		cp = cp->m_right;
    	}
    	n.normalize();
    	if (n.x == 0.f) n.x = 0.0001f;
    	if (n.y == 0.f) n.y = 0.0001f;
    	if (n.z == 0.f) n.z = 0.0001f;
    
    	slMat4 V;
    	slMat4 P;
    	slMath::lookAtRH(V, n, slVec4(), slVec4(0.f, 1.f, 0.f, 0.f));
    	slMath::orthoRH(P, 100.f, 100.f, -1000.f, 1000.f);
    	
    	slMat4 W;
    	W.m_data[0].x = scale;
    	W.m_data[1].y = scale;
    	W.m_data[2].z = scale;
    
    	slMat4 VP = P * V * W;
    
    	{
    		auto cp = m_first_polygon;
    		auto lp = cp->m_left;
    		while (true)
    		{
    			auto cv = cp->GetVertices()->m_head;
    			auto lv = cv->m_left;
    			while (true)
    			{
    				slVec4 point = cv->m_data->m_data.baseData.Position;// -center3d;
    				point.w = 1.f;
    				slMath::mul(VP, slVec4(point), point);
    
    				cv->m_data->m_data.baseData.UV.x = (float)(point.x / point.w);
    				cv->m_data->m_data.baseData.UV.y = (float)(-point.y / point.w);
    
    				//aabb2d.add(v3f(cv->m_data.m_uv.x, cv->m_data.m_uv.y, 0.f));
    
    				if (cv == lv)
    					break;
    				cv = cv->m_right;
    			}
    			if (cp == lp)
    				break;
    			cp = cp->m_right;
    		}
    	}
    }
    

    Download