Transformation,Animation and Viewing

4 Transformation,Animation and Viewing

声明:该代码来自:Computer Graphics Through OpenGL From Theory to Experiments,仅用作学习参考

4.1 Modeling Transformations

平移、缩放和旋转,即 OpenGL 的建模转换,应用于物体以更改其位置和形状。
Modeling Transformations控制世界坐标系中物体的位置、大小、旋转

4.1.1 Translation




glFrustum(left, right, bottom, top, near, far)
请注意 OpenGL 的一个小怪癖,即 near 和 far 值在符号上颠倒。
给函数glFrustum输入near,far为正数,实际上为 z = − near , z = − far \text{z}=-\text{near}, \text{z}=-\text{far} z=near,z=far

4.1.2 Scaling

the scaling command glScalef(u, v, w) maps each point (x,y,z) of an object to the point (ux vy wz). This has the e ect of stretching objects by a factor of u in the x-direction, v in the y-direction, and w in the z-direction

一个或多个缩放因子为零的缩放转换称为退化转换。虽然并不常见,但偶尔会有一些应用程序会派上用场。
如果w为0那么,将3维物体退化为2维



4.1.3 Rotation



4.2 Composing Modeling Transformations

任务:想要对正方形绕它自己的中心逆时针旋转45°,如 Figure 4.20(a)所示


如果直接使用glRotatef(45.0, 0.0, 0.0, 1.0)则会得到4.20(b)中的效果,即绕原点逆时针45°,而不是绕物体本身的中心旋转45°


正确步骤应该是:
(3)glTranslatef(7.5, 7.5, 0.0); // Translate back
(2)glRotatef(45.0, 0.0, 0.0, 1.0); // Rotate about origin.
(1)glTranslatef(-7.5,-7.5, 0.0); // Translate to origin.

在 OpenGL 中,变换矩阵的操作是以堆栈的方式进行的,最新的变换操作会首先应用。也就是说,变换操作的执行顺序是从最后一个变换开始,依次向前应用。

4.3 Placing Multiple Objects



在 OpenGL 中,所有的矩阵变换操作会累积在当前的模型视图矩阵上,并且会影响后续的绘制操作。因此,在你的 drawScene 函数中,所有的变换操作会同时作用于立方体和球体。这些变换会作用于立方体和球体。为了确保球体的变换不受立方体的变换影响,你可以在绘制球体之前重置模型视图矩阵例如使用glLoadIdentity(); 或者使用 glPushMatrix 和 glPopMatrix 来保存和恢复矩阵状态。

在创建时,Object1 的局部坐标系与世界坐标系重合。

(1)如果变换 tn 是由函数 glTranslatef(p, q, r) 指定的 translation 变换
则物体所有顶点 V 相对于 object1 的局部坐标系的位置 ( a , b , c ) (a,b,c) (a,b,c) 不会改变。但V在世界坐标系中的位置变为了 ( a + p , b + q , c + r ) (a+p,b+q,c+r) (a+p,b+q,c+r)

(2) 如果变换 tn 是由函数 glRotatef(A, p, q, r) 指定的 rotation 变换
则物体所有顶点 V 相对于 object1 的局部坐标系的位置 ( a , b , c ) (a,b,c) (a,b,c) 不会改变

(3)如果变换 tn 是由函数 glScalef(u, v, w) 指定的 scaling 变换
V 在世界坐标中的位置通过缩放更改为 ( u a , v b , w c ) (ua,vb,wc) (ua,vb,wc)。但是,由于相同的缩放适用于 object1 的局部坐标系的轴,因此 V 相对于该系统的位置 ( a , b , c ) (a,b,c) (a,b,c) 不会再次改变。

例子:
浅蓝色为世界坐标系、红人和蓝人有各自的局部坐标系(图中只画出了红人的局部坐标系),对两个人进行变换,可以看出两人在世界坐标系中的坐标发生了变换,但是在他们各自的局部坐标系中均为发生变换

