OpenGL--骨骼动画

news/2024/11/19 13:29:50/

理论基础

  1. 骨骼蒙皮动画其实现类似人体模型,由节点(关节)树构成,节点间通过骨骼连接,每块骨骼至多一个父节点,父节点带动子骨骼运动。具体是关节带动其对应子骨骼运动从而牵动绑定到其上的皮肤变化。骨骼是刚体不会变形,只能绕父节点旋转(构造前面章节有提–3D世界实现中的机器人手臂例子,早期的骨骼动画就是这样,不过在关节处会有明显裂缝,所以才引出现在的蒙皮概念)。而绑定到其上的皮肤顶点则是实时变换拉伸的,变换大体就是通过一些矩阵的操作来最终计算出新顶点坐标等信息,再根据这些新顶点信息进行渲染,即通过更新顶点,渲染这样不断循环形成动画。

  2. 实现步骤总结:
    一,根据更新前后两个关键帧的时间值插值计算出该时刻骨骼相对于其父骨骼的新变换矩阵–骨骼顶点信息。(本实例由于是手动控制动作,直接由变化的x,y计算)
    二,再计算皮肤顶点信息,首先找到影响其顶点的所有骨骼,然后计算每一骨骼对该顶点的影响,即计算出在每个独立骨骼作用下顶点的新位置。公式如下:
    这里写图片描述

    最后将所有这些新位置按照每一骨骼的影响权重加权求和,得到皮肤顶点信息。
    三,根据这些顶点信息进行绘制。

  3. 说明:
    1,我们通常会把每个关节赋予一个索引值标志,无论是储存空间上还是查找时间上,都比直接使用关节名高效得多。因为每个关节有且仅有一个父关节,只要在每个关节储存其父关节的索引,即能表示整个骨骼结构。由于根关节无父,所以其索引通常会设为无效的索引,如-1。

    2,对于一些要求比较精细的动作不适合用骨骼动画,因为这种动作需要的关节数接近网格顶点数了,那这样还不如直接控制网格顶点,如面部表情渲染。

    3,骨骼蒙皮动画核心就是怎么更新顶点数据,其实就是矩阵操作,关于这部分知识推荐一本好书《3D数学基础:图形与游戏开发》


实例源码

  • 实现
