【OpenGL现代游戏引擎学习笔记】【001-可视化骨骼动画关节节点】

在这里插入图片描述
老婆镇楼!白毛真是prpr!
一般现代OpenGL指的是用OpenGL3.3左右+GLM+GLAD+GLFW/SDL/etc.
矩阵操作更加直观,这里点名批评GLUT,代码简直不是人看的
在这里插入图片描述

本文改编网上glut的源码到glad-sdl/glfw
为后面操作骨骼做准备!

准备顶点数据,这里提供aPos,aNormal, indices
填充到mesh类,mesh类可以到learnopengl下载

本代码提供了box,Pyramid等类型的显示,数据由Maya建模获取,原理就是做个默认cube的内接几何体,然后放大100倍,也就是外接一个1立方米的cube,即所有设定的几何体的包围盒大小是1立方米,并且确保轴心在原点,然后通过变换矩阵去变换这个几何体进行骨骼的可视化!数据提取通过把这个模型导出fbx然后丢到Unity读取所需要mesh类顶点数据

Unity端代码:

void Start()
    {
        MeshFilter meshRenderer = GetComponent<MeshFilter>();
        var mesh = meshRenderer.sharedMesh;
        var vs= mesh.vertices;
        var ns= mesh.normals;
        var _is = mesh.GetIndices(0);
        print(_is.Length);
        print(mesh.triangles.Length);
        print(mesh.subMeshCount);

        StringBuilder sb = new System.Text.StringBuilder();
        for (int i = 0; i < mesh.vertexCount; i++)
        {
            sb.Append(vs[i].x.ToString("0.00") + ","+ vs[i].y.ToString("0.00") + ","+ vs[i].z.ToString("0.00") + ","+"\n");
        }
        print(mesh.vertexCount);
        sb.Append("------------" + "\n");
        for (int i = 0; i < mesh.vertexCount; i++)
        {
            sb.Append(ns[i].x.ToString("0.00") + "," + ns[i].y.ToString("0.00") + "," + ns[i].z.ToString("0.00") + "," + "\n");
        }
        sb.Append("------------" + "\n");
        sb.Append(string.Join(",", mesh.triangles));
        System.IO.File.WriteAllText("abc.txt",sb.ToString());
        
        
    }