///      
// relativePlacement.cpp
//
// This program shows composition of transformations and 
// the relative placement of one object w.r.t another.
//
// Interaction:
// Press the up/down arrow keys to process code statements.
//
// Sumanta Guha.
///#define _USE_MATH_DEFINES #include <cmath>
#include <iostream>#include <GL/glew.h>
#include <GL/freeglut.h> // Globals.
static unsigned int base; // Display lists base index.
static int numVal = 0; // Step index.
static long font = (long)GLUT_BITMAP_8_BY_13; // Font selection.// Routine to draw a bitmap character string.
void writeBitmapString(void *font, char *string)
{char *c;for (c = string; *c != '\0'; c++) glutBitmapCharacter(font, *c);
}// Draw stick figure with a local co-ordinate system.
void drawMan(void)
{float angle;int i;glLineWidth(2.0);glBegin(GL_LINE_LOOP);for (i = 0; i < 20; ++i){angle = 2 * M_PI * i / 20;glVertex2f(0.0 + cos(angle) * 3.0, 7 + sin(angle) * 3.0);}glEnd();glBegin(GL_LINES);glVertex2f(0.0, 4.0);glVertex2f(0.0, -4.0);glVertex2f(0.0, -4.0);glVertex2f(6.0, -10.0);glVertex2f(0.0, -4.0);glVertex2f(-6.0, -10.0);glVertex2f(-6.0, 0.0);glVertex2f(6.0, 0.0);glEnd();glLineWidth(1.0);glRasterPos3f(0.0, 0.0, 0.0);writeBitmapString((void*)font, "O");glRasterPos3f(7.0, 0.0, 0.0);writeBitmapString((void*)font, "x");glRasterPos3f(-1.0, 6.0, 0.0);writeBitmapString((void*)font, "y");
}// Draw local co-ordinates grid.
void drawGrid(void)
{int i;glEnable(GL_LINE_STIPPLE); // Enable line stippling.glLineStipple(1, 0x00FF);glBegin(GL_LINES);for (i = -5; i < 6; ++i){glVertex2f(5 * i, 25.0);glVertex2f(5 * i, -25.0);}for (i = -5; i < 6; ++i){glVertex2f(25.0, 5 * i);glVertex2f(-25.0, 5 * i);}glEnd();glDisable(GL_LINE_STIPPLE); // Disable line stippling.
}// Draw and label world co-ordinate axes.
void drawWorldAxes(void)
{glColor3f(0.0, 1.0, 1.0);glBegin(GL_LINES);glVertex2f(-50.0, 0.0);glVertex2f(50.0, 0.0);glVertex2f(0.0, -50.0);glVertex2f(0.0, 50.0);glEnd();glRasterPos3f(48.0, -2.0, 0.0);writeBitmapString((void*)font, "x");glRasterPos3f(1.0, 48.0, 0.0);writeBitmapString((void*)font, "y");
}// Write fixed messages.
void writeFixedMessages(void)
{glColor3f(0.0, 0.0, 0.0);glRasterPos3f(-15.0, 43.0, 0.0);writeBitmapString((void*)font, "Press the up/down arrow keys!");glColor3f(0.8, 0.8, 0.8);glRasterPos3f(-44.0, -17.0, 0.0);writeBitmapString((void*)font, "glScalef(1.5, 0.75, 1.0);");glRasterPos3f(-44.0, -20.0, 0.0);writeBitmapString((void*)font, "glRotatef(30.0, 0.0, 0.0, 1.0);");glRasterPos3f(-44.0, -23.0, 0.0);writeBitmapString((void*)font, "glTranslatef(10.0, 0.0, 0.0);");glRasterPos3f(-44.0, -26.0, 0.0);writeBitmapString((void*)font, "drawRedMan; // Also draw grid in his local co-ordinate system.");glRasterPos3f(-44.0, -29.0, 0.0);writeBitmapString((void*)font, "glRotatef(45.0, 0.0, 0.0, 1.0);");glRasterPos3f(-44.0, -32.0, 0.0);writeBitmapString((void*)font, "glTranslatef(20.0, 0.0, 0.0);");glRasterPos3f(-44.0, -35.0, 0.0);writeBitmapString((void*)font, "drawBlueMan;");
}// Drawing routine.
void drawScene(void)
{glClear(GL_COLOR_BUFFER_BIT);glLoadIdentity();writeFixedMessages();drawWorldAxes();glColor3f(0.0, 0.0, 0.0);switch (numVal){case 0:goto step0;break;case 1:goto step1;break;case 2:goto step2;break;case 3:goto step3;break;case 4:goto step4;break;case 5:goto step5;break;case 6:goto step6;break;case 7:goto step7;break;default:break;}// Transformation steps.// Text drawing statements are enclosed within push/pop pairs// so that the raster position is w.r.t the identity transform.
step7:// Scale. glPushMatrix();glLoadIdentity();glRasterPos3f(-44.0, -17.0, 0.0);writeBitmapString((void*)font, "glScalef(1.5, 0.75, 1.0);");glPopMatrix();glScalef(1.5, 0.75, 1.0);step6:// Rotate. glPushMatrix();glLoadIdentity();glRasterPos3f(-44.0, -20.0, 0.0);writeBitmapString((void*)font, "glRotatef(30.0, 0.0, 0.0, 1.0);");glPopMatrix();glRotatef(30, 0.0, 0.0, 1.0);step5:// Translate.glPushMatrix();glLoadIdentity();glRasterPos3f(-44.0, -23.0, 0.0);writeBitmapString((void*)font, "glTranslatef(10.0, 0.0, 0.0);");glPopMatrix();glTranslatef(10.0, 0.0, 0.0);step4:// Draw red man.glPushMatrix();glLoadIdentity();glRasterPos3f(-44.0, -26.0, 0.0);writeBitmapString((void*)font, "drawRedMan; // Also draw grid in his local co-ordinate system.");glPopMatrix();glColor3f(1.0, 0.0, 0.0);glCallList(base);glCallList(base + 1);glColor3f(0.0, 0.0, 0.0);step3:// Rotate.glPushMatrix();glLoadIdentity();glRasterPos3f(-44.0, -29.0, 0.0);writeBitmapString((void*)font, "glRotatef(45.0, 0.0, 0.0, 1.0);");glPopMatrix();glRotatef(45, 0.0, 0.0, 1.0);step2:// Translate.glPushMatrix();glLoadIdentity();glRasterPos3f(-44.0, -32.0, 0.0);writeBitmapString((void*)font, "glTranslatef(20.0, 0.0, 0.0);");glPopMatrix();glTranslatef(20.0, 0.0, 0.0);step1:// Draw blue man.glPushMatrix();glLoadIdentity();glRasterPos3f(-44.0, -35.0, 0.0);writeBitmapString((void*)font, "drawBlueMan;");glPopMatrix();glColor3f(0.0, 0.0, 1.0);glCallList(base);step0:glFlush();
}// Initialization routine.
void setup(void)
{base = glGenLists(2);glNewList(base, GL_COMPILE);drawMan();glEndList();glNewList(base + 1, GL_COMPILE);drawGrid();glEndList();glClearColor(1.0, 1.0, 1.0, 0.0);
}// OpenGL window reshape routine.
void resize(int w, int h)
{glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION);glLoadIdentity();glOrtho(-50.0, 50.0, -50.0, 50.0, -1.0, 1.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();
}// Keyboard input processing routine.
void keyInput(unsigned char key, int x, int y)
{switch (key){case 27:exit(0);break;break;default:break;}
}// Callback routine for non-ASCII key entry.
void specialKeyInput(int key, int x, int y)
{if (key == GLUT_KEY_UP){if (numVal < 7) numVal++; else numVal = 0;}if (key == GLUT_KEY_DOWN){if (numVal > 0) numVal--; else numVal = 7;}glutPostRedisplay();
}// Routine to output interaction instructions to the C++ window.
void printInteraction(void)
{std::cout << "Interaction:" << std::endl;std::cout << "Press the up/down arrow keys to process code statements." << std::endl;
}// Main routine.
int main(int argc, char **argv)
{printInteraction();glutInit(&argc, argv);glutInitContextVersion(4, 3);glutInitContextProfile(GLUT_COMPATIBILITY_PROFILE);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);glutInitWindowSize(500, 500);glutInitWindowPosition(100, 100);glutCreateWindow("relativePlacement.cpp");glutDisplayFunc(drawScene);glutReshapeFunc(resize);glutKeyboardFunc(keyInput);glutSpecialFunc(specialKeyInput);glewExperimental = GL_TRUE;glewInit();setup();glutMainLoop();
}

