Unity的Bounds(包围盒)简记

  • 一、Bounds(包围盒)概述
    • 1.什么是包围盒?
    • 2.包围盒的类型
      • 2.1 AABB包围盒(Axis-aligned bounding box)
      • 2.2 包围球(Sphere)
      • 2.3 OBB方向包围盒(Oriented bounding box)
      • 2.4 FDH固定方向凸包(Fixed directions hulls或k-DOP)
      • 2.5 包围盒选择
  • 二、Unity中的Bounds
    • 1.Bounds结构体
      • 1.1 Public Attribute(公告属性)
      • 1.2 Public Functions(公告函数)
  • 三、旋转对Bounds的影响
  • 四、Bounds和碰撞器Collider的区别
  • 五、相关方法
    • 1.多物体Bounds(Encapsulate)
    • 2.计算包围盒的八个顶点
    • 3.绘制bounds方框
    • 4.绘制碰撞器方框
      • 4.1方法一
      • 4.2方法二
    • 5.求两个包围盒之间的距离
    • 6.计算所有包围盒的中心点
  • 参考连接

一、Bounds(包围盒)概述

1.什么是包围盒?

包围盒算法是一种求解离散点集最优包围空间的方法。
基本思想是用体积稍大且特性简单的几何体(称为包围盒)来近似地代替复杂的几何对象。
最常见的包围盒算法有AABB包围盒(Axis-aligned bounding box),包围球(Sphere),方向包围盒OBB(Oriented bounding box),固定方向凸包FDH(Fixed directions hulls或k-DOP)。

2.包围盒的类型

2.1 AABB包围盒(Axis-aligned bounding box)

AABB是应用最早的包围盒。它被定义为包含该对象,且边平行于坐标轴的最小六面体。故描述一个AABB,仅需六个标量。AABB构造比较简单,存储空间小,但紧密性差,尤其对不规则几何形体,冗余空间很大,当对象旋转时,无法对其进行相应的旋转。处理对象是刚性并且是凸的,不适合包含软体变形的复杂的虚拟环境情况。AABB也是比较简单的一类包围盒。但对于沿斜对角方向放置的瘦长形对象,其紧密性较差。由于AABB相交测试的简单性及较好的紧密性,因此得到了广泛的应用,还可以用于软体对象的碰撞检测。

2.2 包围球(Sphere)

包围球被定义为包含该对象的最小的球体。确定包围球,首先需分别计算组成对象的基本几何元素集合中所有元素的顶点的x,y,z坐标的均值以确定包围球的球心,再由球心与三个最大值坐标所确定的点间的距离确定半径r。包围球的碰撞检测主要是比较两球间半径和与球心距离的大小。

2.3 OBB方向包围盒(Oriented bounding box)

OBB是较为常用的包围盒类型。它是包含该对象且相对于坐标轴方向任意的最小的长方体。OBB最大特点是它的方向的任意性,这使得它可以根据被包围对象的形状特点尽可能紧密的包围对象,但同时也使得它的相交测试变得复杂。OBB包围盒比AABB包围盒和包围球更加紧密地逼近物体,能比较显著地减少包围体的个数,从而避免了大量包围体之间的相交检测。但OBB之间的相交检测比AABB或包围球体之间的相交检测更费时。

2.4 FDH固定方向凸包(Fixed directions hulls或k-DOP)

FDH(k-DOP)是一种特殊的凸包,继承了AABB简单性的特点,但其要具备良好的空间紧密度,必须使用足够多的固定方向。被定义为包含该对象且它的所有面的法向量都取自一个固定的方向(k个向量)集合的凸包。FDH比其他包围体更紧密地包围原物体,创建的层次树也就有更少的节点,求交检测时就会减少更多的冗余计算,但相互间的求交运算较为复杂。

2.5 包围盒选择

任何实时三维交互式程序,如果没有碰撞检测,都是没有价值,甚至无法使用的。游戏中最常用的碰撞检测技术莫过于包围盒(bounding volume)碰撞检测。对于以60pfs运行的游戏来说,处理每一帧数据的时间只有0.0167s左右,对于不同的游戏,碰撞检测大概需要占10~30%的时间,也就是说,所有碰撞检测必须在0.002~0.005s内完成,非常巨大的挑战。
因此,任何包围盒都应该满足以下特性:

  1. 快速的碰撞检测;
  2. 能紧密覆盖所包围的对象;
  3. 包围盒应该非常容易计算;
  4. 能方便的旋转和变换坐标;
  5. 低内存占用。