#include "GLTools.h"
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif#include "Bone.h"
#include "Matrix.h"
#include "Vector.h"#define MAX_BONES                2   /**骨骼数*/
#define MAX_MESHES              3   /**网格数,即基本图元数(纹理贴图后的皮肤)*/
#define MAX_MESH_POINTS    4   /**一个网格顶点数,即四边形*/CVector4         trans;                       /**< 用于平移骨骼模型 */
CBone             bones[MAX_BONES];            /**< 保存骨骼结构 */
CMatrix4x4     displayBones[MAX_BONES];     /**< 用于绘制骨骼 */
CBoneVertex   modelPoints[MAX_MESHES * MAX_MESH_POINTS]; /**< 模型顶点数据,即皮肤顶点 */void init(void)
{glClearColor(0.5f, 0.5f, 1.0f, 0.0f);glShadeModel(GL_SMOOTH);glEnable(GL_DEPTH_TEST);glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);/** 构造骨骼 */bones[0].SetBone(-1, 4.5f);/**根关节(骨骼索引与长度)*/bones[1].SetBone(0, 4.5f);/**子关节*//** 绑定到骨骼上的皮肤顶点数据 */modelPoints[0].SetVertex(CVector4(-1.0f, 0.0f, 0.0f), CVector4(0.0f, 0.0f, 1.0),0, 0, 0, 0, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1);modelPoints[1].SetVertex(CVector4(1.0f, 0.0f, 0.0f), CVector4(0.0f, 0.0f, 1.0),0, 0, 0, 0, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1);modelPoints[2].SetVertex(CVector4(1.0f, 3.0f, 0.0f), CVector4(0.0f, 0.0f, 1.0),0, 1, 0, 0, 0.50f, 0.50f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 2);modelPoints[3].SetVertex(CVector4(-1.0f, 3.0f, 0.0f), CVector4(0.0f, 0.0f, 1.0),0, 1, 0, 0, 0.50f, 0.50f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 2);modelPoints[4].SetVertex(CVector4(-1.0f, 3.0f, 0.0f), CVector4(0.0f, 0.0f, 1.0),0, 1, 0, 0, 0.50f, 0.50f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 2);modelPoints[5].SetVertex(CVector4(1.0f, 3.0f, 0.0f), CVector4(0.0f, 0.0f, 1.0),0, 1, 0, 0, 0.50f, 0.50f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 2);modelPoints[6].SetVertex(CVector4(1.0f, 6.0f, 0.0f), CVector4(0.0f, 0.0f, 1.0),0, 1, 0, 0, 0.35f, 0.65f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 2);modelPoints[7].SetVertex(CVector4(-1.0f, 6.0f, 0.0f), CVector4(0.0f, 0.0f, 1.0),0, 1, 0, 0, 0.35f, 0.65f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 2);modelPoints[8].SetVertex(CVector4(-1.0f, 6.0f, 0.0f), CVector4(0.0f, 0.0f, 1.0),0, 1, 0, 0, 0.35f, 0.65f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 2);modelPoints[9].SetVertex(CVector4(1.0f, 6.0f, 0.0f), CVector4(0.0f, 0.0f, 1.0),0, 1, 0, 0, 0.35f, 0.65f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 2);modelPoints[10].SetVertex(CVector4(1.0f, 9.0f, 0.0f), CVector4(0.0f, 0.0f, 1.0),1, 0, 0, 0, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1);modelPoints[11].SetVertex(CVector4(-1.0f, 9.0f, 0.0f), CVector4(0.0f, 0.0f, 1.0),1, 0, 0, 0, 1.0f, 0.0f, 0.0f, 0.0f, 1.0, 0.0f, 0.0f, 1.0f, 1);}GLint xRotation = 0;
GLint yRotation = 0;
/** 骨骼更新,即计算出每个骨骼的新变换矩阵,用displayBones数组保存 */
void updateBones()
{/** 用于保存旋转和平移矩阵 */CMatrix4x4 transpose, rotTemp1, rotTemp2, tempRelative;/** 循环更新骨骼 */for(int i = 0; i < MAX_BONES; i++){///检查是否是根骨骼if(bones[i].parent == -1){/** 设置变换矩阵 */bones[i].relative.Translate(trans.x, trans.y, trans.z);bones[i].absolute = bones[i].relative;/** 赋值,为了显示骨骼 */displayBones[i] = bones[i].relative;}else{bones[i].relative.Clear();/** 移动该骨骼到父结点骨骼(绕父骨骼转) */bones[i].relative.Translate(0, bones[bones[i].parent].length * i, 0);/** 根据鼠标旋转 */rotTemp1.Rotate(xRotation, 0, 1, 0);rotTemp2.Rotate(yRotation, 0, 0, 1);/** 保存相对变换矩阵,并反转 */tempRelative = bones[i].relative;tempRelative.inverseTranslate();/** 保存变换,为了显示骨骼 */displayBones[i] = bones[bones[i].parent].absolute * bones[i].relative *(rotTemp1 * rotTemp2);/** 计算相对变换矩阵 */bones[i].relative = bones[i].relative * (rotTemp1 * rotTemp2) * tempRelative;/** 计算绝对变换矩阵 */bones[i].absolute = bones[bones[i].parent].absolute * bones[i].relative;}}
}void display(void)
{/** 用户自定义的绘制过程 */glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );glLoadIdentity();glTranslatef(0.0f, -4.0f, -15.0f);/** 更新骨骼列表 */updateBones();CMatrix4x4 mat;/** 渲染网格中的顶点,即绘制皮肤 */for(int j = 0; j < MAX_MESHES; j++){glBegin(GL_QUADS);for(int i = 0; i < MAX_MESH_POINTS; i++){///获得顶点指针CBoneVertex *thisVertex = &modelPoints[i + j * MAX_MESH_POINTS];///根据权值计算顶点CVector4 pos = CVector4(0.0, 0.0, 0.0, 0.0);CVector4 normal = CVector4(0.0, 0.0, 0.0);for(int i2 = 0; i2 < thisVertex->numBones; i2++){mat = bones[thisVertex->boneIndex[i2]].absolute;///加权骨骼对顶点位置和法线的影响pos += (mat.VectorMatrixMultiply(thisVertex->pos) * thisVertex->weights[i2]);normal += (mat.VectorMatrixMultiply3x3(thisVertex->normal) *thisVertex->weights[i2]);}///渲染该顶点glColor4f(thisVertex->r, thisVertex->g, thisVertex->b, thisVertex->a);glNormal3f(normal.x, normal.y, normal.z);glVertex3f(pos.x, pos.y, pos.z);}glEnd();}//绘制骨骼for(int i = 0; i < MAX_BONES; i++){glPushMatrix();glMultMatrixf(displayBones[i].matrix);glColor3f(1.0f, 1.0f, 1.0f);glBegin(GL_LINES);///绘制线段glVertex3f(-0.4f, 0.0f, -0.4f);glVertex3f(0.4f, 0.0f, -0.4f);glVertex3f(0.4f, 0.0f, -0.4f);glVertex3f(0.4f, 0.0f, 0.4f);glVertex3f(0.4f, 0.0f, 0.4f);glVertex3f(-0.4f, 0.0f, 0.4f);glVertex3f(-0.4f, 0.0f, 0.4f);glVertex3f(-0.4f, 0.0f, -0.4f);glVertex3f(-0.4f, 0.0f, -0.4f);glVertex3f(0.0f, bones[i].length, 0.0f);glVertex3f(0.4f, 0.0f, -0.4f);glVertex3f(0.0f, bones[i].length, 0.0f);glVertex3f(0.4f, 0.0f, 0.4f);glVertex3f(0.0f, bones[i].length, 0.0f);glVertex3f(-0.4f, 0.0f, 0.4f);glVertex3f(0.0f, bones[i].length, 0.0f);glEnd();glPopMatrix();}/** 强制执行所有的OpenGL命令 */glFlush();
}void ChangeSize(int width, int height)
{glViewport(0, 0, width, height);                                    /**< 重新设置视口 */glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 1700.0f);glMatrixMode(GL_MODELVIEW);glLoadIdentity();
}int oldx = 0;
int oldy = 0;
void motion(int x, int y)
{xRotation = xRotation - (x - oldx);yRotation = yRotation - (y - oldy);oldx = x;oldy = y;glutPostRedisplay();
}int main(int argc, char** argv)
{glutInit(&argc, argv);glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB );glutInitWindowSize (400, 400);glutInitWindowPosition (100, 100);glutCreateWindow("骨骼动画");init();glutReshapeFunc(ChangeSize);glutDisplayFunc(display);glutMotionFunc(motion);glutMainLoop();return 0;
}