4.4 Modelview Matrix Stack and Isolating Transformations

modelview 矩阵堆栈有助于将转换应用于多个对象

我们描述的 modelview 矩阵是通过右侧的乘法建模转换来修改的,实际上是 modelview 矩阵堆栈中最上面的一个。这个特定的矩阵称为当前 modelview 矩阵。事实上,OpenGL 维护了三个不同的矩阵堆栈:modelview、projection 和 texture。glMatrixMode(mode) 命令(其中 mode 为 GL_MODELVIEW、GL_PROJECTION 或 GL_TEXTURE)确定当前处于活动状态的堆栈。

glPushMatrix() 命令的作用是在 modelview 矩阵堆栈中复制当前(即当前最顶层)矩阵,并将其放置在堆栈顶部;因此,在执行 glPushMatrix() 时,堆栈的两个顶部矩阵立即相同。另一方面,glPopMatrix() 语句会删除 modelview 矩阵堆栈的最顶层矩阵,以便下面的矩阵成为当前矩阵。

4.5 Animation

4.5.1 Animation Technicals

Controlling Animation
在 OpenGL 中,有三种简单的方法可以控制动画:

  1. 通过键盘或鼠标输入以交互方式,借助其回调例程(callback routine)来调用转换
  2. 用glutIdelFunc(idle_function)语句调用idle函数,idle 函数在没有 OpenGL 事件时处于待处理状态时调用。
  3. 通过指定一个常规定时器函数(称为定时器函数),并调用 glutTimerFunc(period, 定时器函数, value) 即可实现半自动操作。定时器函数会在执行 glutTimerFunc() 语句后的 period 毫秒被调用,并且会将传递给它的参数值作为参数。