ps:这里的triangles就是我们的indices

  float model_scale = 0.05f;
    const float position[24 * 3] = {
        //Pyramid
       //0.00,-0.25,-0.50,
       // 0.00,0.50,0.00,
       // 0.50,-0.25,0.00,
       // 0.50,-0.25,0.00,
       // 0.00,0.50,0.00,
       // 0.00,-0.25,0.50,
       // 0.00,-0.25,0.50,
       // 0.00,0.50,0.00,
       // -0.50,-0.25,0.00,
       // -0.50,-0.25,0.00,
       // 0.00,0.50,0.00,
       // 0.00,-0.25,-0.50,
       // 0.50,-0.25,0.00,
       // 0.00,-0.50,0.00,
       // 0.00,-0.25,-0.50,
       // 0.00,-0.25,0.50,
       // 0.00,-0.50,0.00,
       // 0.50,-0.25,0.00,
       // -0.50,-0.25,0.00,
       // 0.00,-0.50,0.00,
       // 0.00,-0.25,0.50,
       // 0.00,-0.25,-0.50,
       // 0.00,-0.50,0.00,
       // -0.50,-0.25,0.00

        //Pyramid_B
     /*   0.50,-0.50,-0.50,
        0.00,0.50,0.00,
        0.50,-0.50,0.50,
        0.50,-0.50,0.50,
        0.00,0.50,0.00,
        -0.50,-0.50,0.50,
        -0.50,-0.50,0.50,
        0.00,0.50,0.00,
        -0.50,-0.50,-0.50,
        -0.50,-0.50,-0.50,
        0.00,0.50,0.00,
        0.50,-0.50,-0.50,
        0.50,-0.50,-0.50,
        0.50,-0.50,0.50,
        -0.50,-0.50,0.50,
        -0.50,-0.50,-0.50*/

        //cube
      /*  0.50,-0.50,0.50,
        -0.50,-0.50,0.50,
        0.50,0.50,0.50,
        -0.50,0.50,0.50,
        0.50,0.50,-0.50,
        -0.50,0.50,-0.50,
        0.50,-0.50,-0.50,
        -0.50,-0.50,-0.50,
        0.50,0.50,0.50,
        -0.50,0.50,0.50,
        0.50,0.50,-0.50,
        -0.50,0.50,-0.50,
        0.50,-0.50,-0.50,
        0.50,-0.50,0.50,
        -0.50,-0.50,0.50,
        -0.50,-0.50,-0.50,
        -0.50,-0.50,0.50,
        -0.50,0.50,0.50,
        -0.50,0.50,-0.50,
        -0.50,-0.50,-0.50,
        0.50,-0.50,-0.50,
        0.50,0.50,-0.50,
        0.50,0.50,0.50,
        0.50,-0.50,0.50*/

        //cube2
        0.50,-0.50,0.50,
        0.07,0.50,0.07,
        -0.07,0.50,0.07,
        -0.50,-0.50,0.50,
        0.07,0.50,0.07,
        0.07,0.50,-0.07,
        -0.07,0.50,-0.07,
        -0.07,0.50,0.07,
        0.07,0.50,-0.07,
        0.50,-0.50,-0.50,
        -0.50,-0.50,-0.50,
        -0.07,0.50,-0.07,
        0.50,-0.50,-0.50,
        0.50,-0.50,0.50,
        -0.50,-0.50,0.50,
        -0.50,-0.50,-0.50,
        -0.50,-0.50,0.50,
        -0.07,0.50,0.07,
        -0.07,0.50,-0.07,
        -0.50,-0.50,-0.50,
        0.50,-0.50,-0.50,
        0.07,0.50,-0.07,
        0.07,0.50,0.07,
        0.50,-0.50,0.50
    };

    float normal[24 * 3] = {
        //Pyramid
       /* 0.64,0.43,-0.64,
        0.64,0.43,-0.64,
        0.64,0.43,-0.64,
        0.64,0.43,0.64,
        0.64,0.43,0.64,
        0.64,0.43,0.64,
        -0.64,0.43,0.64,
        -0.64,0.43,0.64,
        -0.64,0.43,0.64,
        -0.64,0.43,-0.64,
        -0.64,0.43,-0.64,
        -0.64,0.43,-0.64,
        0.41,-0.82,-0.41,
        0.41,-0.82,-0.41,
        0.41,-0.82,-0.41,
        0.41,-0.82,0.41,
        0.41,-0.82,0.41,
        0.41,-0.82,0.41,
        -0.41,-0.82,0.41,
        -0.41,-0.82,0.41,
        -0.41,-0.82,0.41,
        -0.41,-0.82,-0.41,
        -0.41,-0.82,-0.41,
        -0.41,-0.82,-0.41*/

        //Pyramid_B
       /* 0.89,0.45,0.00,
        0.89,0.45,0.00,
        0.89,0.45,0.00,
        0.00,0.45,0.89,
        0.00,0.45,0.89,
        0.00,0.45,0.89,
        -0.89,0.45,0.00,
        -0.89,0.45,0.00,
        -0.89,0.45,0.00,
        0.00,0.45,-0.89,
        0.00,0.45,-0.89,
        0.00,0.45,-0.89,
        0.00,-1.00,0.00,
        0.00,-1.00,0.00,
        0.00,-1.00,0.00,
        0.00,-1.00,0.00*/

        //cube
        //0.00,0.00,1.00,
        //0.00,0.00,1.00,
        //0.00,0.00,1.00,
        //0.00,0.00,1.00,
        //0.00,1.00,0.00,
        //0.00,1.00,0.00,
        //0.00,0.00,-1.00,
        //0.00,0.00,-1.00,
        //0.00,1.00,0.00,
        //0.00,1.00,0.00,
        //0.00,0.00,-1.00,
        //0.00,0.00,-1.00,
        //0.00,-1.00,0.00,
        //0.00,-1.00,0.00,
        //0.00,-1.00,0.00,
        //0.00,-1.00,0.00,
        //-1.00,0.00,0.00,
        //-1.00,0.00,0.00,
        //-1.00,0.00,0.00,
        //-1.00,0.00,0.00,
        //1.00,0.00,0.00,
        //1.00,0.00,0.00,
        //1.00,0.00,0.00,
        //1.00,0.00,0.00

        //cube2
        0.00,0.39,0.92,
        0.00,0.39,0.92,
        0.00,0.39,0.92,
        0.00,0.39,0.92,
        0.00,1.00,0.00,
        0.00,1.00,0.00,
        0.00,1.00,0.00,
        0.00,1.00,0.00,
        0.00,0.39,-0.92,
        0.00,0.39,-0.92,
        0.00,0.39,-0.92,
        0.00,0.39,-0.92,
        0.00,-1.00,0.00,
        0.00,-1.00,0.00,
        0.00,-1.00,0.00,
        0.00,-1.00,0.00,
        -0.92,0.39,0.00,
        -0.92,0.39,0.00,
        -0.92,0.39,0.00,
        -0.92,0.39,0.00,
        0.92,0.39,0.00,
        0.92,0.39,0.00,
        0.92,0.39,0.00,
        0.92,0.39,0.00
    };
    vector<Vertex>vertices;
    //vector<unsigned int> indices{ 0,2,3,0,3,1,8,4,5,8,5,9,10,6,7,10,7,11,12,13,14,12,14,15,16,17,18,16,18,19,20,21,22,20,22,23 };//cube
    vector<unsigned int> indices{ 0,1,2,0,2,3,4,5,6,4,6,7,8,9,10,8,10,11,12,13,14,12,14,15,16,17,18,16,18,19,20,21,22,20,22,23 };//cube2
    //vector<unsigned int> indices{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 };//Pyramid
    //vector<unsigned int> indices{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,12,14,15  };//Pyramid_B
    //printf("indices:%d\n", indices.size());
    vector<TextureInfo> textures;
    for (int i = 0, max_len = 24 * 3; i < max_len; i += 3)
    {
        Vertex vertex;
        vertex.Position = model_scale * glm::vec3(position[i], position[i + 1], position[i + 2]);//model_scale * glm::vec3(position[i], position[i + 1], position[i + 2]);//Scale
        vertex.Normal = glm::vec3(normal[i], normal[i + 1], normal[i + 2]);
        vertex.TexCoords = glm::vec2();
        vertex.Tangent = glm::vec3();
        vertex.Bitangent = glm::vec3();
        vertex.m_BoneIDs[0] = 0;
        vertex.m_BoneIDs[1] = 0;
        vertex.m_BoneIDs[2] = 0;
        vertex.m_BoneIDs[3] = 0;

        vertex.m_Weights[0] = 0;
        vertex.m_Weights[1] = 0;
        vertex.m_Weights[2] = 0;
        vertex.m_Weights[3] = 0;
        vertices.push_back(vertex);
    }

    for (unsigned int i = 0; i < numJoints; ++i) {
        if (pose.GetParent(i) < 0) {
            continue;
        }
        //meshs.emplace_back(vertices, indices, textures, false);
       p_mesh = new Mesh(vertices, indices, textures, false);
        meshs.push_back(Mesh(vertices, indices, textures, false));
        ps->use();
        ps->setVec3("light_direction", -1.0f, -1.0f, -1.0f);
    }