最常见的包围盒有:Sphere,AABB,OBB等,外加一个比较特殊的frustum。Sphere能很好的满足1,3,4,5条,但通常包含了太多无用的空间,容易导致错误的碰撞结果。AABB应该是sphere与obb之间的解决方案,同时兼顾了效率和空间覆盖范围。OBB是三者中精度最高的,但检测代价也是最高的。
最终使用哪一种包围盒,是一个非常痛苦的过程,我们需要在效率和精度之间做出权衡取舍。前几天刚好完成了基本的碰撞检测函数,以下是我的一些测试数据,在一定程度上可以作为参考。纯C#代码实现,没有任何GPU加速,单线程在Q6600上运行。

  • AABB包围盒(Axis-aligned bounding box):100万次测试,1000次碰撞,耗时0.014s。
  • 包围球(Sphere):100万次测试,大约有16000次碰撞,耗时0.016s。
  • OBB方向包围盒(Oriented bounding box):使用传统的separate axis算法,100万次测试,30万次碰撞,耗时0.160s左右。对于没有碰撞的情况,几乎在前6条轴的检测中,就能结束检测,也就是说大约50万次(50%)测试都在检测第七条轴之前结束。
  • Vertical-agliened OBB:普通OBB的特殊版本,只能绕Y轴旋转。100w次测试,同样30万次碰撞,耗时0.08s,几乎比普通OBB快了一倍。
  • Frustum-AABB:使用<< Optimized View Frustum Culling Algorithms for Bounding Boxes >>中的算法,100w次测试,6万次碰撞,耗时0.096s。目前我计算n-vertex和p-vertex的方法是瓶颈,大约0.016s的时间花在计算这两个点上。 相比XNA中的BoundingFrustum.Intersects,同样的测试需要0.5s左右。

(以上均为对随机数据的测试,因此不同包围盒之间的实际碰撞次数并没有可比性,也不代表不同类型间的精度)
显然,AABB是性价比最高的,OBB虽然有较高精度,但相对其计算代价来说,并不划算,可以考虑用多个AABB来近似OBB,或者使用代价相对较低的Vertical-agliened OBB。Sphere看起来简单,但计算涉及到开方(虽然Math.Sqrt会直接编译为fsqrt指令),因此仍然没有AABB快(只需要6条逻辑比较指令)

二、Unity中的Bounds

1.Bounds结构体

unity api对Bounds的解释:

An axis-aligned bounding box, or AABB for short, is a box aligned with coordinate axes and fully enclosing some object. Because the box is never rotated with respect to the axes, it can be defined by just its center and extents, or alternatively by min and max points.

翻译:

  • 轴对齐边框(简称AABB)是与坐标轴对齐并完全包围某个对象的框。 因为方框不会相对于坐标轴旋转,所以可以通过它的中心和范围来定义它,或者通过最小和最大点来定义它。

Unity用Bounds这个结构体struct来描述AABB包围盒,获取一个物体AABB包围盒的API有三种:RenderColliderMesh

  • Render:GetComponent<Renderer>().bounds—世界坐标
  • Collider:GetComponent<Collider>().bounds—世界坐标
  • Mesh:GetComponent<MeshFilter>().bounds—本地坐标

    把Mesh.bounds本地坐标换算成世界坐标bounds:

    var centerPoint = transform.TransformPoint(bounds.center);
    Bounds newBounds = new Bounds(centerPoint, bounds.size);
    

注意:不管是2D还是3D碰撞以及精灵和都是有bounds属性的。
总结:幸亏有了这个结构体,在实际开发中适当的使用包围盒会省去很多麻烦,做为结构体他和Vector3一样是不允许为空的。在一些属性中他是只读的。

1.1 Public Attribute(公告属性)

  • center:边界盒的中心(世界坐标);
  • extents:边界框的范围,总是size的一半;
  • max:(世界坐标)边界盒的最大点,这个值总是等于center+extents;
  • min:(世界坐标)边界盒的最小点,这个值总是等于center-extents;
  • size:边界盒的总大小。

我们不能直接修改Bounds结构体里头的centersize属性都不能直接设置。
我们通过画线的方式分别看一下各个参数在预制体上的位置。

Bounds bounds = this.GetComponent<Collider>().bounds;
Debug.DrawLine(bounds.center, bounds.center + bounds.extents, Color.red);


