在游戏开发中,矩阵具有十分重要的地位,但他也只是我们操作点和向量的一个工具,在这里我们使用列优先规则来存储矩阵。在这里矩阵最主要的两个作用是:1. 旋转一个向量或者变换一个坐标点的位置;2. 坐标空间变换。对于第一点,在第2.1向量章节中,我们直接使用了三角函数对向量进行旋转,矩阵则是提供了另一种表示方式。我们知道向量可以表示为坐标空间基向量和的形式,即向量p = ax + by + cz = (1, 0, 0)*a + (0, 1, 0)*b + (0, 0, 1) * c,(a, b, c)就是向量p在x, y, z空间中的坐标如下图,

上面表达式可以写成矩阵相乘的形式:


我们让x、y坐标轴绕z旋转到x'、y'如上图,x'、y'的基向量分别为(cosθ, sinθ, 0)和(-sinθ, cosθ, 0),替换上面的公式的RUD基向量,即得到绕z轴旋转的矩阵为:

其中

同理可以得到绕y轴的矩阵为:
,其中
绕x轴的矩阵为:
,其中 
当绕任意向量u旋转时,

则此时旋转矩阵为:

也可以利用矩阵来计算反射矩阵,根据向量的反射可以得到:

从而得到反射矩阵如下(在《3D游戏引擎设计》一书中,此矩阵有些错误这里进行了修正):

利用矩阵来计算缩放则比较简单,对3x3的矩阵M来讲,只需要将M(0,0)、M(1,1)、M(2,2)矩阵位置处的值进行缩放,即可对向量x,y,z方向进行缩放。上面利用3x3矩阵计算了出了旋转矩阵,当要对空间点位置进行移动时,需要用到矩阵和向量的第四维,此时的向量称为齐次坐标,此时的矩阵形式如下:

矩阵中的(b0, b1, b2)即为在x、y、z方向的偏移。用了这个4x4的矩阵,可以将向量从一个坐标空间转换到另一个坐标空间,这在渲染中是最常用的操作。在美术设计师给到一个模型时,模型中点的位置是相对于模型自己的坐标空间,而游戏世界需要渲染一个模型,会将整个模型放置于世界中的某个位置并带有旋转和缩放,游戏世界所在的空间为世界空间,要渲染一个模型,还需要一个摄像机和投影平面,通过摄像机去看一个物体是需要转换到相机空间的,最后还需要投影到摄像机的近裁剪面,在这里模型转换到世界空间的矩阵为M,世界空间转换到相机空间矩阵为V,相机空间进行投影计算矩阵为P,这就是以后会常听到的MVP矩阵。要真正渲染一个顶点Q,由于矩阵是列优先的,利用矩阵乘法计算坐标空间转换为右乘计算Q' = P * V * M * Q。这些用到的矩阵的实现,会在后面章节详细介绍。下面是4x4矩阵的实现代码:
1 #ifndef _MATRIX_4_X_4_HPP
2 #define _MATRIX_4_X_4_HPP
3
4 #include "Vector3.hpp"
5
6 using namespace std;
7 template <typename T>
8 class Matrix4x4
9 {
10 public:
11 Matrix4x4(
12 T m00, T m01, T m02, T m03,
13 T m10, T m11, T m12, T m13,
14 T m20, T m21, T m22, T m23,
15 T m30, T m31, T m32, T m33
16 );
17 Matrix4x4(T m[16]);
18 Matrix4x4();
19
20 Matrix4x4 &MakeIdentity();
21 void MakeRotation(const Vector3<T> &v, T radian);
22 void MakeTransition(const Vector3<T> & v);
23 void MakeTransition(T x, T y, T z);
24 void MakeScale(const Vector3<T> & v);
25 void MakeScale(T x, T y, T z);
26 void MakeReflect(const Vector3<T> &normal);
27 bool GetInverse(Matrix4x4<T> &out) const;
28 void GetTransposed(Matrix4x4<T> &o) const;
29 Vector3<T> Transform(const Vector3<T> &v) const;
30 Matrix4x4<T> operator*(const Matrix4x4 &m) const;
31 T operator[](int i) const;
32 T operator[](int i);
33 T operator()(int row, int col) const;
34 T operator()(int row, int col);
35
36 union
37 {
38 struct
39 {
40 T m00, m01, m02, m03;
41 T m10, m11, m12, m13;
42 T m20, m21, m22, m23;
43 T m30, m31, m32, m33;
44 };
45
46 T m[16];
47 };
48 };
49
50
51 template <typename T>
52 Matrix4x4<T>::Matrix4x4(
53 T m00, T m01, T m02, T m03,
54 T m10, T m11, T m12, T m13,
55 T m20, T m21, T m22, T m23,
56 T m30, T m31, T m32, T m33
57 ):m00(m00), m01(m01), m02(m02), m03(m03),
58 m10(m10), m11(m11), m12(m12), m13(m13),
59 m20(m20), m21(m21), m22(m22), m23(m23),
60 m30(m30), m31(m31), m32(m32), m33(m33)
61 {
62 }
63
64 template <typename T>
65 Matrix4x4<T>::Matrix4x4(T m[16])
66 {
67 memcpy(this->m, m, sizeof(this->m));
68 }
69
70 template <typename T>
71 Matrix4x4<T>::Matrix4x4()
72 : m00(1), m01(0), m02(0), m03(0),
73 m10(0), m11(1), m12(0), m13(0),
74 m20(0), m21(0), m22(1), m23(0),
75 m30(0), m31(0), m32(0), m33(1)
76 {
77 }
78
79
80 template <typename T>
81 Matrix4x4<T> &Matrix4x4<T>::MakeIdentity()
82 {
83 memset(m, 0, sizeof(m));
84 m[0] = m[5] = m[10] = m[15] = static_cast<T>(1);
85 return *this;
86 }
87
88
89 template <typename T>
90 void Matrix4x4<T>::MakeRotation(const Vector3<T> &v, T radian)
91 {
92 T c = cos(radian);
93 T s = sin(radian);
94 T x2 = v.x * v.x;
95 T y2 = v.y * v.y;
96 T z2 = v.z * v.z;
97 T xy = v.x * v.y;
98 T xz = v.x * v.z;
99 T yz = v.y * v.z;
100
101 m00 = c + (1 - c) * x2; m01 = -v.z * s + (1 - c) * xy; m02 = v.y * s + (1 - c) * xz;
102 m10 = v.z * s + (1 - c) * xy; m11 = c + (1 - c) * y2; m12 = -v.x * s + (1 - c) * yz;
103 m20 = -v.y * s + (1 - c) * xz; m21 = v.x * s + (1 - c) * yz; m22 = c + (1 - c) * z2;
104 }
105
106 template <typename T>
107 void Matrix4x4<T>::MakeTransition(const Vector3<T> & v)
108 {
109 m03 = v.x;
110 m13 = v.y;
111 m23 = v.z;
112 }
113
114 template <typename T>
115 void Matrix4x4<T>::MakeTransition(T x, T y, T z)
116 {
117 m03 = x;
118 m13 = y;
119 m23 = z;
120 }
121
122 template <typename T>
123 void Matrix4x4<T>::MakeScale(T x, T y, T z)
124 {
125 m00 = x;
126 m11 = y;
127 m22 = z;
128 }
129
130 template <typename T>
131 void Matrix4x4<T>::MakeScale(const Vector3<T> &v)
132 {
133 m00 = v.x;
134 m11 = v.y;
135 m22 = v.z;
136 }
137
138 template <typename T>
139 void Matrix4x4<T>::MakeReflect(const Vector3<T> &n)
140 {
141 T x2 = n.x * n.x;
142 T y2 = n.y * n.y;
143 T z2 = n.z * n.z;
144
145 T xy = n.x * n.y;
146 T xz = n.x * n.z;
147 T yz = n.y * n.z;
148
149 m00 = 1 - 2 * x2; m01 = -2 * xy; m02 = -2 * xz;
150 m10 = -2 * xy; m11 = 1 - 2 * y2; m12 = -2 * yz;
151 m20 = -2 * xz; m21 = -2 * yz; m22 = 1 - 2 * z2;
152 }
153
154 template <typename T>
155 bool Matrix4x4<T>::GetInverse(Matrix4x4<T> &out) const
156 {
157 const Matrix4x4 &m = *this;
158
159 T d = (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) -
160 (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
161 (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)) +
162 (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) -
163 (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
164 (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0));
165
166 if (d > -0.00001 && d < 0.00001)
167 return false;
168
169 d = 1 / d;
170
171 out(0, 0) = d * (m(1, 1) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) +
172 m(1, 2) * (m(2, 3) * m(3, 1) - m(2, 1) * m(3, 3)) +
173 m(1, 3) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)));
174 out(0, 1) = d * (m(2, 1) * (m(0, 2) * m(3, 3) - m(0, 3) * m(3, 2)) +
175 m(2, 2) * (m(0, 3) * m(3, 1) - m(0, 1) * m(3, 3)) +
176 m(2, 3) * (m(0, 1) * m(3, 2) - m(0, 2) * m(3, 1)));
177 out(0, 2) = d * (m(3, 1) * (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) +
178 m(3, 2) * (m(0, 3) * m(1, 1) - m(0, 1) * m(1, 3)) +
179 m(3, 3) * (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)));
180 out(0, 3) = d * (m(0, 1) * (m(1, 3) * m(2, 2) - m(1, 2) * m(2, 3)) +
181 m(0, 2) * (m(1, 1) * m(2, 3) - m(1, 3) * m(2, 1)) +
182 m(0, 3) * (m(1, 2) * m(2, 1) - m(1, 1) * m(2, 2)));
183 out(1, 0) = d * (m(1, 2) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) +
184 m(1, 3) * (m(2, 2) * m(3, 0) - m(2, 0) * m(3, 2)) +
185 m(1, 0) * (m(2, 3) * m(3, 2) - m(2, 2) * m(3, 3)));
186 out(1, 1) = d * (m(2, 2) * (m(0, 0) * m(3, 3) - m(0, 3) * m(3, 0)) +
187 m(2, 3) * (m(0, 2) * m(3, 0) - m(0, 0) * m(3, 2)) +
188 m(2, 0) * (m(0, 3) * m(3, 2) - m(0, 2) * m(3, 3)));
189 out(1, 2) = d * (m(3, 2) * (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) +
190 m(3, 3) * (m(0, 2) * m(1, 0) - m(0, 0) * m(1, 2)) +
191 m(3, 0) * (m(0, 3) * m(1, 2) - m(0, 2) * m(1, 3)));
192 out(1, 3) = d * (m(0, 2) * (m(1, 3) * m(2, 0) - m(1, 0) * m(2, 3)) +
193 m(0, 3) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
194 m(0, 0) * (m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2)));
195 out(2, 0) = d * (m(1, 3) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0)) +
196 m(1, 0) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
197 m(1, 1) * (m(2, 3) * m(3, 0) - m(2, 0) * m(3, 3)));
198 out(2, 1) = d * (m(2, 3) * (m(0, 0) * m(3, 1) - m(0, 1) * m(3, 0)) +
199 m(2, 0) * (m(0, 1) * m(3, 3) - m(0, 3) * m(3, 1)) +
200 m(2, 1) * (m(0, 3) * m(3, 0) - m(0, 0) * m(3, 3)));
201 out(2, 2) = d * (m(3, 3) * (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) +
202 m(3, 0) * (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) +
203 m(3, 1) * (m(0, 3) * m(1, 0) - m(0, 0) * m(1, 3)));
204 out(2, 3) = d * (m(0, 3) * (m(1, 1) * m(2, 0) - m(1, 0) * m(2, 1)) +
205 m(0, 0) * (m(1, 3) * m(2, 1) - m(1, 1) * m(2, 3)) +
206 m(0, 1) * (m(1, 0) * m(2, 3) - m(1, 3) * m(2, 0)));
207 out(3, 0) = d * (m(1, 0) * (m(2, 2) * m(3, 1) - m(2, 1) * m(3, 2)) +
208 m(1, 1) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
209 m(1, 2) * (m(2, 1) * m(3, 0) - m(2, 0) * m(3, 1)));
210 out(3, 1) = d * (m(2, 0) * (m(0, 2) * m(3, 1) - m(0, 1) * m(3, 2)) +
211 m(2, 1) * (m(0, 0) * m(3, 2) - m(0, 2) * m(3, 0)) +
212 m(2, 2) * (m(0, 1) * m(3, 0) - m(0, 0) * m(3, 1)));
213 out(3, 2) = d * (m(3, 0) * (m(0, 2) * m(1, 1) - m(0, 1) * m(1, 2)) +
214 m(3, 1) * (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) +
215 m(3, 2) * (m(0, 1) * m(1, 0) - m(0, 0) * m(1, 1)));
216 out(3, 3) = d * (m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) +
217 m(0, 1) * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) +
218 m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0)));
219
220 return true;
221 }
222
223 template <typename T>
224 void Matrix4x4<T>::GetTransposed(Matrix4x4<T> &o) const
225 {
226 o[0] = m[0];
227 o[1] = m[4];
228 o[2] = m[8];
229 o[3] = m[12];
230
231 o[4] = m[1];
232 o[5] = m[5];
233 o[6] = m[9];
234 o[7] = m[13];
235
236 o[8] = m[2];
237 o[9] = m[6];
238 o[10] = m[10];
239 o[11] = m[14];
240
241 o[12] = m[3];
242 o[13] = m[7];
243 o[14] = m[11];
244 o[15] = m[15];
245 }
246
247 template <typename T>
248 Vector3<T> Matrix4x4<T>::Transform(const Vector3<T> &v) const
249 {
250 T w = (m30 * v.x + m31 * v.y + m32 * v.z + m33);
251 T invW = w > 0 ? static_cast<T>(1.0) / w : static_cast<T>(1.0);
252 return Vector3<T>(
253 (m00 * v.x + m01 * v.y + m02 * v.z + m03) * invW,
254 (m10 * v.x + m11 * v.y + m12 * v.z + m13) * invW,
255 (m20 * v.x + m21 * v.y + m22 * v.z + m23) * invW
256 );
257 }
258
259 template <typename T>
260 Matrix4x4<T> Matrix4x4<T>::operator*(const Matrix4x4<T> &m) const
261 {
262 return Matrix4x4<T>(
263 m00 * m.m00 + m01 * m.m10 + m02 * m.m20 + m03 * m.m30,
264 m00 * m.m01 + m01 * m.m11 + m02 * m.m21 + m03 * m.m31,
265 m00 * m.m02 + m01 * m.m12 + m02 * m.m22 + m03 * m.m32,
266 m00 * m.m03 + m01 * m.m13 + m02 * m.m23 + m03 * m.m33,
267
268 m10 * m.m00 + m11 * m.m10 + m12 * m.m20 + m13 * m.m30,
269 m10 * m.m01 + m11 * m.m11 + m12 * m.m21 + m13 * m.m31,
270 m10 * m.m02 + m11 * m.m12 + m12 * m.m22 + m13 * m.m32,
271 m10 * m.m03 + m11 * m.m13 + m12 * m.m23 + m13 * m.m33,
272
273 m20 * m.m00 + m21 * m.m10 + m22 * m.m20 + m23 * m.m30,
274 m20 * m.m01 + m21 * m.m11 + m22 * m.m21 + m23 * m.m31,
275 m20 * m.m02 + m21 * m.m12 + m22 * m.m22 + m23 * m.m32,
276 m20 * m.m03 + m21 * m.m13 + m22 * m.m23 + m23 * m.m33,
277
278 m30 * m.m00 + m31 * m.m10 + m32 * m.m20 + m33 * m.m30,
279 m30 * m.m01 + m31 * m.m11 + m32 * m.m21 + m33 * m.m31,
280 m30 * m.m02 + m31 * m.m12 + m32 * m.m22 + m33 * m.m32,
281 m30 * m.m03 + m31 * m.m13 + m32 * m.m23 + m33 * m.m33
282 );
283 }
284
285 template <typename T>
286 T Matrix4x4<T>::operator[](int i) const
287 {
288 assert(i >= 0 && i < 16);
289 return m[i];
290 }
291
292 template <typename T>
293 T Matrix4x4<T>::operator[](int i)
294 {
295 assert(i >= 0 && i < 16);
296 return m[i];
297 }
298
299
300 template <typename T>
301 T Matrix4x4<T>::operator()(int row, int col) const
302 {
303 assert(row >=0 && row < 4 && col >= 0 && row < 4);
304 return row << 2 + col;
305 }
306 template <typename T>
307 T Matrix4x4<T>::operator()(int row, int col)
308 {
309 assert(row >=0 && row < 4 && col >= 0 && row < 4);
310 return row << 2 + col;
311 }
312
313 template <typename T>
314 ostream &operator<<(ostream &out, const Matrix4x4<T> &m)
315 {
316 for (int i = 0; i < 16; ++i)
317 {
318 out << m[i];
319 if ((i + 1) % 4 == 0)
320 out << endl;
321 else if (i != 15)
322 out << ",";
323
324 }
325 return out;
326 }
327
328 typedef Matrix4x4<float> Matrix4x4f;
329 typedef Matrix4x4<double> Matrix4x4d;
330
331 #endif
参考文献:
《3D数学基础:图形与游戏开发》
《3D游戏与计算机图形学中的数学方法》
《3D游戏引擎设计:实时计算机图形学的应用方法》
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm
我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI
这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub
我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度; 在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/
@作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors 1、什么是behaviors 2、behaviors的工作方式 3、创建behavior 4、导入并使用behavior 5、behavior中所有可用的节点 6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors 1、什么是behaviorsbehaviors是小程序中,用于实现