Double Buffer
颜色缓冲区是一个空间,通常位于 GPU 内存中,用于存储光栅像素的 RGBA 值,通常每个 R、G、B 和 A 分别占用 8 位,总计每个像素 32 位。因此,颜色缓冲区保存着单帧的数据,并在该帧被绘制到显示器时进行读取。
在双缓冲系统中,会提供两个颜色缓冲区的空间,其中一个缓冲区(可查看缓冲区)保存当前显示在显示器上的帧,而下一帧则在第二个缓冲区(可绘制缓冲区)中绘制。当在可绘制缓冲区中绘制下一帧完成时,缓冲区会进行交换,这样下一帧就变为可查看的,同时下一帧的绘制也开始。这个绘制和交换的循环在动画过程中不断重复。

可查看缓冲区(Viewable)通常被称为前缓冲区或主缓冲区,而可绘制缓冲区(Drawable)则被称为后缓冲区或交换缓冲区。任一缓冲区也被称为刷新缓冲区。

双缓冲极大地提高了动画的质量,因为它能隐藏连续帧之间的过渡。而单缓冲则不然,观众会看到下一个帧在包含当前帧的同一个缓冲区中被绘制出来。其结果可能是令人不快的重影,之所以这样称呼,是因为在绘制下一个图像时,之前的图像仍会残留。