我们可以看到这个向量的长度是从中心点到右上角的长度。
由于extentssize的一半,所以我们这样画size

//得到左下角的位置
Vector3 p1 = bounds.center - bounds.extents;
Debug.DrawLine(p1, p1 + bounds.size, Color.green);


我们可以看到size的长度刚好是从左下角到右上角的长度。
然后我们分别画出最小值和最大值和中心点的连线。

Debug.DrawLine(bounds.center,  bounds.min, Color.gray);
Debug.DrawLine(bounds.center, bounds.max, Color.cyan);


由此可以看出最小值在左下角,最大值在右上角。

1.2 Public Functions(公告函数)

  • Encapsulate:重新计算最大最小点;
  • Contains:可判断点是否包含在边界框内(世界坐标)如我们需判断你是否点击了某个精灵则可以用Contains()
  • SetMinMax:设置边界盒的最小最大值;
  • SqrDistance:点和该边界盒之间的最小平方距离;
  • IntersectRay:射线与改边界盒相交吗?
  • Intersects:与另一个边界相交吗?比如我们需要判断两个精灵是否有重叠在一起则就可以使用Intersects()

三、旋转对Bounds的影响

我们对上面的小方块旋转:

旋转之后我们发现这个最小值最大值不再是小方块的左下角右上角
换言之他并不是和自身的坐标轴对齐
于是,我尝试着画出这个小方块的Bounds:

//后左下角
Vector3 backBottomLeft = bounds.min;
///后右下角
Vector3 backBottomRight = backBottomLeft + new Vector3(bounds.size.x, 0, 0);
///前左下角
Vector3 forwardBottomLeft = backBottomLeft + new Vector3(0, 0, bounds.size.z);
///前右下角
Vector3 forwardBottomRight = backBottomLeft + new Vector3(bounds.size.x, 0, bounds.size.z);
///后右上角
Vector3 backTopRight = backBottomLeft + new Vector3(bounds.size.x, bounds.size.y, 0);
///前左上角
Vector3 forwardTopLeft = backBottomLeft + new Vector3(0, bounds.size.y, bounds.size.z);
///后左上角
Vector3 backTopLeft = backBottomLeft + new Vector3(0, bounds.size.y, 0);
///前右上角
Vector3 forwardTopRight = bounds.max;Debug.DrawLine(bounds.min, backBottomRight, Color.red);
Debug.DrawLine(backBottomRight, forwardBottomRight, Color.red);
Debug.DrawLine(forwardBottomRight, forwardBottomLeft, Color.red);
Debug.DrawLine(forwardBottomLeft, bounds.min, Color.red);Debug.DrawLine(bounds.min, backTopLeft, Color.red);
Debug.DrawLine(backBottomRight, backTopRight, Color.red);
Debug.DrawLine(forwardBottomRight, bounds.max, Color.red);
Debug.DrawLine(forwardBottomLeft, forwardTopLeft, Color.red);Debug.DrawLine(backTopRight, backTopLeft, Color.red);
Debug.DrawLine(backTopLeft, forwardTopLeft, Color.red);
Debug.DrawLine(forwardTopLeft, bounds.max, Color.red);
Debug.DrawLine(bounds.max, backTopRight, Color.red);

运行结果如下:
当小方块完全不做旋转时,本地坐标轴和世界坐标轴重合;

旋转45度之后,

注:红框是我们画出的小方块的Bounds,
我们发现小方块的Bounds没有随着小方块旋转,但是它仍然完全包裹着小方块
即是:它是与世界坐标轴对齐,完全包围的对象是它自身的预制体

四、Bounds和碰撞器Collider的区别

  • 碰撞器Collider的方框始终跟着模型旋转移动,缩放跟着模型的,只要模型不缩放它也不缩放。
    属于obb包围盒:他是有向的;检测精度较好
  • Bounds跟随模型移动,而不会跟模型着旋转,而是随着模型旋转而缩放变大变小,始终包裹模型。
    属于aabb包围盒:他是无向的;检测精度较差

五、相关方法

1.多物体Bounds(Encapsulate)

计算多物体Bounds,则要遍历所有子物体,然后调用Encapsulate方法来计算。

Bounds bounds;
Renderer[] renderers = model.GetComponentsInChildren<Renderer>();
for (int i = 0; i < renderers.Length; i++)
{bounds.Encapsulate(renderers[i].bounds);
}

2.计算包围盒的八个顶点