这里写图片描述


辅助类

  • 骨骼类
//
//  Bone.h
//  opengl
//
//  Created by app05 on 15-5-7.
//  Copyright (c) 2015年 app05. All rights reserved.
//#ifndef __opengl__Bone__
#define __opengl__Bone__#include <stdio.h>
#include "Matrix.h"/** 骨骼类 */
class CBone
{
public:CBone();/** 设置骨骼 */void SetBone(unsigned int P, float L);void SetBone(unsigned int P, float L, CMatrix4x4 R, CMatrix4x4 A);unsigned int parent;  /**< 父结点 */float length;         /**< 长度 *//** 变换矩阵 */CMatrix4x4 relative;CMatrix4x4 absolute;
};/** 骨骼顶点类,即绑定到骨骼上的皮肤顶点数据 */
class CBoneVertex
{
public:CBoneVertex();/** 设置顶点数据 */void SetVertex(CVector4 p, CVector4 n, int b1, int b2, int b3, int b4,float w1, float w2, float w3, float w4, float R, float G,float B, float A, int numB);CVector4 pos;         /**< 位置 */CVector4 normal;      /**< 法线 */int boneIndex[4];     /**< 骨骼索引 */float weights[4];     /**< 权值 */int numBones;         /**< 影响的骨骼数目 */float r, g, b, a;     /**< 颜色 */
};#endif /* defined(__opengl__Bone__) */

//
//  Bone.cpp
//  opengl
//
//  Created by app05 on 15-5-7.
//  Copyright (c) 2015年 app05. All rights reserved.
//#include "Bone.h"CBone::CBone() : parent(0), length(0)
{}/** 设置骨骼数据 */
void CBone::SetBone(unsigned int P, float L)
{parent = P; length = L;
}void CBone::SetBone(unsigned int P, float L, CMatrix4x4 R, CMatrix4x4 A)
{parent = P; length = L; relative = R; absolute = A;
}CBoneVertex::CBoneVertex() : r(0), g(0), b(0), a(0), numBones(0)
{///初始化各成员boneIndex[0] = 0; boneIndex[1] = 0; boneIndex[2] = 0; boneIndex[3] = 0;weights[0] = 0; weights[1] = 0; weights[2] = 0; weights[3] = 0;
}/** 设置顶点信息 */
void CBoneVertex::SetVertex(CVector4 p, CVector4 n, int b1, int b2, int b3, int b4,float w1, float w2, float w3, float w4,float R, float G, float B, float A, int numB)
{pos = p;normal = n;boneIndex[0] = b1; boneIndex[1] = b2; boneIndex[2] = b3; boneIndex[3] = b4;weights[0] = w1; weights[1] = w2; weights[2] = w3; weights[3] = w4;r = R; g = G; b = B; a = A;numBones = numB;
}

  • 向量类
//
//  Vector.h
//  opengl
//
//  Created by app05 on 15-5-7.
//  Copyright (c) 2015年 app05. All rights reserved.
//#ifndef __opengl__Vector__
#define __opengl__Vector__#include <stdio.h>
#include <math.h>
#define M_PI 3.141592654/** 四维向量类 */
class CVector4
{
public:///构造函数CVector4();CVector4(float X, float Y, float Z);CVector4(float X, float Y, float Z, float W);CVector4(const CVector4 &v);///运算符重载void operator=(CVector4 v);CVector4 operator-(CVector4 v);CVector4 operator+(CVector4 v);CVector4 operator*(CVector4 v);CVector4 operator/(CVector4 v);CVector4 operator+(float f);CVector4 operator-(float f);CVector4 operator*(float f);CVector4 operator/(float f);void operator +=(CVector4 v);void operator -=(CVector4 v);void operator *=(CVector4 v);void operator /=(CVector4 v);void operator +=(float f);void operator -=(float f);void operator *=(float f);void operator /=(float f);bool operator ==(CVector4 v);bool operator !=(CVector4 v);///叉乘void CrossProduct(CVector4 v1, CVector4 v2);void CrossProduct3(CVector4 v1, CVector4 v2,CVector4 v3);///点乘float DotProduct3(CVector4 v1);float DotProduct4(CVector4 v1);///返回向量长度float GetLength();///归一化向量void Normal();public:float x, y, z, w;
};#endif /* defined(__opengl__Vector__) */