运动的实现离不开物理,这一块内容暂时不进行详细了解

4.6 Viewing Transformation

管理相机位姿(相机在世界坐标系中的位置和朝向)

gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz) ,注意这些坐标都是由世界坐标系描述的
模拟 OpenGL 相机第一次移动到位置 eye = (eyex, eyey, eyez),然后指向 center = (centerx, centery, centerz),并且围绕其视线(line of sight,los)旋转 连接eye到center的线,以便其向上方向是从 up = (upx, upy, upz)


将glTranslatef(0.0, 0.0, -15.0)替换为 gluLookAt(0.0, 0.0, 15.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)

为什么glTranslatef(0.0, 0.0, -15.0)和 gluLookAt(0.0, 0.0, 15.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) 渲染后效果是一样的?
原因:使用函数glTranslatef(0.0, 0.0, -15.0)时的情况,相机和物体都在世界坐标系原点,将物体通过函数平移到了相机的视锥体内
使用函数 gluLookAt(0.0, 0.0, 15.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) 时的情况,物体在世界坐标系原点,将相机平移到了(0,0,15)的位置,物体落到了平移后的相机视锥体内


仅修改相机的center,了解该参数的含义(相机镜头指向的点)


仅修改相机的up,了解该参数的含义(摄像机围绕其视线(z 轴)旋转,因此其向上方向每次都指向沿向上矢量 (upx, upy, upz))

upx=1,相机up方向朝向x轴正方形
相机从原来朝向基础上向右旋转90°

upy为-1,相机up方向朝y轴负方向
相机从原来朝向基础上向左/右旋转180°

4.6.1 Understanding the Viewing Transformation

基础知识铺垫
点积

点积的一个特别有用的应用是:当想要将给定的向量 v 拆分为 v = v1 +v2 时,其中分量 v1 和 v2 分别平行和垂直于另一个给定的非零向量 u。



将上述点积应用到计算相机的up direction上
将up向量分解为 up 1 \text{up}_1 up1 up 2 \text{up}_2 up2、其中 up 1 \text{up}_1 up1与视线los共线, up 2 \text{up}_2 up2在平面p上,为相机的up direction
相机位置 eye = (eyex,eyey,eyez) \text{eye}=\text{(eyex,eyey,eyez)} eye=(eyex,eyey,eyez)
相机“看向” center = (centerx,centery,centerz) \text{center}=\text{(centerx,centery,centerz)} center=(centerx,centery,centerz)
相机up direction: up 2 = (upx,upy,upz) \text{up}_2=\text{(upx,upy,upz)} up2=(upx,upy,upz)

例子:计算每个veiwing transformation的相机up direction
gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz)
gluLookAt(0.0, 0.0, 5.0, 5.0, 0.0, 0.0, 0.0, 1.0, 1.0)

注意:Collectively, the modeling transformations glTranslatef(), glRot
atef() and glScalef() and the viewing transformation gluLookAt() are called modelview transformations.

4.6.2 Simulating a Viewing Transformation with Modeling Transformations

当我们引入 gluLookAt() 时,我们说它模拟了 OpenGL 相机的运动。这是完全正确的。OpenGL 相机永远不会在原点处保留其默认姿势,其镜头指向 -z 方向,顶部沿 +y 方向对齐。换句话说,视锥体(或框)保持在它第一次使用 glFrustum()(或 glOrtho())创建的位置。
也就是做第一帧相机坐标系原点和世界坐标系原点重合

实际上,通过将viewing transformation为等效的modeling transformations序列来模拟viewing transformation。


4.6.3 Orientation and Euler Angles

gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz)
等价于


相机中心eye在世界坐标系中的坐标eye=(eyex,eyey,eyez),通过glTranslatef(-eyex,eyey,-eyez)将相机中心移到世界坐标系原点

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/67331.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Deepseek的RL算法GRPO解读