center = bounds.center;
ext = bounds.extents;float deltaX = Mathf.Abs(ext.x);
float deltaY = Mathf.Abs(ext.y);
float deltaZ = Mathf.Abs(ext.z);#region 获取AABB包围盒顶点
points = new Vector3[8];
points[0] = center + new Vector3(-deltaX, deltaY, -deltaZ);        // 上前左(相对于中心点)
points[1] = center + new Vector3(deltaX, deltaY, -deltaZ);         // 上前右
points[2] = center + new Vector3(deltaX, deltaY, deltaZ);          // 上后右
points[3] = center + new Vector3(-deltaX, deltaY, deltaZ);         // 上后左points[4] = center + new Vector3(-deltaX, -deltaY, -deltaZ);       // 下前左
points[5] = center + new Vector3(deltaX, -deltaY, -deltaZ);        // 下前右
points[6] = center + new Vector3(deltaX, -deltaY, deltaZ);         // 下后右
points[7] = center + new Vector3(-deltaX, -deltaY, deltaZ);        // 下后左
#endregion

3.绘制bounds方框

/// <summary> 绘制Bounds方框 </summary>
/// <param name="bounds"></param>
/// <param name="color"></param>
/// <param name="offsetSize"></param>
/// <param name="duration"></param>
public static void DrawBoundBoxLine(Bounds bounds, Color color = default(Color), float offsetSize = 1f, float duration = 0.1f)
{//先计算出包围盒8个点Vector3[] points = new Vector3[8];var width_x = bounds.size.x * offsetSize;var hight_y = bounds.size.y * offsetSize;var length_z = bounds.size.z * offsetSize;var LeftBottomPoint = bounds.min;var rightUpPoint = bounds.max;var centerPoint = bounds.center;var topPoint = new Vector3(centerPoint.x, centerPoint.y + hight_y / 2, centerPoint.z);var bottomPoint = new Vector3(centerPoint.x, centerPoint.y - hight_y * 0.5f, centerPoint.z);points[0] = LeftBottomPoint + Vector3.right * width_x;points[1] = LeftBottomPoint + Vector3.up * hight_y;points[2] = LeftBottomPoint + Vector3.forward * length_z;points[3] = rightUpPoint - Vector3.right * width_x;points[4] = rightUpPoint - Vector3.up * hight_y;points[5] = rightUpPoint - Vector3.forward * length_z;points[6] = LeftBottomPoint;points[7] = rightUpPoint;Debug.DrawLine(LeftBottomPoint, points[0], color, duration);Debug.DrawLine(LeftBottomPoint, points[1], color, duration);Debug.DrawLine(LeftBottomPoint, points[2], color, duration);Debug.DrawLine(rightUpPoint, points[3], color, duration);Debug.DrawLine(rightUpPoint, points[4], color, duration);Debug.DrawLine(rightUpPoint, points[5], color, duration);Debug.DrawLine(points[1], points[3], color, duration);Debug.DrawLine(points[2], points[4], color, duration);Debug.DrawLine(points[0], points[5], color, duration);Debug.DrawLine(points[2], points[3], color, duration);Debug.DrawLine(points[0], points[4], color, duration);Debug.DrawLine(points[1], points[5], color, duration);
}

4.绘制碰撞器方框

4.1方法一

/// <summary> 绘制boxCollider的绿色方框 </summary>
/// <param name="color"></param>
void DrawGizmosOnRunTime(Color color)
{var boxCollider = GetComponent<BoxCollider>();Gizmos.color = color;Matrix4x4 rotationMatrix = Matrix4x4.TRS(boxCollider.transform.position, boxCollider.transform.rotation, boxCollider.transform.lossyScale);Gizmos.matrix = rotationMatrix;Gizmos.DrawWireCube(boxCollider.center, boxCollider.size);
}
void OnDrawGizmos()
{DrawGizmosOnRunTime(Color.red);
}

4.2方法二