//
//  Vector.cpp
//  opengl
//
//  Created by app05 on 15-5-7.
//  Copyright (c) 2015年 app05. All rights reserved.
//#include "Vector.h"CVector4::CVector4()
{///初始化x = y = z = 0.0; w = 1;
}CVector4::CVector4(float X, float Y, float Z)
{///初始化x = X;y = Y;z = Z;
}CVector4::CVector4(float X, float Y, float Z, float W)
{///初始化.x = X;y = Y;z = Z;w = W;
}CVector4::CVector4(const CVector4 &v)
{x = v.x;y = v.y;z = v.z;w = v.w;
}void CVector4::operator =(CVector4 v)
{x = v.x;y = v.y;z = v.z;w = v.w;
}/// -
CVector4 CVector4::operator -(CVector4 v)
{return CVector4(x - v.x, y - v.y, z - v.z);
}/// +
CVector4 CVector4::operator +(CVector4 v)
{return CVector4(x + v.x, y + v.y, z + v.z);
}/// *
CVector4 CVector4::operator *(CVector4 v)
{return CVector4(x * v.x, y * v.y, z * v.z);
}/// /
CVector4 CVector4::operator /(CVector4 v)
{return CVector4(x / v.x, y / v.y, z / v.z);
}/// +
CVector4 CVector4::operator +(float f)
{return CVector4(x + f, y + f, z + f);
}/// -
CVector4 CVector4::operator -(float f)
{return CVector4(x - f, y - f, z - f);
}/// *
CVector4 CVector4::operator *(float f)
{return CVector4(x * f, y * f, z * f);
}/// /
CVector4 CVector4::operator /(float f)
{f = 1/f;return CVector4(x * f, y * f, z * f);
}/// +=
void CVector4::operator +=(CVector4 v)
{x += v.x;y += v.y;z += v.z;
}/// -=
void CVector4::operator -=(CVector4 v)
{x -= v.x;y -= v.y;z -= v.z;
}/// *=
void CVector4::operator *=(CVector4 v)
{x *= v.x;y *= v.y;z *= v.z;
}/// /=
void CVector4::operator /=(CVector4 v)
{x /= v.x;y /= v.y;z /= v.z;
}/// +=
void CVector4::operator +=(float f)
{x += f;y += f;z += f;
}/// -=
void CVector4::operator -=(float f)
{x -= f;y -= f;z -= f;
}/// *=
void CVector4::operator *=(float f)
{x *= f;y *= f;z *= f;
}/// /=
void CVector4::operator /=(float f)
{f = 1/f;x *= f;y *= f;z *= f;
}/// ==
bool CVector4::operator ==(CVector4 v)
{return ((x == v.x) && (y== v.y) && (z == v.z));
}/// !=
bool CVector4::operator !=(CVector4 v)
{return !((x == v.x) && (y== v.y) && (z == v.z));
}/// 叉乘
void CVector4::CrossProduct(CVector4 v1, CVector4 v2)
{x = ((v1.y * v2.z) - (v1.z * v2.y));y = ((v1.z * v2.x) - (v1.x * v2.z));z = ((v1.x * v2.y) - (v1.y * v2.x));
}void CVector4::CrossProduct3(CVector4 v1, CVector4 v2, CVector4 v3)
{///求得v1,v2,v3的叉积x = v1.y * v2.z * v3.w +v1.z * v2.w * v3.y +v1.w * v2.y * v3.z -v1.y * v2.w * v3.z -v1.z * v2.y * v3.w -v1.w * v2.z * v3.y;y = v1.x * v2.w * v3.z +v1.z * v2.x * v3.w +v1.w * v2.z * v3.x -v1.x * v2.z * v3.w -v1.z * v2.w * v3.x -v1.w * v2.x * v3.z;z = v1.x * v2.y * v3.w +v1.y * v2.w * v3.x +v1.w * v2.x * v3.y -v1.x * v2.w * v3.y -v1.y * v2.x * v3.w -v1.w * v2.y * v3.x;w = v1.x * v2.z * v3.y +v1.y * v2.x * v3.z +v1.z * v2.y * v3.x -v1.x * v2.y * v3.z -v1.y * v2.z * v3.x -v1.z * v2.x * v3.y;
}/// 点乘
float CVector4::DotProduct3(CVector4 v1)
{return x * v1.x + y * v1.y + z * v1.z;
}float CVector4::DotProduct4(CVector4 v1)
{return x * v1.x + y * v1.y + z * v1.z + w * v1.w;
}/// 返回长度
float CVector4::GetLength()
{return (float)sqrt((x * x + y * y + z * z));
}/// 归一化
void CVector4::Normal()
{float lenght = GetLength();if(lenght == 0.0f)lenght = 1.0f;x = x/lenght;y = y/lenght;z = z/lenght;w = w/lenght;
}

  • 4x4矩阵类