在本文中&#xff0c;我们将深入探讨Deepseek采用的策略优化方法GRPO&#xff0c;并顺带介绍一些强化学习&#xff08;Reinforcement Learning, RL&#xff09;的基础知识&#xff0c;包括PPO等关键概念。 策略函数&#xff08;policy&#xff09; 在强化学习中&#xff0c; a…

【python】python基于机器学习与数据分析的二手手机特性关联与分类预测(源码+数据集)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;专__注&#x1f448;&#xff1a;专注主流机器人、人工智能等相关领域的开发、测试技术。 python基于机器学习与数据分析的二手手机特性关联与…

手撕Diffusion系列 - 第十一期 - lora微调 - 基于Stable Diffusion(代码)

手撕Diffusion系列 - 第十一期 - lora微调 - 基于Stable Diffusion&#xff08;代码&#xff09; 目录 手撕Diffusion系列 - 第十一期 - lora微调 - 基于Stable Diffusion&#xff08;代码&#xff09;Stable Diffusion 原理图Stable Diffusion的原理解释Stable Diffusion 和Di…

前端【8】HTML+CSS+javascript实战项目----实现一个简单的待办事项列表 (To-Do List)

目录 一、功能需求 二、 HTML 三、CSS 四、js 1、绑定事件与初始设置 2.、绑定事项 &#xff08;1&#xff09;添加操作&#xff1a; &#xff08;2&#xff09;完成操作 &#xff08;3&#xff09;删除操作 &#xff08;4&#xff09;修改操作 3、完整js代码 总结…

vue事件总线(原理、优缺点)

目录 一、原理二、使用方法三、优缺点优点缺点 四、使用注意事项具体代码参考&#xff1a; 一、原理 在Vue中&#xff0c;事件总线&#xff08;Event Bus&#xff09;是一种可实现任意组件间通信的通信方式。 要实现这个功能必须满足两点要求&#xff1a; &#xff08;1&#…

图像处理之HSV颜色空间

目录 1 RGB 的局限性 2 HSV 颜色空间 3 RGB与HSV相互转换 4 HSV颜色模型对图像的色相、饱和度和明度进行调节 5 演示Demo 5.1 开发环境 5.2 功能介绍 5.3 下载地址 参考 1 RGB 的局限性 RGB 是我们接触最多的颜色空间&#xff0c;由三个通道表示一幅图像&#xff0c;分…

【C++高并发服务器WebServer】-9:多线程开发

本文目录 一、线程概述1.1 线程和进程的区别1.2 线程之间共享和非共享资源1.3 NPTL 二、线程操作2.1 pthread_create2.2 pthread_exit2.3 pthread_join2.4 pthread_detach2.5 patch_cancel2.6 pthread_attr 三、实战demo四、线程同步五、死锁六、读写锁七、生产消费者模型 一、…

14-6-1C++STL的list