获取到关节父子节点世界坐标后,比如v1,v2,就可以用我们的变换矩阵操作了,那么核心代码是:

参数__length是关节长度,size是整体骨架大小,这里只能大致拟合,不能精确,想要相对精确需要借助模型包围盒尺寸推算__length和size

	glm::mat4 ComputeBoneMatrix(const vec3& _start, const vec3& _end, float __length=14.5f, float size= 0.37f)
	{
	    vec3 direction = (_end - _start);
		auto _length = len(direction);//计算模长
		auto _len_ = _length;

		glm::mat4 model = glm::mat4(1.0f);
		float height_adjust = 1.05f;
		model = glm::translate(model, glm::vec3((_start.x + _end.x) * size, (_start.y  + _end.y) * size + height_adjust, (_start.z  + _end.z) * size));
	
		float dir_x = direction.x, dir_y = direction.y, dir_z = direction.z;
		if (0 == _length)
		{
			dir_x = 0.0; dir_y = 0.0; dir_z = 1.0;  _length = 1.0;
		}
		dir_x /= _length;
		dir_y /= _length;
		dir_z /= _length;

		double  up_x, up_y, up_z;
		up_x = 0.0;
		up_y = 1.0;
		up_z = 0.0;

		double  side_x, side_y, side_z;
		side_x = up_y * dir_z - up_z * dir_y;
		side_y = up_z * dir_x - up_x * dir_z;
		side_z = up_x * dir_y - up_y * dir_x;

		// x軸を単位ベクトルに正規化
		_length = sqrt(side_x * side_x + side_y * side_y + side_z * side_z);
		if (_length < 0.0001) {
			side_x = 1.0; side_y = 0.0; side_z = 0.0;  _length = 1.0;
		}
		side_x /= _length;  side_y /= _length;  side_z /= _length;

		// z軸とx軸の外積からy軸の向きを計算
		up_x = dir_y * side_z - dir_z * side_y;
		up_y = dir_z * side_x - dir_x * side_z;
		up_z = dir_x * side_y - dir_y * side_x;

		glm::mat4 rot_matrx = { 
			side_x, side_y, side_z, 0.0,
			up_x,   up_y,   up_z,   0.0,
			dir_x,  dir_y,  dir_z,  0.0,
			0.0,    0.0,    0.0,    1.0 };

		auto result = glm::scale(glm::rotate(model * rot_matrx, glm::radians((float)(90)), glm::vec3(1, 0, 0)), glm::vec3(1, __length * _len_, 1));
		return result;
	}

在这里插入图片描述

另外这个法线扭曲是无解,最好重新计算,有大佬能解决就好了,当然也可以有骚操作,就是通过shader里把小于0.4的亮度的强行变为0.4
glsl:

#version 330 core
out vec4 FragColor;

in vec2 TexCoords;
in vec3 Normal;
in vec3 FragPos;


uniform vec3 light_direction;


void main()
{  
  
	vec3 norm = normalize(Normal);
	vec3 lightDir = normalize(-light_direction);
	// diffuse shading
    float diff = max(dot(norm, lightDir), 0.0);
	if(diff<0.4)
		diff=0.4;
	vec3 color=vec3(0.447,1,0)*diff;
    FragColor = vec4(color, 0.75);
}

这样可以实现最基本的光照,已经非常还原Unity的效果了
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值