From c60a1ad4f6aa4904e80280586b440a584b5ff061 Mon Sep 17 00:00:00 2001 From: Normand Briere <nbriere@noware.ca> Date: Mon, 22 Apr 2019 15:17:45 -0400 Subject: [PATCH] Refactoring phase 2 --- Geometry.java | 2 VehicleDemo.java | 8 MorphNode.java | 2 SwitchNode.java | 2 Merge.java | 2 GLShapeDrawer.java | 12 GenericJoint.java | 20 +- ScriptNode.java | 2 cMesh.java | 2 iCameraPane.java | 6 FrameSelector.java | 2 TriMesh.java | 199 +----------------------- CameraPane.java | 194 ++++++++++++++++++++++++ PhysicsNode.java | 2 cSpring.java | 4 ParticleNode.java | 4 16 files changed, 246 insertions(+), 217 deletions(-) diff --git a/CameraPane.java b/CameraPane.java index 36fbe8d..c4bdcc2 100644 --- a/CameraPane.java +++ b/CameraPane.java @@ -192,6 +192,11 @@ /// INTERFACE + public boolean IsBoxMode() + { + return BOXMODE; + } + public void ClearDepth() { GetGL().glClear(GetGL().GL_DEPTH_BUFFER_BIT); @@ -566,6 +571,195 @@ } } + /** + * <code>draw</code> renders a <code>TriMesh</code> object including + * it's normals, colors, textures and vertices. + * + * @see Renderer#draw(TriMesh) + * @param tris + * the mesh to render. + */ + public void DrawParticles(TriMesh geo, Object3D shape, boolean selected, boolean rotate) // TriMesh tris) + { + CameraPane display = this; + + float r = display.modelParams0[0]; + float g = display.modelParams0[1]; + float b = display.modelParams0[2]; + float opacity = display.modelParams5[1]; + + //final GL gl = GLU.getCurrentGL(); + GL gl = display.GetGL(); // getGL(); + + FloatBuffer vertBuf = geo.vertBuf; + + int v = vertBuf.capacity(); + + int count = 0; + + boolean cf = gl.glIsEnabled(gl.GL_CULL_FACE); + gl.glEnable(gl.GL_CULL_FACE); + // gl.glScalef(1.0f/1024,1.0f/1024,1.0f/1024); + for (int i=0; i<v/3; i++) + { + int index3 = i*3; + + if (geo.sizeBuf.get(index3+1) == 0) + continue; + + count++; + + int index4 = i*4; + + float tx = vertBuf.get(index3); + float ty = vertBuf.get(index3+1); + float tz = vertBuf.get(index3+2); + + // if (tx == 0 && ty == 0 && tz == 0) + // continue; + + gl.glMatrixMode(gl.GL_TEXTURE); + gl.glPushMatrix(); + + float[] texmat = geo.texmat; + texmat[12] = texmat[13] = texmat[14] = i; + + gl.glMultMatrixf(texmat, 0); + + gl.glMatrixMode(gl.GL_MODELVIEW); + gl.glPushMatrix(); + + gl.glTranslatef(tx,ty,tz); + + if (rotate) + gl.glRotatef(i, 0, 1, 0); + + float size = geo.sizeBuf.get(index3) / 100; + gl.glScalef(size,size,size); + + float cr = geo.colorBuf.get(index4); + float cg = geo.colorBuf.get(index4+1); + float cb = geo.colorBuf.get(index4+2); + float ca = geo.colorBuf.get(index4+3); + + display.modelParams0[0] = r * cr; + display.modelParams0[1] = g * cg; + display.modelParams0[2] = b * cb; + + display.modelParams5[1] = opacity * ca; + + gl.glProgramEnvParameter4fvARB(gl.GL_FRAGMENT_PROGRAM_ARB, 0, display.modelParams0, 0); + gl.glProgramEnvParameter4fvARB(gl.GL_FRAGMENT_PROGRAM_ARB, 5, display.modelParams5, 0); + + RandomNode.globalseed = (int)geo.sizeBuf.get(index3+2); // i; + RandomNode.globalseed2 = RandomNode.globalseed; + +// gl.glColor4f(cr,cg,cb,ca); + // gl.glScalef(1024/16,1024/16,1024/16); + shape.Draw/*Node*/(display,null,selected,false); // blocked + // gl.glScalef(16.0f/1024,16.0f/1024,16.0f/1024); + //gl.glTranslatef(-tx,-ty,-tz); + gl.glPopMatrix(); + + gl.glMatrixMode(gl.GL_TEXTURE); + gl.glPopMatrix(); + } + // gl.glScalef(1024,1024,1024); + if (!cf) + gl.glDisable(gl.GL_CULL_FACE); + + display.modelParams0[0] = r; + display.modelParams0[1] = g; + display.modelParams0[2] = b; + + display.modelParams5[1] = opacity; + + gl.glProgramEnvParameter4fvARB(gl.GL_FRAGMENT_PROGRAM_ARB, 0, display.modelParams0, 0); + gl.glProgramEnvParameter4fvARB(gl.GL_FRAGMENT_PROGRAM_ARB, 5, display.modelParams5, 0); + + gl.glMatrixMode(gl.GL_MODELVIEW); + +// System.err.println("total = " + v/3 + "; displayed = " + count); + if (true) + return; + +//// if (!tris.predraw(this)) +//// { +//// return; +//// } +//// if (Debug.stats) +//// { +//// StatCollector.addStat(StatType.STAT_TRIANGLE_COUNT, tris.getTriangleCount()); +//// StatCollector.addStat(StatType.STAT_VERTEX_COUNT, tris.getVertexCount()); +//// StatCollector.addStat(StatType.STAT_GEOM_COUNT, 1); +//// } +//// +//// if (tris.getDisplayListID() != -1) +//// { +//// renderDisplayList(tris); +//// return; +//// } +//// +//// if (!generatingDisplayList) +//// { +//// applyStates(tris.states, tris); +//// } +//// if (Debug.stats) +//// { +//// StatCollector.startStat(StatType.STAT_RENDER_TIMER); +//// } +//// boolean transformed = doTransforms(tris); +// +// int glMode = GL.GL_TRIANGLES; +// switch (getMode()) +// { +// case Triangles: +// glMode = GL.GL_TRIANGLES; +// break; +// case Strip: +// glMode = GL.GL_TRIANGLE_STRIP; +// break; +// case Fan: +// glMode = GL.GL_TRIANGLE_FAN; +// break; +// } +// +// if (!predrawGeometry(gl)) +// { +// // make sure only the necessary indices are sent through on old +// // cards. +// IntBuffer indices = this.getIndexBuffer(); +// if (indices == null) +// { +// logger.severe("missing indices on geometry object: " + this.toString()); +// } else +// { +// indices.rewind(); +// indices.limit(this.getMaxIndex()); +// +// gl.glDrawElements(glMode, indices.limit(), GL.GL_UNSIGNED_INT, indices); // TODO Check <count> and assumed <type> of GL_UNSIGNED_INT +// +// indices.clear(); +// } +// } else +// { +// gl.glDrawElements(glMode, this.getIndexBuffer().limit(), +// GL.GL_UNSIGNED_INT, 0); +// } +// +//// postdrawGeometry(tris); +//// if (transformed) +//// { +//// undoTransforms(tris); +//// } +//// +//// if (Debug.stats) +//// { +//// StatCollector.endStat(StatType.STAT_RENDER_TIMER); +//// } +//// tris.postdraw(this); + } + /// INTERFACE void SetColor(Object3D obj, Vertex p0) diff --git a/FrameSelector.java b/FrameSelector.java index 91ff1ec..d811fba 100644 --- a/FrameSelector.java +++ b/FrameSelector.java @@ -16,7 +16,7 @@ frame = 0; } - void DrawNode(CameraPane display, Object3D /*Composite*/ root, boolean selected) + void DrawNode(iCameraPane display, Object3D /*Composite*/ root, boolean selected) { while (realframe == 0) { diff --git a/GLShapeDrawer.java b/GLShapeDrawer.java index f516e61..38fb421 100644 --- a/GLShapeDrawer.java +++ b/GLShapeDrawer.java @@ -136,13 +136,13 @@ } private static float[] glMat = new float[16]; - static public void drawOpenGL(CameraPane display, Transform trans, CollisionShape shape, Vector3f color, int debugMode) { + static public void drawOpenGL(iCameraPane display, Transform trans, CollisionShape shape, Vector3f color, int debugMode) { ObjectPool<Transform> transformsPool = ObjectPool.get(Transform.class); ObjectPool<Vector3f> vectorsPool = ObjectPool.get(Vector3f.class); //System.out.println("shape="+shape+" type="+BroadphaseNativeTypes.forValue(shape.getShapeType())); - GL gl = display.getGL(); + GL gl = display.GetGL(); gl.glPushMatrix(); trans.getOpenGLMatrix(glMat); @@ -550,9 +550,9 @@ private static Map<SphereKey, Integer> sphereDisplayLists = new HashMap<SphereKey, Integer>(); private static SphereKey sphereKey = new SphereKey(); - static public void drawSphere(CameraPane display, float radius, int slices, int stacks) + static public void drawSphere(iCameraPane display, float radius, int slices, int stacks) { - GL gl = display.getGL(); + GL gl = display.GetGL(); sphereKey.radius = radius; Integer glList = sphereDisplayLists.get(sphereKey); @@ -622,9 +622,9 @@ private static Map<CylinderKey, Integer> cylinderDisplayLists = new HashMap<CylinderKey, Integer>(); private static CylinderKey cylinderKey = new CylinderKey(); - static public void drawCylinder(CameraPane display, float radius, float halfHeight, int upAxis) + static public void drawCylinder(iCameraPane display, float radius, float halfHeight, int upAxis) { - GL gl = display.getGL(); + GL gl = display.GetGL(); gl.glPushMatrix(); switch (upAxis) diff --git a/GenericJoint.java b/GenericJoint.java index b6d18be..90f9509 100644 --- a/GenericJoint.java +++ b/GenericJoint.java @@ -314,7 +314,7 @@ bRep = null; } - void DrawNode(CameraPane display, Object3D /*Composite*/ root, boolean selected) // ?? + void DrawNode(iCameraPane display, Object3D /*Composite*/ root, boolean selected) // ?? { // super.DrawNode(display,root,selected); @@ -451,9 +451,9 @@ int startvertex; int currentobject; - public void renderme(CameraPane display) + public void renderme(iCameraPane display) { - GL gl = display!=null?display.getGL():null; + GL gl = display!=null?display.GetGL():null; // gl0 = gl; if (GetDynamicsWorld() != null) @@ -796,9 +796,9 @@ } } - public void drawCube(CameraPane display, float extent) + public void drawCube(iCameraPane display, float extent) { - GL gl = display.getGL(); + GL gl = display.GetGL(); extent = extent * 0.5f; @@ -838,7 +838,7 @@ private /*static*/ float[] glMat = new float[16]; - public void drawOpenGL(CameraPane display, Transform trans, CollisionShape shape, Vector3f color, int debugMode) + public void drawOpenGL(iCameraPane display, Transform trans, CollisionShape shape, Vector3f color, int debugMode) { GL gl = null; // display.getGL(); @@ -1522,9 +1522,9 @@ private static Map<SphereKey, Integer> sphereDisplayLists = new HashMap<SphereKey, Integer>(); private static SphereKey sphereKey = new SphereKey(); - public void drawSphere(CameraPane display, float radius, int slices, int stacks) + public void drawSphere(iCameraPane display, float radius, int slices, int stacks) { - GL gl = display.getGL(); + GL gl = display.GetGL(); sphereKey.radius = radius; Integer glList = sphereDisplayLists.get(sphereKey); @@ -1594,9 +1594,9 @@ private static Map<CylinderKey, Integer> cylinderDisplayLists = new HashMap<CylinderKey, Integer>(); private static CylinderKey cylinderKey = new CylinderKey(); - public void drawCylinder(CameraPane display, float radius, float halfHeight, int upAxis) + public void drawCylinder(iCameraPane display, float radius, float halfHeight, int upAxis) { - GL gl = display.getGL(); + GL gl = display.GetGL(); gl.glPushMatrix(); switch (upAxis) diff --git a/Geometry.java b/Geometry.java index 15468cc..13f98a8 100755 --- a/Geometry.java +++ b/Geometry.java @@ -75,7 +75,7 @@ { static final long serialVersionUID = 0; - abstract void DrawParticles(CameraPane display, Object3D geo, boolean selected, boolean rotate); + abstract void DrawParticles(iCameraPane display, Object3D geo, boolean selected, boolean rotate); private static final Logger logger = Logger.getLogger(Geometry.class.getName()); // private static final long serialVersionUID = 1; diff --git a/Merge.java b/Merge.java index 1c276fb..aa47522 100644 --- a/Merge.java +++ b/Merge.java @@ -135,7 +135,7 @@ // ObjectArrayList<Transform> initialmatrices; - void DrawNode(CameraPane display, Object3D /*Composite*/ root, boolean selected) // ?? + void DrawNode(iCameraPane display, Object3D /*Composite*/ root, boolean selected) // ?? { //if (support == null) // System.err.println("DrawNode Merge # " + ((Mocap)object).frame); diff --git a/MorphNode.java b/MorphNode.java index c783c97..01079dc 100644 --- a/MorphNode.java +++ b/MorphNode.java @@ -42,7 +42,7 @@ morphobject.count = 1; // hide } - void DrawNode(CameraPane display, Object3D /*Composite*/ root, boolean selected) + void DrawNode(iCameraPane display, Object3D /*Composite*/ root, boolean selected) { //System.err.println("Frame # " + frame); diff --git a/ParticleNode.java b/ParticleNode.java index e05819c..dcf5821 100644 --- a/ParticleNode.java +++ b/ParticleNode.java @@ -344,9 +344,9 @@ } } - void DrawNode(CameraPane display, Object3D /*Composite*/ root, boolean selected) // ?? + void DrawNode(iCameraPane display, Object3D /*Composite*/ root, boolean selected) // ?? { - if (display.DrawMode() == display.SELECTION || display.BOXMODE) + if (display.DrawMode() == display.SELECTION || display.IsBoxMode()) return; // hum... Object3D geo = test; diff --git a/PhysicsNode.java b/PhysicsNode.java index 97369ee..77051fd 100644 --- a/PhysicsNode.java +++ b/PhysicsNode.java @@ -108,7 +108,7 @@ float totalms = 0; - void drawSelf(CameraPane display, Object3D /*Composite*/ root, boolean selected, boolean blocked) + void drawSelf(iCameraPane display, Object3D /*Composite*/ root, boolean selected, boolean blocked) { if (Globals.isLIVE() && live && display.DrawMode() == display.SHADOW) // FUCK { diff --git a/ScriptNode.java b/ScriptNode.java index d341a50..a856be3 100644 --- a/ScriptNode.java +++ b/ScriptNode.java @@ -1785,7 +1785,7 @@ return live; } - void DrawNode(CameraPane display, Object3D /*Composite*/ root, boolean selected) + void DrawNode(iCameraPane display, Object3D /*Composite*/ root, boolean selected) { if (CameraPane.ABORTED) { diff --git a/SwitchNode.java b/SwitchNode.java index 0297c96..b06c2aa 100644 --- a/SwitchNode.java +++ b/SwitchNode.java @@ -46,7 +46,7 @@ transient boolean toggleneutral; - void DrawNode(CameraPane display, Object3D /*Composite*/ root, boolean selected) + void DrawNode(iCameraPane display, Object3D /*Composite*/ root, boolean selected) { //System.err.println("Frame # " + frame); diff --git a/TriMesh.java b/TriMesh.java index efb3206..6068a2e 100755 --- a/TriMesh.java +++ b/TriMesh.java @@ -70,13 +70,28 @@ */ public class TriMesh extends Geometry implements Serializable { + /** + * <code>draw</code> renders a <code>TriMesh</code> object including + * it's normals, colors, textures and vertices. + * + * @see Renderer#draw(TriMesh) + * @param tris + * the mesh to render. + */ + void DrawParticles(iCameraPane display, Object3D geo, boolean selected, boolean rotate) // TriMesh tris) + { + display.DrawParticles(this, geo, selected, rotate); + } + static final long serialVersionUID = 0; boolean IsStatic() { return false; } + private static final Logger logger = Logger.getLogger(TriMesh.class.getName()); + // private static final long serialVersionUID = 2L; public enum Mode { @@ -270,190 +285,6 @@ float[] texmat = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 }; - // super.DrawNode(...); - /** - * <code>draw</code> renders a <code>TriMesh</code> object including - * it's normals, colors, textures and vertices. - * - * @see Renderer#draw(TriMesh) - * @param tris - * the mesh to render. - */ - void DrawParticles(CameraPane display, Object3D geo, boolean selected, boolean rotate) // TriMesh tris) - { - float r = display.modelParams0[0]; - float g = display.modelParams0[1]; - float b = display.modelParams0[2]; - float opacity = display.modelParams5[1]; - - //final GL gl = GLU.getCurrentGL(); - GL gl = display.GetGL(); // getGL(); - - int v = vertBuf.capacity(); - - int count = 0; - - boolean cf = gl.glIsEnabled(gl.GL_CULL_FACE); - gl.glEnable(gl.GL_CULL_FACE); - // gl.glScalef(1.0f/1024,1.0f/1024,1.0f/1024); - for (int i=0; i<v/3; i++) - { - int index3 = i*3; - - if (sizeBuf.get(index3+1) == 0) - continue; - - count++; - - int index4 = i*4; - - float tx = vertBuf.get(index3); - float ty = vertBuf.get(index3+1); - float tz = vertBuf.get(index3+2); - - // if (tx == 0 && ty == 0 && tz == 0) - // continue; - - gl.glMatrixMode(gl.GL_TEXTURE); - gl.glPushMatrix(); - texmat[12] = texmat[13] = texmat[14] = i; - - gl.glMultMatrixf(texmat, 0); - - gl.glMatrixMode(gl.GL_MODELVIEW); - gl.glPushMatrix(); - - gl.glTranslatef(tx,ty,tz); - - if (rotate) - gl.glRotatef(i, 0, 1, 0); - - float size = sizeBuf.get(index3) / 100; - gl.glScalef(size,size,size); - - float cr = colorBuf.get(index4); - float cg = colorBuf.get(index4+1); - float cb = colorBuf.get(index4+2); - float ca = colorBuf.get(index4+3); - - display.modelParams0[0] = r * cr; - display.modelParams0[1] = g * cg; - display.modelParams0[2] = b * cb; - - display.modelParams5[1] = opacity * ca; - - gl.glProgramEnvParameter4fvARB(gl.GL_FRAGMENT_PROGRAM_ARB, 0, display.modelParams0, 0); - gl.glProgramEnvParameter4fvARB(gl.GL_FRAGMENT_PROGRAM_ARB, 5, display.modelParams5, 0); - - RandomNode.globalseed = (int)sizeBuf.get(index3+2); // i; - RandomNode.globalseed2 = RandomNode.globalseed; - -// gl.glColor4f(cr,cg,cb,ca); - // gl.glScalef(1024/16,1024/16,1024/16); - geo.Draw/*Node*/(display,null,selected,false); // blocked - // gl.glScalef(16.0f/1024,16.0f/1024,16.0f/1024); - //gl.glTranslatef(-tx,-ty,-tz); - gl.glPopMatrix(); - - gl.glMatrixMode(gl.GL_TEXTURE); - gl.glPopMatrix(); - } - // gl.glScalef(1024,1024,1024); - if (!cf) - gl.glDisable(gl.GL_CULL_FACE); - - display.modelParams0[0] = r; - display.modelParams0[1] = g; - display.modelParams0[2] = b; - - display.modelParams5[1] = opacity; - - gl.glProgramEnvParameter4fvARB(gl.GL_FRAGMENT_PROGRAM_ARB, 0, display.modelParams0, 0); - gl.glProgramEnvParameter4fvARB(gl.GL_FRAGMENT_PROGRAM_ARB, 5, display.modelParams5, 0); - - gl.glMatrixMode(gl.GL_MODELVIEW); - -// System.err.println("total = " + v/3 + "; displayed = " + count); - if (true) - return; - -//// if (!tris.predraw(this)) -//// { -//// return; -//// } -//// if (Debug.stats) -//// { -//// StatCollector.addStat(StatType.STAT_TRIANGLE_COUNT, tris.getTriangleCount()); -//// StatCollector.addStat(StatType.STAT_VERTEX_COUNT, tris.getVertexCount()); -//// StatCollector.addStat(StatType.STAT_GEOM_COUNT, 1); -//// } -//// -//// if (tris.getDisplayListID() != -1) -//// { -//// renderDisplayList(tris); -//// return; -//// } -//// -//// if (!generatingDisplayList) -//// { -//// applyStates(tris.states, tris); -//// } -//// if (Debug.stats) -//// { -//// StatCollector.startStat(StatType.STAT_RENDER_TIMER); -//// } -//// boolean transformed = doTransforms(tris); -// -// int glMode = GL.GL_TRIANGLES; -// switch (getMode()) -// { -// case Triangles: -// glMode = GL.GL_TRIANGLES; -// break; -// case Strip: -// glMode = GL.GL_TRIANGLE_STRIP; -// break; -// case Fan: -// glMode = GL.GL_TRIANGLE_FAN; -// break; -// } -// -// if (!predrawGeometry(gl)) -// { -// // make sure only the necessary indices are sent through on old -// // cards. -// IntBuffer indices = this.getIndexBuffer(); -// if (indices == null) -// { -// logger.severe("missing indices on geometry object: " + this.toString()); -// } else -// { -// indices.rewind(); -// indices.limit(this.getMaxIndex()); -// -// gl.glDrawElements(glMode, indices.limit(), GL.GL_UNSIGNED_INT, indices); // TODO Check <count> and assumed <type> of GL_UNSIGNED_INT -// -// indices.clear(); -// } -// } else -// { -// gl.glDrawElements(glMode, this.getIndexBuffer().limit(), -// GL.GL_UNSIGNED_INT, 0); -// } -// -//// postdrawGeometry(tris); -//// if (transformed) -//// { -//// undoTransforms(tris); -//// } -//// -//// if (Debug.stats) -//// { -//// StatCollector.endStat(StatType.STAT_RENDER_TIMER); -//// } -//// tris.postdraw(this); - } - final boolean supportsVBO = false; private FloatBuffer prevVerts; diff --git a/VehicleDemo.java b/VehicleDemo.java index 1641446..2c1a8af 100755 --- a/VehicleDemo.java +++ b/VehicleDemo.java @@ -484,7 +484,7 @@ } - void DrawNode(CameraPane display, Object3D /*Composite*/ root, boolean selected) // ?? + void DrawNode(iCameraPane display, Object3D /*Composite*/ root, boolean selected) // ?? { // super.DrawNode(display,root,selected); @@ -526,10 +526,10 @@ return debugMode; } - public void renderme0(CameraPane display) + public void renderme0(iCameraPane display) { //updateCamera(); - GL gl = display.getGL(); + GL gl = display.GetGL(); if (dynamicsWorld != null) { int numObjects = dynamicsWorld.getNumCollisionObjects(); @@ -755,7 +755,7 @@ // // to be implemented by the demo // @Override - public void renderme(CameraPane display) + public void renderme(iCameraPane display) { // updateCamera(); diff --git a/cMesh.java b/cMesh.java index c2eb4ad..863e918 100644 --- a/cMesh.java +++ b/cMesh.java @@ -484,7 +484,7 @@ } - void DrawNode(CameraPane display, Object3D /*Composite*/ root, boolean selected) // ?? + void DrawNode(iCameraPane display, Object3D /*Composite*/ root, boolean selected) // ?? { // ?????? if (size() > 0) // { diff --git a/cSpring.java b/cSpring.java index fcf1d91..47b7769 100644 --- a/cSpring.java +++ b/cSpring.java @@ -543,13 +543,13 @@ } // serial lost - void DrawNode0(CameraPane display) + void DrawNode0(iCameraPane display) { super.DrawNode(display, null, false); } - void DrawNode/*notused*/(CameraPane display, Object3D /*Composite*/ root, boolean selected) + void DrawNode/*notused*/(iCameraPane display, Object3D /*Composite*/ root, boolean selected) { // assert displaylist == -1; diff --git a/iCameraPane.java b/iCameraPane.java index 5fa0b77..9d55774 100644 --- a/iCameraPane.java +++ b/iCameraPane.java @@ -5,7 +5,9 @@ static final public int SELECTION = 1; static final public int SHADOW = 2; static final public int OCCLUSION = 3; - + + boolean IsBoxMode(); + void ClearDepth(); void DepthTest(boolean depthtest); @@ -50,4 +52,6 @@ void ReleaseTextures(cTexture tex); void DrawFace(Object3D obj, Vertex pv, Vertex qv, Vertex rv, Face face); + + void DrawParticles(TriMesh geo, Object3D shape, boolean selected, boolean rotate); } -- Gitblit v1.6.2