(一&#xff09;list容器的基本概念 list容器简介&#xff1a; 1.list是一个双向链表容器&#xff0c;可高效地进行插入删除元素 2.list不可以随机存取元素&#xff0c;所以不支持at.(pos)函数与[ ]操作符 &#xff08;二&#xff09;list容器头部和尾部的操作 list对象的默…

21.Word:小赵-毕业论文排版❗【39】

目录 题目​ NO1.2 NO3.4 NO5.6 NO7.8.9 NO10.11.12 题目 NO1.2 自己的论文当中接收老师的修改&#xff1a;审阅→比较→源文档&#xff1a;考生文件夹&#xff1a;Word.docx→修订的文档&#xff1a;考生文件夹&#xff1a;教师修改→确定→接收→接收所有修订将合并之…

深度学习 DAY3:NLP发展史及早期的前馈神经网络(ANN)及多任务学习

NLP发展史 NLP发展脉络简要梳理如下&#xff1a; 2001 - Neural language models&#xff08;神经语言模型&#xff09; 2008 - Multi-task learning&#xff08;多任务学习&#xff09; 2013 - Word embeddings&#xff08;词嵌入&#xff09; 2013 - Neural networks for NL…

全面了解 Web3 AIGC 和 AI Agent 的创新先锋 MelodAI

不管是在传统领域还是 Crypto&#xff0c;AI 都是公认的最有前景的赛道。随着数字内容需求的爆炸式增长和技术的快速迭代&#xff0c;Web3 AIGC&#xff08;AI生成内容&#xff09;和 AI Agent&#xff08;人工智能代理&#xff09;正成为两大关键赛道。 AIGC 通过 AI 技术生成…

54.数字翻译成字符串的可能性|Marscode AI刷题

1.题目 问题描述 小M获得了一个任务&#xff0c;需要将数字翻译成字符串。翻译规则是&#xff1a;0对应"a"&#xff0c;1对应"b"&#xff0c;依此类推直到25对应"z"。一个数字可能有多种翻译方法。小M需要一个程序来计算一个数字有多少种不同的…

RabbitMQ5-死信队列

目录 死信的概念 死信的来源 死信实战 死信之TTl 死信之最大长度 死信之消息被拒 死信的概念 死信&#xff0c;顾名思义就是无法被消费的消息&#xff0c;一般来说&#xff0c;producer 将消息投递到 broker 或直接到queue 里了&#xff0c;consumer 从 queue 取出消息进…

10JavaWeb——SpringBootWeb案例01

前面我们已经讲解了Web前端开发的基础知识&#xff0c;也讲解了Web后端开发的基础(HTTP协议、请求响应)&#xff0c;并且也讲解了数据库MySQL&#xff0c;以及通过Mybatis框架如何来完成数据库的基本操作。 那接下来&#xff0c;我们就通过一个案例&#xff0c;来将前端开发、后…

JAVA 接口、抽象类的关系和用处 详细解析

接口 - Java教程 - 廖雪峰的官方网站 一个 抽象类 如果实现了一个接口&#xff0c;可以只选择实现接口中的 部分方法&#xff08;所有的方法都要有&#xff0c;可以一部分已经写具体&#xff0c;另一部分继续保留抽象&#xff09;&#xff0c;原因在于&#xff1a; 抽象类本身…

ResNeSt: Split-Attention Networks论文学习笔记

这张图展示了一个名为“Split-Attention”的神经网络结构&#xff0c;该结构在一个基数组&#xff08;cardinal group&#xff09;内进行操作。基数组通常指的是在神经网络中处理的一组特征或通道。图中展示了如何通过一系列操作来实现对输入特征的注意力机制。 以下是图中各部…

设计模式Python版 原型模式

文章目录 前言一、原型模式二、原型模式示例三、原型管理器 前言 GOF设计模式分三大类&#xff1a; 创建型模式&#xff1a;关注对象的创建过程&#xff0c;包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。结构型模式&#xff1a;关注类和对…

神经网络的通俗介绍

人工神经网络&#xff0c;是一种模仿人类大脑工作原理的数学模型。人类的大脑是由无数的小“工作站”组成的&#xff0c;每个工作站叫做“神经元”。这些神经元通过“电线”互相连接&#xff0c;负责接收、处理和传递信息。 一、人类大脑神经网络 人类大脑的神经网络大概长这…

OpenEuler学习笔记(八):安装OpenEuler

在VMware Workstation中安装OpenEuler 准备工作 下载并安装VMware Workstation虚拟机软件。前往OpenEuler官网下载OpenEuler系统镜像文件。 创建虚拟机 打开VMware Workstation&#xff0c;点击“创建新的虚拟机”&#xff0c;选择“自定义”&#xff0c;点击“下一步”。选择…

Leetcode::119. 杨辉三角 II

119. 杨辉三角 II 已解答 简单 相关标签 相关企业 给定一个非负索引 rowIndex&#xff0c;返回「杨辉三角」的第 rowIndex 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: rowIndex 3 输出: [1,3,3,1]示例 2: 输入: rowIndex 0…