//
//  Matrix.h
//  opengl
//
//  Created by app05 on 15-5-7.
//  Copyright (c) 2015年 app05. All rights reserved.
//#ifndef __opengl__Matrix__
#define __opengl__Matrix__#include <stdio.h>
#include "Vector.h"/** 4x4矩阵类 */
class  CMatrix4x4
{
public:///构造函数CMatrix4x4();CMatrix4x4(const CMatrix4x4 &m);CMatrix4x4(float r11, float r12, float r13, float r14,float r21, float r22, float r23, float r24,float r31, float r32, float r33, float r34,float r41, float r42, float r43, float r44);~CMatrix4x4();///重置矩阵void Clear();void Zero();///运算符重载void operator=(CMatrix4x4 m);CMatrix4x4 operator-(CMatrix4x4 m);CMatrix4x4 operator+(CMatrix4x4 m);CMatrix4x4 operator*(CMatrix4x4 m);CMatrix4x4 operator/(CMatrix4x4 m);void operator +=(CMatrix4x4 m);void operator -=(CMatrix4x4 m);void operator *=(CMatrix4x4 m);void operator /=(CMatrix4x4 m);CMatrix4x4 operator-(float f);CMatrix4x4 operator+(float f);CMatrix4x4 operator*(float f);CMatrix4x4 operator/(float f);void operator -=(float f);void operator +=(float f);void operator *=(float f);void operator /=(float f);bool operator ==(CMatrix4x4 v);bool operator !=(CMatrix4x4 v);///平移一个点void Translate(CVector4 Translate);void Translate(float x, float y, float z);void inverseTranslate();///旋转一个点void Rotate(double angle, float x, float y,float z);///向量与矩阵相乘CVector4 VectorMatrixMultiply(CVector4 v);CVector4 VectorMatrixMultiply3x3(CVector4 v);public:float matrix[16];
};#endif /* defined(__opengl__Matrix__) */