/// <summary> 绘制boxCollider的绿色方框 </summary>
/// <param name="boxCollider"></param>
/// <param name="color"></param>
/// <param name="offsetSize"></param>
public static void DrawOnGameViewRuntime(BoxCollider boxCollider, Color color = default(Color), float offsetSize = 1f)
{  float width = 0.1f;Vector3 rightDir = boxCollider.transform.right.normalized;Vector3 forwardDir = boxCollider.transform.forward.normalized;Vector3 upDir = boxCollider.transform.up.normalized;Vector3 center = boxCollider.transform.position + boxCollider.center;Vector3 size = boxCollider.size * offsetSize;size.x *= boxCollider.transform.lossyScale.x;size.y *= boxCollider.transform.lossyScale.y;size.z *= boxCollider.transform.lossyScale.z;Debug.DrawLine(center + upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, center + upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, color);Debug.DrawLine(center - upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, center - upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, color);Debug.DrawLine(center + upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, center - upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, color);Debug.DrawLine(center + upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, center - upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, color);Debug.DrawLine(center + upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, center + upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, color);Debug.DrawLine(center - upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, center - upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, color);Debug.DrawLine(center + upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, center - upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, color);Debug.DrawLine(center + upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, center - upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, color);Debug.DrawLine(center + upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, center + upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, color);Debug.DrawLine(center - upDir * size.y / 2f + rightDir * size.x / 2f + forwardDir * size.z / 2f, center - upDir * size.y / 2f + rightDir * size.x / 2f - forwardDir * size.z / 2f, color);Debug.DrawLine(center + upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, center + upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, color);Debug.DrawLine(center - upDir * size.y / 2f - rightDir * size.x / 2f + forwardDir * size.z / 2f, center - upDir * size.y / 2f - rightDir * size.x / 2f - forwardDir * size.z / 2f, color);
}

5.求两个包围盒之间的距离

// Distance between two ClosestPointOnBounds
// this is needed in cases where entites are really big. in those cases,
// we can't just move to entity.transform.position, because it will be
// unreachable. instead we have to go the closest point on the boundary.
//
// Vector3.Distance(a.transform.position, b.transform.position):
//    _____        _____
//   |     |      |     |
//   |  x==|======|==x  |
//   |_____|      |_____|
//
//
// Utils.ClosestDistance(a.collider, b.collider):
//    _____        _____
//   |     |      |     |
//   |     |x====x|     |
//   |_____|      |_____|
//
public static float ClosestDistance(Collider a, Collider b)
{return Vector3.Distance(a.ClosestPointOnBounds(b.transform.position),b.ClosestPointOnBounds(a.transform.position));
}

6.计算所有包围盒的中心点

计算出多个Bounds的中心点。

[MenuItem ("MyMenu/Do Test")]
static void Test ()
{Transform parent = Selection.activeGameObject.transform;Vector3 postion = parent.position;Quaternion rotation = parent.rotation;Vector3 scale = parent.localScale;parent.position = Vector3.zero;parent.rotation = Quaternion.Euler(Vector3.zero);parent.localScale = Vector3.one;Vector3 center = Vector3.zero;Renderer[] renders = parent.GetComponentsInChildren<Renderer>();foreach (Renderer child in renders){center += child.bounds.center;   }center /= parent.GetComponentsInChildren<Transform>().Length; Bounds bounds = new Bounds(center,Vector3.zero);foreach (Renderer child in renders){bounds.Encapsulate(child.bounds);   }parent.position = postion;parent.rotation = rotation;parent.localScale = scale;foreach(Transform t in parent){t.position = t.position -  bounds.center;}parent.transform.position = bounds.center + parent.position;
}

参考连接

  1. https://blog.csdn.net/SmillCool/article/details/126708371
  2. https://blog.csdn.net/weixin_42977419/article/details/100045078
  3. https://blog.csdn.net/cscscsliqi/article/details/80405059
  4. https://blog.csdn.net/Windgs_YF/article/details/87884884
  5. https://blog.csdn.net/u013628121/article/details/128117992
  6. https://blog.csdn.net/sinat_25415095/article/details/104588989