//
//  Matrix.cpp
//  opengl
//
//  Created by app05 on 15-5-7.
//  Copyright (c) 2015年 app05. All rights reserved.
//#include "Matrix.h"CMatrix4x4::CMatrix4x4()
{///初始化各元素Clear();
}CMatrix4x4::CMatrix4x4(const CMatrix4x4 &m)
{matrix[0]  = m.matrix[0];matrix[4]  = m.matrix[4];matrix[8]  = m.matrix[8];matrix[12] = m.matrix[12];matrix[1]  = m.matrix[1];matrix[5]  = m.matrix[5];matrix[9]  = m.matrix[9];matrix[13] = m.matrix[13];matrix[2]  = m.matrix[2];matrix[6]  = m.matrix[6];matrix[10] = m.matrix[10];matrix[14] = m.matrix[14];matrix[3]  = m.matrix[3];matrix[7]  = m.matrix[7];matrix[11] = m.matrix[11];matrix[15] = m.matrix[15];
}CMatrix4x4::CMatrix4x4(float r11, float r12, float r13, float r14,float r21, float r22, float r23, float r24,float r31, float r32, float r33, float r34,float r41, float r42, float r43, float r44)
{matrix[0]  = r11; matrix[1]  = r12; matrix[2]  = r13; matrix[3]  = r14;matrix[4]  = r21; matrix[5]  = r22; matrix[6]  = r23; matrix[7]  = r24;matrix[8]  = r31; matrix[9]  = r32; matrix[10] = r33; matrix[11] = r34;matrix[12] = r41; matrix[13] = r42; matrix[14] = r43; matrix[15] = r44;
}CMatrix4x4::~CMatrix4x4()
{}void CMatrix4x4::operator =(CMatrix4x4 m)
{matrix[0]  = m.matrix[0]; matrix[1]   = m.matrix[1]; matrix[2]   = m.matrix[2];matrix[3]  = m.matrix[3];matrix[4]  = m.matrix[4]; matrix[5]   = m.matrix[5]; matrix[6]   = m.matrix[6];matrix[7]  = m.matrix[7];matrix[8]  = m.matrix[8]; matrix[9]   = m.matrix[9]; matrix[10]  = m.matrix[10];matrix[11] = m.matrix[11];matrix[12] = m.matrix[12]; matrix[13] = m.matrix[13]; matrix[14] = m.matrix[14];matrix[15] = m.matrix[15];
}/// 矩阵相减
CMatrix4x4 CMatrix4x4::operator -(CMatrix4x4 m)
{return CMatrix4x4(matrix[0] - m.matrix[0], matrix[1] - m.matrix[1], matrix[2] - m.matrix[2],matrix[3] - m.matrix[3], matrix[4] - m.matrix[4], matrix[5] - m.matrix[5],matrix[6] - m.matrix[6], matrix[7] - m.matrix[7], matrix[8] - m.matrix[8],matrix[9] - m.matrix[9], matrix[10] - m.matrix[10], matrix[11] - m.matrix[11],matrix[12] - m.matrix[12], matrix[13] - m.matrix[13],matrix[14] - m.matrix[14], matrix[15] - m.matrix[15]);
}/// 矩阵相加
CMatrix4x4 CMatrix4x4::operator +(CMatrix4x4 m)
{return CMatrix4x4(matrix[0] + m.matrix[0], matrix[1] + m.matrix[1], matrix[2] + m.matrix[2],matrix[3] + m.matrix[3], matrix[4] + m.matrix[4], matrix[5] + m.matrix[5],matrix[6] + m.matrix[6], matrix[7] + m.matrix[7], matrix[8] + m.matrix[8],matrix[9] + m.matrix[9], matrix[10] + m.matrix[10], matrix[11] + m.matrix[11],matrix[12] + m.matrix[12], matrix[13] + m.matrix[13],matrix[14] + m.matrix[14], matrix[15] + m.matrix[15]);
}/// 矩阵相乘
CMatrix4x4 CMatrix4x4::operator *(CMatrix4x4 m)
{float newMatrix[16];const float *m1 = matrix, *m2 = m.matrix;newMatrix[0] = m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2];newMatrix[1] = m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2];newMatrix[2] = m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2];newMatrix[3] = 0;newMatrix[4] = m1[0] * m2[4] + m1[4] * m2[5] + m1[8] * m2[6];newMatrix[5] = m1[1] * m2[4] + m1[5] * m2[5] + m1[9] * m2[6];newMatrix[6] = m1[2] * m2[4] + m1[6] * m2[5] + m1[10] * m2[6];newMatrix[7] = 0;newMatrix[8] = m1[0] * m2[8] + m1[4] * m2[9] + m1[8] * m2[10];newMatrix[9] = m1[1] * m2[8] + m1[5] * m2[9] + m1[9] * m2[10];newMatrix[10] = m1[2] * m2[8] + m1[6] * m2[9] + m1[10] * m2[10];newMatrix[11] = 0;newMatrix[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8] * m2[14] + m1[12];newMatrix[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9] * m2[14] + m1[13];newMatrix[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14];newMatrix[15] = 1;return CMatrix4x4(newMatrix[0], newMatrix[1], newMatrix[2], newMatrix[3], newMatrix[4],newMatrix[5], newMatrix[6], newMatrix[7], newMatrix[8], newMatrix[9],newMatrix[10], newMatrix[11], newMatrix[12], newMatrix[13], newMatrix[14],newMatrix[15]);
}/// 矩阵相除
CMatrix4x4 CMatrix4x4::operator /(CMatrix4x4 m)
{return CMatrix4x4(matrix[0] / m.matrix[0] + matrix[4] / m.matrix[1] + matrix[8] /m.matrix[2] + matrix[12] / m.matrix[3],matrix[1] / m.matrix[0] + matrix[5] / m.matrix[1] + matrix[9] /m.matrix[2] + matrix[13] / m.matrix[3],matrix[2] / m.matrix[0] + matrix[6] / m.matrix[1] + matrix[10] /m.matrix[2] + matrix[14] / m.matrix[3],matrix[3] / m.matrix[0] + matrix[7] / m.matrix[1] + matrix[11] /m.matrix[2] + matrix[15] / m.matrix[3],matrix[0] / m.matrix[4] + matrix[4] / m.matrix[5] + matrix[8] /m.matrix[6] + matrix[12] / m.matrix[7],matrix[1] / m.matrix[4] + matrix[5] / m.matrix[5] + matrix[9] /m.matrix[6] + matrix[13] / m.matrix[7],matrix[2] / m.matrix[4] + matrix[6] / m.matrix[5] + matrix[10] /m.matrix[6] + matrix[14] / m.matrix[7],matrix[3] / m.matrix[4] + matrix[7] / m.matrix[5] + matrix[11] /m.matrix[6] + matrix[15] / m.matrix[7],matrix[0] / m.matrix[8] + matrix[4] / m.matrix[9] + matrix[8] /m.matrix[10] + matrix[12] / m.matrix[11],matrix[1] / m.matrix[8] + matrix[5] / m.matrix[9] + matrix[9] /m.matrix[10] + matrix[13] / m.matrix[11],matrix[2] / m.matrix[8] + matrix[6] / m.matrix[9] + matrix[10] /m.matrix[10] + matrix[14] / m.matrix[11],matrix[3] / m.matrix[8] + matrix[7] / m.matrix[9] + matrix[11] /m.matrix[10] + matrix[15] / m.matrix[11],matrix[0] / m.matrix[12] + matrix[4] / m.matrix[13] + matrix[8] /m.matrix[14] + matrix[12] / m.matrix[15],matrix[1] / m.matrix[12] + matrix[5] / m.matrix[13] + matrix[9] /m.matrix[14] + matrix[13] / m.matrix[15],matrix[2] / m.matrix[12] + matrix[6] / m.matrix[13] + matrix[10] /m.matrix[14] + matrix[14] / m.matrix[15],matrix[3] / m.matrix[12] + matrix[7] / m.matrix[13] + matrix[11] /m.matrix[14] + matrix[15] / m.matrix[15]);
}CMatrix4x4 CMatrix4x4::operator -(float f)
{return CMatrix4x4(matrix[0]  - f, matrix[1]  - f, matrix[2]  - f, matrix[3]  - f,matrix[4]  - f, matrix[5]  - f, matrix[6]  - f, matrix[7]  - f,matrix[8]  - f, matrix[9]  - f, matrix[10] - f, matrix[11] - f,matrix[12] - f, matrix[13] - f, matrix[14] - f, matrix[15] - f);
}CMatrix4x4 CMatrix4x4::operator +(float f)
{return CMatrix4x4(matrix[0]  + f, matrix[1]  + f, matrix[2]  + f, matrix[3]  + f,matrix[4]  + f, matrix[5]  + f, matrix[6]  + f, matrix[7]  + f,matrix[8]  + f, matrix[9]  + f, matrix[10] + f, matrix[11] + f,matrix[12] + f, matrix[13] + f, matrix[14] + f, matrix[15] + f);
}CMatrix4x4 CMatrix4x4::operator *(float f)
{return CMatrix4x4(matrix[0]  * f, matrix[1]  * f, matrix[2]  * f, matrix[3]  * f,matrix[4]  * f, matrix[5]  * f, matrix[6]  * f, matrix[7]  * f,matrix[8]  * f, matrix[9]  * f, matrix[10] * f, matrix[11] * f,matrix[12] * f, matrix[13] * f, matrix[14] * f, matrix[15] * f);
}CMatrix4x4 CMatrix4x4::operator /(float f)
{if(f == 0) f = 1;f = 1/f;return CMatrix4x4(matrix[0]  * f, matrix[1]  * f, matrix[2]  * f, matrix[3]  * f,matrix[4]  * f, matrix[5]  * f, matrix[6]  * f, matrix[7]  * f,matrix[8]  * f, matrix[9]  * f, matrix[10] * f, matrix[11] * f,matrix[12] * f, matrix[13] * f, matrix[14] * f, matrix[15] * f);
}bool CMatrix4x4::operator ==(CMatrix4x4 m)
{for(int i = 0; i < 16; i++){if(matrix[i] != m.matrix[i])return false;}return true;
}void CMatrix4x4::operator +=(CMatrix4x4 m)
{(*this) = (*this) + m;
}void CMatrix4x4::operator -=(CMatrix4x4 m)
{(*this) = (*this) - m;
}void CMatrix4x4::operator *=(CMatrix4x4 m)
{(*this) = (*this) * m;
}void CMatrix4x4::operator /=(CMatrix4x4 m)
{(*this) = (*this) / m;
}bool CMatrix4x4::operator !=(CMatrix4x4 m)
{return !((*this) == m);
}void CMatrix4x4::operator -=(float f)
{(*this) = (*this) - f;
}void CMatrix4x4::operator +=(float f)
{(*this) = (*this) + f;
}void CMatrix4x4::operator *=(float f)
{(*this) = (*this) * f;
}void CMatrix4x4::operator /=(float f)
{(*this) = (*this) / f;
}void CMatrix4x4::Clear()
{///重置矩阵为单位矩阵matrix[0]  = 1.0f; matrix[1]  = 0.0f; matrix[2]  = 0.0f; matrix[3]  = 0.0f;matrix[4]  = 0.0f; matrix[5]  = 1.0f; matrix[6]  = 0.0f; matrix[7]  = 0.0f;matrix[8]  = 0.0f; matrix[9]  = 0.0f; matrix[10] = 1.0f; matrix[11] = 0.0f;matrix[12] = 0.0f; matrix[13] = 0.0f; matrix[14] = 0.0f; matrix[15] = 1.0f;}void CMatrix4x4::Zero()
{///重置矩阵各元素为0matrix[0]  = 0.0f; matrix[1]  = 0.0f; matrix[2]  = 0.0f; matrix[3]  = 0.0f;matrix[4]  = 0.0f; matrix[5]  = 0.0f; matrix[6]  = 0.0f; matrix[7]  = 0.0f;matrix[8]  = 0.0f; matrix[9]  = 0.0f; matrix[10] = 0.0f; matrix[11] = 0.0f;matrix[12] = 0.0f; matrix[13] = 0.0f; matrix[14] = 0.0f; matrix[15] = 0.0f;
}///平移变换
void CMatrix4x4::Translate(CVector4 Translate)
{matrix[12] = Translate.x;matrix[13] = Translate.y;matrix[14] = Translate.z;matrix[15] = 1.0f;
}void CMatrix4x4::Translate(float x, float y, float z)
{matrix[12] = x;matrix[13] = y;matrix[14] = z;matrix[15] = 1.0f;
}void CMatrix4x4::inverseTranslate()
{matrix[12] = -matrix[12];matrix[13] = -matrix[13];matrix[14] = -matrix[14];
}/// 旋转变换
void CMatrix4x4::Rotate(double angle, float x, float y, float z)
{float sine = (float)sin(angle);float cosine = (float)cos(angle);float sinAngle = (float)sin(3.14 * angle / 180);float cosAngle = (float)cos(3.14 * angle / 180);float oneSubCos = 1.0f - cosAngle;matrix[0] = (x * x) * oneSubCos + cosAngle;matrix[4] = (x * y) * oneSubCos - (z * sinAngle);matrix[8] = (x * z) * oneSubCos + (y * sinAngle);matrix[1] = (y * x) * oneSubCos + (sinAngle * z);matrix[5] = (y * y) * oneSubCos + cosAngle;matrix[9] = (y * z) * oneSubCos - (x * sinAngle);matrix[2] = (z * x) * oneSubCos - (y * sinAngle);matrix[6] = (z * y) * oneSubCos + (x * sinAngle);matrix[10] = (z * z) * oneSubCos + cosAngle;
}///向量与矩阵相乘
CVector4 CMatrix4x4::VectorMatrixMultiply(CVector4 v)
{CVector4 out;out.x = (v.x * matrix[0]) + (v.y * matrix[4]) + (v.z * matrix[8]) + matrix[12];out.y = (v.x * matrix[1]) + (v.y * matrix[5]) + (v.z * matrix[9]) + matrix[13];out.z = (v.x * matrix[2]) + (v.y * matrix[6]) + (v.z * matrix[10]) + matrix[14];return out;
}CVector4 CMatrix4x4::VectorMatrixMultiply3x3(CVector4 v)
{CVector4 out;out.x = (v.x * matrix[0]) + (v.y * matrix[4]) + (v.z * matrix[8]);out.y = (v.x * matrix[1]) + (v.y * matrix[5]) + (v.z * matrix[9]);out.z = (v.x * matrix[2]) + (v.y * matrix[6]) + (v.z * matrix[10]);return out;
}

http://www.ppmy.cn/news/911919.html

相关文章

RSA2验签遭遇异常,请检查公钥格式是否正确。待验签内容不可为空

支付宝支付&#xff0c;上线突然出现这个问题。 2021-09-27 22:54:37 2021-09-27 14:54:37.348 [http-nio-5020-exec-7] INFO com.fastonetech.listener.OrderPayedListener - 支付宝回调&#xff0c;{} 2021-09-27 22:54:37 2021-09-27 14:54:37.348 [http-nio-5020-exec-7]…

POI和POI-TL操作Word

POI操作Word 操作依赖包org.apache.poi&#xff0c;包括poi和poi-ooxml。创建空白Word文件 void poiCreateNewWord() {String path "C:\\Users\\wisdom21111\\Desktop\\";XWPFDocument document new XWPFDocument();try {FileOutputStream out new FileOutputStr…

beagleboneblack(BBB)开发板使用NFS挂载根文件系统,tftp下载镜像与设备树

一、文件下载 交叉编译工具链下载地址 wget -c https://releases.linaro.org/components/toolchain/binaries/6.5-2018.12/arm-linux-gnueabihf/gcc-linaro-6.5.0-2018.12-i686_arm-linux-gnueabihf.tar.xz beagleboneblack内核kernel下载地址&#xff0c;切换到tag为4.19.94-t…

数据结构与算法基础ppt

根据数据结构C语言版第2版书编写。想要电子书的童鞋可以私我 B站学习地址 9.13开始 9.29更新到p118 线性表 2.1线性表的定义和特点 P10 2.2 案例引入 p11 2.3 线性表的类型定义 p12 2.4 线性表的顺序表示和实现1 p13 2.4 线性表的顺序表示和实现2 p14 P15 第02周06–类C语言…

ia笔记总结

HCIA 计算机 使用二进制语言 应用层&#xff1a;人机交互的接口&#xff0c;自然语言转化为编码表示层&#xff1a;编码–>二进制&#xff0c;翻译介质访问控制层&#xff1a;控制硬件物理层:CPU 对等网 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接…

golang打包后在另一台电脑运行报错/lib64/libc.so.6: version `GLIBC_xxxx‘ not found解决方案

前言 最近使用golang打包项目出现个问题报错/lib64/libc.so.6: version GLIBC_xxxx’ not found&#xff0c;很多人都说需要安装GLIBC解决&#xff0c;但是这里有个误区&#xff0c;好像CGO库是依赖glibc的&#xff08;具体的我也没有考证&#xff09;就是我根部就没有使用CGO…

jakarta ee_Jakarta EE社区之声:Jakarta EE的未来是什么?

jakarta ee 本月初&#xff0c;Jakarta EE社区成员被邀请参加Jakarta EE社区之声文档 &#xff0c;该文档重点关注Jakarta EE规范的技术创新。 本文档中的内容反映了参与者对他们希望贡献时间的领域的个人观点。 但是&#xff0c;必须提及的是&#xff0c;它们并不代表硬性承诺…

C#正则表达式通过HTML提取网页中的图片src

C#正则表达式通过HTML提取网页中的图片src 原文: C#正则表达式通过HTML提取网页中的图片src 目前在做HoverTreeCMS项目中有处理图片的部分&#xff0c;参考了一下网上案例&#xff0c;自己写了一个获取内容中的图片地址的方法。可以先看看效果&#xff1a;http://tool.hovertre…