Unity的Bounds(包围盒)简记相关推荐

  1. Bounds(包围盒)概述与AABB包围盒应用

    Bounds(包围盒)概述与应用 ==转载标明出处== 1.包围盒描述(摘至百度百科): 1.1 什么是包围盒?包围盒算法是一种求解离散点集最优包围空间的方法.基本思想是用体积稍大且特性简单的几何体( ...

  2. Unity使用bounds绘制不规则图形边框

    Unity使用bounds绘制不规则图形边框 for (int i = 0; i < screenList.Count; i++) { if (screenList[i].activeSelf ...

  3. Unity3d bounds包围盒 和collider碰撞器区别

    Bounds 外包围盒 Bounds 叫作外包围盒.边界框.外扩矩形.是struct 结构体.而我们获得Bounds的主要途径有三种:Render,Collider,Mesh. Render.boun ...

  4. NX/UG二次开发—3D几何—包围盒相交检测(转载)

    一:包围盒介绍 包围盒是指能够包容物体的三维立方体或者二维长方形,是包围体的一种,常常用于模型的碰撞检测.包围体主要包括球体.轴对齐包围盒(AABB).有向包围盒(OBB)和凸包(Convex Hul ...

  5. unity如何得到所有子对象_Unity3D研究院之自动计算所有子对象包围盒(六)

    蹦蹦呛 说: 雨松大大超级棒棒,看了雨松大大的第二版游戏开发,很细节,都是一些底层.超级棒. 林会亮 说: 我是新手,请问这个脚本完成需要什么条件?(是否需要继承editor或者继承其他) 早上也用编 ...

  6. ❤️UNITY实战进阶-OBB包围盒详解-6

    ❤️UNITY实战进阶-三维AABB包围盒详解-6_欲望如海水,越喝越渴.-CSDN博客前言 碰撞检测问题在虚拟现实.计算机辅助设计与制造.游戏.机器人等方面都有着广泛的应用,而包围盒算法是进行碰撞检 ...

  7. Unity录屏功能插件NatCorder使用简记

    Unity录屏功能插件NatCorder使用简记 简单介绍 插件下载 使用简介 代码 参考链接 简单介绍 NatCorder 是一个轻量级且易于使用的全功能视频录制 API,适用于 iOS.Andro ...

  8. Unity插件NativeGallery拉取手机相册的使用简记

    Unity插件NativeGallery拉取手机相册的使用简记 拉取手机相册 文档摘要 1. 关于 2. 使用设置 3.常见问题解答 项目示例 资源链接 拉取手机相册 项目中使用到了拉取手机相册的功能 ...

  9. Unity webgl 版本崩溃提示Memory access out of bounds 系列问题巨坑

    如上图所示,这真的是个巨坑,只有火狐浏览器可以正常打开,其他浏览器都报上面的错误,百度,翻墙,查找各种办法解决之后无果,只是得出一个结论,有N种原因都可能导致这个问题的出现. 既然不知道问题的原因,那 ...

最新文章

  1. NandFlash详述【转】
  2. Istio 首次安全评估结果公布
  3. .NET Core使用微软AI认知服务识别文字语言
  4. layui table数据渲染页面+筛选医生+在筛选日期一条龙2
  5. 年底各类年会邀请函也要美美的设计
  6. C#串口通信工作笔记0001---上位机开发_嵌入式_串口助手_收发数据开发
  7. 如何将微商管理模式流程化
  8. scrapy基础知识之防止爬虫被反的几个策略::
  9. C#基础精华05(正则表达式,)
  10. win8.1桌面上快捷方式的箭头
  11. 斯特灵公式求阶乘c语言,斯特林公式求阶乘
  12. 第一象限直线插补程序 c语言,直线插补算法流程(求助四个象限的直线插补程序)...
  13. 树莓派安装python3.5_一树 - 神奇宝贝百科,关于宝可梦的百科全书
  14. 自然人机交互到底“自然”在哪儿?
  15. 上海市医药学校计算机房,上海市医药学校校内比价文件综合楼三楼机房信息发布及广播配套.DOC...
  16. 在微信H5网页中获取用户基本信息
  17. mysql general bin区别_MySQL_Mysql常见问题集锦,1,utf8_bin跟utf8_general_ci的区别 - phpStudy...
  18. 32位/64位系统,jdk32位,64位,32/64位jdk编译出来的class和eclipse 32位和64位
  19. outlook计算机应用基础,计算机应用基础Outlook.doc
  20. 国际计算机网络与信息安全博览会,2018中国(成都)国际计算机网络及信息安全展览会暨论坛...

热门文章

  1. 九、系统的软中断导致CPU使用率升高,我该怎么办?
  2. 中国版GDPR《个人信息安全规范》解读:国内企业如何保障信息安全?
  3. Linux vsftp
  4. 庆阳市西峰区中小学武术教学开展现状及应对措施-4
  5. xampp linux教程,xampp for linux
  6. JAVA微信小程序小说电子书阅读系统毕业设计 开题报告
  7. 1.1 命题逻辑 笔记
  8. 每日学习 与 每日未知
  9. android基于ffmpeg本地视频、在线视频、直播播放器 支持rtmp、rtsp、http等协议
  10. python imshow调整比例_如何在不拉伸图像的情况下更改matplotlib中imshow的比例?