/** * This method applies the variation to the particle with already set velocity. * * @param particle the particle to be affected */ protected void applyVelocityVariation(Particle particle) { particle.velocity.set(initialVelocity); temp.set(FastMath.nextRandomFloat(), FastMath.nextRandomFloat(), FastMath.nextRandomFloat()); temp.multLocal(2f); temp.subtractLocal(1f, 1f, 1f); temp.multLocal(initialVelocity.length()); particle.velocity.interpolate(temp, velocityVariation); }
@Override public void render(RenderManager rm) { if (!isEnabled() || listener == null) { return; } Vector3f lastLocation = listener.getLocation(); Vector3f currentLocation = camera.getLocation(); Vector3f velocity = listener.getVelocity(); if (!lastLocation.equals(currentLocation)) { velocity.set(currentLocation).subtractLocal(lastLocation); velocity.multLocal(1f / lastTpf); listener.setLocation(currentLocation); listener.setVelocity(velocity); } else if (!velocity.equals(Vector3f.ZERO)) { listener.setVelocity(Vector3f.ZERO); } Quaternion lastRotation = listener.getRotation(); Quaternion currentRotation = camera.getRotation(); if (!lastRotation.equals(currentRotation)) { listener.setRotation(currentRotation); } }
private void applyGravity(Spatial blackHole, Spatial target, float tpf) { Vector3f difference = blackHole.getLocalTranslation().subtract(target.getLocalTranslation()); Vector3f gravity = difference.normalize().multLocal(tpf); float distance = difference.length(); if (target.getName().equals("Player")) { gravity.multLocal(250f / distance); target.getControl(PlayerControl.class).applyGravity(gravity.mult(80f)); } else if (target.getName().equals("Bullet")) { gravity.multLocal(250f / distance); target.getControl(BulletControl.class).applyGravity(gravity.mult(-0.8f)); } else if (target.getName().equals("Seeker")) { target.getControl(SeekerControl.class).applyGravity(gravity.mult(150000)); } else if (target.getName().equals("Wanderer")) { target.getControl(WandererControl.class).applyGravity(gravity.mult(150000)); } else if (target.getName().equals("Laser") || target.getName().equals("Glow")) { target.getControl(ParticleControl.class).applyGravity(gravity.mult(15000), distance); } }
public void postQueue(RenderQueue rq) { GeometryList occluders = rq.getShadowQueueContent(ShadowMode.Cast); if (occluders.size() == 0) { noOccluders = true; return; } else { noOccluders = false; } GeometryList receivers = rq.getShadowQueueContent(ShadowMode.Receive); // update frustum points based on current camera Camera viewCam = viewPort.getCamera(); ShadowUtil.updateFrustumPoints( viewCam, viewCam.getFrustumNear(), viewCam.getFrustumFar(), 1.0f, points); Vector3f frustaCenter = new Vector3f(); for (Vector3f point : points) { frustaCenter.addLocal(point); } frustaCenter.multLocal(1f / 8f); // update light direction shadowCam.setProjectionMatrix(null); shadowCam.setParallelProjection(true); // shadowCam.setFrustumPerspective(45, 1, 1, 20); shadowCam.lookAtDirection(direction, Vector3f.UNIT_Y); shadowCam.update(); shadowCam.setLocation(frustaCenter); shadowCam.update(); shadowCam.updateViewProjection(); // render shadow casters to shadow map ShadowUtil.updateShadowCamera(occluders, receivers, shadowCam, points); Renderer r = renderManager.getRenderer(); renderManager.setCamera(shadowCam, false); renderManager.setForcedMaterial(preshadowMat); r.setFrameBuffer(shadowFB); r.clearBuffers(false, true, false); viewPort.getQueue().renderShadowQueue(ShadowMode.Cast, renderManager, shadowCam, true); r.setFrameBuffer(viewPort.getOutputFrameBuffer()); renderManager.setForcedMaterial(null); renderManager.setCamera(viewCam, false); }
public static Mesh genNormalLines(Mesh mesh, float scale) { FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData(); FloatBuffer normalBuffer = (FloatBuffer) mesh.getBuffer(Type.Normal).getData(); ColorRGBA originColor = ColorRGBA.White; ColorRGBA normalColor = ColorRGBA.Blue; Mesh lineMesh = new Mesh(); lineMesh.setMode(Mesh.Mode.Lines); Vector3f origin = new Vector3f(); Vector3f point = new Vector3f(); FloatBuffer lineVertex = BufferUtils.createFloatBuffer(vertexBuffer.limit() * 2); FloatBuffer lineColor = BufferUtils.createFloatBuffer(vertexBuffer.limit() / 3 * 4 * 2); for (int i = 0; i < vertexBuffer.limit() / 3; i++) { populateFromBuffer(origin, vertexBuffer, i); populateFromBuffer(point, normalBuffer, i); int index = i * 2; setInBuffer(origin, lineVertex, index); setInBuffer(originColor, lineColor, index); point.multLocal(scale); point.addLocal(origin); setInBuffer(point, lineVertex, index + 1); setInBuffer(normalColor, lineColor, index + 1); } lineMesh.setBuffer(Type.Position, 3, lineVertex); lineMesh.setBuffer(Type.Color, 4, lineColor); lineMesh.setStatic(); // lineMesh.setInterleaved(); return lineMesh; }
private static void convertNormals(FloatBuffer input, ByteBuffer output) { if (output.capacity() < input.capacity()) throw new RuntimeException("Output must be at least as large as input!"); input.clear(); output.clear(); Vector3f temp = new Vector3f(); int vertexCount = input.capacity() / 3; for (int i = 0; i < vertexCount; i++) { BufferUtils.populateFromBuffer(temp, input, i); // offset and scale vector into -128 ... 127 temp.multLocal(127).addLocal(0.5f, 0.5f, 0.5f); // quantize byte v1 = (byte) temp.getX(); byte v2 = (byte) temp.getY(); byte v3 = (byte) temp.getZ(); // store output.put(v1).put(v2).put(v3); } }
@Override public void simpleUpdate(float lastTimePerFrame) { float playerMoveSpeed = ((cubesSettings.getBlockSize() * 6.5f) * lastTimePerFrame); Vector3f camDir = cam.getDirection().mult(playerMoveSpeed); Vector3f camLeft = cam.getLeft().mult(playerMoveSpeed); walkDirection.set(0, 0, 0); if (arrowKeys[0]) { walkDirection.addLocal(camDir); } if (arrowKeys[1]) { walkDirection.addLocal(camLeft.negate()); } if (arrowKeys[2]) { walkDirection.addLocal(camDir.negate()); } if (arrowKeys[3]) { walkDirection.addLocal(camLeft); } walkDirection.setY(0); walkDirection.normalize(); walkDirection.multLocal(lastTimePerFrame * 10); playerControl.setWalkDirection(walkDirection); cam.setLocation(playerControl.getPhysicsLocation()); }
private static Transform convertPositions(FloatBuffer input, BoundingBox bbox, Buffer output) { if (output.capacity() < input.capacity()) throw new RuntimeException("Output must be at least as large as input!"); Vector3f offset = bbox.getCenter().negate(); Vector3f size = new Vector3f(bbox.getXExtent(), bbox.getYExtent(), bbox.getZExtent()); size.multLocal(2); ShortBuffer sb = null; ByteBuffer bb = null; float dataTypeSize; float dataTypeOffset; if (output instanceof ShortBuffer) { sb = (ShortBuffer) output; dataTypeOffset = shortOff; dataTypeSize = shortSize; } else { bb = (ByteBuffer) output; dataTypeOffset = byteOff; dataTypeSize = byteSize; } Vector3f scale = new Vector3f(); scale.set(dataTypeSize, dataTypeSize, dataTypeSize).divideLocal(size); Vector3f invScale = new Vector3f(); invScale.set(size).divideLocal(dataTypeSize); offset.multLocal(scale); offset.addLocal(dataTypeOffset, dataTypeOffset, dataTypeOffset); // offset = (-modelOffset * shortSize)/modelSize + shortOff // scale = shortSize / modelSize input.clear(); output.clear(); Vector3f temp = new Vector3f(); int vertexCount = input.capacity() / 3; for (int i = 0; i < vertexCount; i++) { BufferUtils.populateFromBuffer(temp, input, i); // offset and scale vector into -32768 ... 32767 // or into -128 ... 127 if using bytes temp.multLocal(scale); temp.addLocal(offset); // quantize and store if (sb != null) { short v1 = (short) temp.getX(); short v2 = (short) temp.getY(); short v3 = (short) temp.getZ(); sb.put(v1).put(v2).put(v3); } else { byte v1 = (byte) temp.getX(); byte v2 = (byte) temp.getY(); byte v3 = (byte) temp.getZ(); bb.put(v1).put(v2).put(v3); } } Transform transform = new Transform(); transform.setTranslation(offset.negate().multLocal(invScale)); transform.setScale(invScale); return transform; }
@Override public void updateParticleData(ParticleData[] particles, Camera cam, Matrix3f inverseRotation) { for (int i = 0; i < particles.length; i++) { ParticleData p = particles[i]; int offset = templateVerts.capacity() * i; int colorOffset = templateColors.capacity() * i; if (p.life == 0 || !p.active) { for (int x = 0; x < templateVerts.capacity(); x += 3) { finVerts.put(offset + x, 0); finVerts.put(offset + x + 1, 0); finVerts.put(offset + x + 2, 0); } continue; } for (int x = 0; x < templateVerts.capacity(); x += 3) { switch (emitter.getBillboardMode()) { case Velocity: if (p.velocity.x != Vector3f.UNIT_Y.x && p.velocity.y != Vector3f.UNIT_Y.y && p.velocity.z != Vector3f.UNIT_Y.z) up.set(p.velocity).crossLocal(Vector3f.UNIT_Y).normalizeLocal(); else up.set(p.velocity).crossLocal(lock).normalizeLocal(); left.set(p.velocity).crossLocal(up).normalizeLocal(); dir.set(p.velocity); break; case Velocity_Z_Up: if (p.velocity.x != Vector3f.UNIT_Y.x && p.velocity.y != Vector3f.UNIT_Y.y && p.velocity.z != Vector3f.UNIT_Y.z) up.set(p.velocity).crossLocal(Vector3f.UNIT_Y).normalizeLocal(); else up.set(p.velocity).crossLocal(lock).normalizeLocal(); left.set(p.velocity).crossLocal(up).normalizeLocal(); dir.set(p.velocity); rotStore = tempQ.fromAngleAxis(-90 * FastMath.DEG_TO_RAD, left); left = rotStore.mult(left); up = rotStore.mult(up); break; case Velocity_Z_Up_Y_Left: up.set(p.velocity).crossLocal(Vector3f.UNIT_Y).normalizeLocal(); left.set(p.velocity).crossLocal(up).normalizeLocal(); dir.set(p.velocity); tempV3.set(left).crossLocal(up).normalizeLocal(); rotStore = tempQ.fromAngleAxis(90 * FastMath.DEG_TO_RAD, p.velocity); left = rotStore.mult(left); up = rotStore.mult(up); rotStore = tempQ.fromAngleAxis(-90 * FastMath.DEG_TO_RAD, left); up = rotStore.mult(up); break; case Normal: emitter.getShape().setNext(p.triangleIndex); tempV3.set(emitter.getShape().getNormal()); if (tempV3 == Vector3f.UNIT_Y) tempV3.set(p.velocity); up.set(tempV3).crossLocal(Vector3f.UNIT_Y).normalizeLocal(); left.set(tempV3).crossLocal(up).normalizeLocal(); dir.set(tempV3); break; case Normal_Y_Up: emitter.getShape().setNext(p.triangleIndex); tempV3.set(p.velocity); if (tempV3 == Vector3f.UNIT_Y) tempV3.set(Vector3f.UNIT_X); up.set(Vector3f.UNIT_Y); left.set(tempV3).crossLocal(up).normalizeLocal(); dir.set(tempV3); break; case Camera: up.set(cam.getUp()); left.set(cam.getLeft()); dir.set(cam.getDirection()); break; case UNIT_X: up.set(Vector3f.UNIT_Y); left.set(Vector3f.UNIT_Z); dir.set(Vector3f.UNIT_X); break; case UNIT_Y: up.set(Vector3f.UNIT_Z); left.set(Vector3f.UNIT_X); dir.set(Vector3f.UNIT_Y); break; case UNIT_Z: up.set(Vector3f.UNIT_X); left.set(Vector3f.UNIT_Y); dir.set(Vector3f.UNIT_Z); break; } tempV3.set(templateVerts.get(x), templateVerts.get(x + 1), templateVerts.get(x + 2)); tempV3 = rotStore.mult(tempV3); tempV3.multLocal(p.size); rotStore.fromAngles(p.angles.x, p.angles.y, p.angles.z); tempV3 = rotStore.mult(tempV3); tempV3.addLocal(p.position); if (!emitter.getParticlesFollowEmitter()) { tempV3.subtractLocal( emitter .getEmitterNode() .getWorldTranslation() .subtract(p.initialPosition)); // .divide(8f)); } finVerts.put(offset + x, tempV3.getX()); finVerts.put(offset + x + 1, tempV3.getY()); finVerts.put(offset + x + 2, tempV3.getZ()); } if (p.emitter.getApplyLightingTransform()) { for (int v = 0; v < templateNormals.capacity(); v += 3) { tempV3.set( templateNormals.get(v), templateNormals.get(v + 1), templateNormals.get(v + 2)); rotStore.fromAngles(p.angles.x, p.angles.y, p.angles.z); mat3.set(rotStore.toRotationMatrix()); float vx = tempV3.x, vy = tempV3.y, vz = tempV3.z; tempV3.x = mat3.get(0, 0) * vx + mat3.get(0, 1) * vy + mat3.get(0, 2) * vz; tempV3.y = mat3.get(1, 0) * vx + mat3.get(1, 1) * vy + mat3.get(1, 2) * vz; tempV3.z = mat3.get(2, 0) * vx + mat3.get(2, 1) * vy + mat3.get(2, 2) * vz; finNormals.put(offset + v, tempV3.getX()); finNormals.put(offset + v + 1, tempV3.getY()); finNormals.put(offset + v + 2, tempV3.getZ()); } } for (int v = 0; v < templateColors.capacity(); v += 4) { finColors .put(colorOffset + v, p.color.r) .put(colorOffset + v + 1, p.color.g) .put(colorOffset + v + 2, p.color.b) .put(colorOffset + v + 3, p.color.a * p.alpha); } } this.setBuffer(VertexBuffer.Type.Position, 3, finVerts); if (particles[0].emitter.getApplyLightingTransform()) this.setBuffer(VertexBuffer.Type.Normal, 3, finNormals); this.setBuffer(VertexBuffer.Type.Color, 4, finColors); updateBound(); }
/** * Rebuilds the cylinder based on a new set of parameters. * * @param axisSamples the number of samples along the axis. * @param radialSamples the number of samples around the radial. * @param radius the radius of the bottom of the cylinder. * @param radius2 the radius of the top of the cylinder. * @param height the cylinder's height. * @param closed should the cylinder have top and bottom surfaces. * @param inverted is the cylinder is meant to be viewed from the inside. */ public void updateGeometry( int axisSamples, int radialSamples, float radius, float radius2, float height, boolean closed, boolean inverted) { this.axisSamples = axisSamples + (closed ? 2 : 0); this.radialSamples = radialSamples; this.radius = radius; this.radius2 = radius2; this.height = height; this.closed = closed; this.inverted = inverted; // VertexBuffer pvb = getBuffer(Type.Position); // VertexBuffer nvb = getBuffer(Type.Normal); // VertexBuffer tvb = getBuffer(Type.TexCoord); // Vertices int vertCount = axisSamples * (radialSamples + 1) + (closed ? 2 : 0); setBuffer(Type.Position, 3, createVector3Buffer(getFloatBuffer(Type.Position), vertCount)); // Normals setBuffer(Type.Normal, 3, createVector3Buffer(getFloatBuffer(Type.Normal), vertCount)); // Texture co-ordinates setBuffer(Type.TexCoord, 2, createVector2Buffer(vertCount)); int triCount = ((closed ? 2 : 0) + 2 * (axisSamples - 1)) * radialSamples; setBuffer(Type.Index, 3, createShortBuffer(getShortBuffer(Type.Index), 3 * triCount)); // generate geometry float inverseRadial = 1.0f / radialSamples; float inverseAxisLess = 1.0f / (closed ? axisSamples - 3 : axisSamples - 1); float inverseAxisLessTexture = 1.0f / (axisSamples - 1); float halfHeight = 0.5f * height; // Generate points on the unit circle to be used in computing the mesh // points on a cylinder slice. float[] sin = new float[radialSamples + 1]; float[] cos = new float[radialSamples + 1]; for (int radialCount = 0; radialCount < radialSamples; radialCount++) { float angle = FastMath.TWO_PI * inverseRadial * radialCount; cos[radialCount] = FastMath.cos(angle); sin[radialCount] = FastMath.sin(angle); } sin[radialSamples] = sin[0]; cos[radialSamples] = cos[0]; // calculate normals Vector3f[] vNormals = null; Vector3f vNormal = Vector3f.UNIT_Z; if ((height != 0.0f) && (radius != radius2)) { vNormals = new Vector3f[radialSamples]; Vector3f vHeight = Vector3f.UNIT_Z.mult(height); Vector3f vRadial = new Vector3f(); for (int radialCount = 0; radialCount < radialSamples; radialCount++) { vRadial.set(cos[radialCount], sin[radialCount], 0.0f); Vector3f vRadius = vRadial.mult(radius); Vector3f vRadius2 = vRadial.mult(radius2); Vector3f vMantle = vHeight.subtract(vRadius2.subtract(vRadius)); Vector3f vTangent = vRadial.cross(Vector3f.UNIT_Z); vNormals[radialCount] = vMantle.cross(vTangent).normalize(); } } FloatBuffer nb = getFloatBuffer(Type.Normal); FloatBuffer pb = getFloatBuffer(Type.Position); FloatBuffer tb = getFloatBuffer(Type.TexCoord); // generate the cylinder itself Vector3f tempNormal = new Vector3f(); for (int axisCount = 0, i = 0; axisCount < axisSamples; axisCount++, i++) { float axisFraction; float axisFractionTexture; int topBottom = 0; if (!closed) { axisFraction = axisCount * inverseAxisLess; // in [0,1] axisFractionTexture = axisFraction; } else { if (axisCount == 0) { topBottom = -1; // bottom axisFraction = 0; axisFractionTexture = inverseAxisLessTexture; } else if (axisCount == axisSamples - 1) { topBottom = 1; // top axisFraction = 1; axisFractionTexture = 1 - inverseAxisLessTexture; } else { axisFraction = (axisCount - 1) * inverseAxisLess; axisFractionTexture = axisCount * inverseAxisLessTexture; } } // compute center of slice float z = -halfHeight + height * axisFraction; Vector3f sliceCenter = new Vector3f(0, 0, z); // compute slice vertices with duplication at end point int save = i; for (int radialCount = 0; radialCount < radialSamples; radialCount++, i++) { float radialFraction = radialCount * inverseRadial; // in [0,1) tempNormal.set(cos[radialCount], sin[radialCount], 0.0f); if (vNormals != null) { vNormal = vNormals[radialCount]; } else if (radius == radius2) { vNormal = tempNormal; } if (topBottom == 0) { if (!inverted) nb.put(vNormal.x).put(vNormal.y).put(vNormal.z); else nb.put(-vNormal.x).put(-vNormal.y).put(-vNormal.z); } else { nb.put(0).put(0).put(topBottom * (inverted ? -1 : 1)); } tempNormal.multLocal((radius - radius2) * axisFraction + radius2).addLocal(sliceCenter); pb.put(tempNormal.x).put(tempNormal.y).put(tempNormal.z); tb.put((inverted ? 1 - radialFraction : radialFraction)).put(axisFractionTexture); } BufferUtils.copyInternalVector3(pb, save, i); BufferUtils.copyInternalVector3(nb, save, i); tb.put((inverted ? 0.0f : 1.0f)).put(axisFractionTexture); } if (closed) { pb.put(0).put(0).put(-halfHeight); // bottom center nb.put(0).put(0).put(-1 * (inverted ? -1 : 1)); tb.put(0.5f).put(0); pb.put(0).put(0).put(halfHeight); // top center nb.put(0).put(0).put(1 * (inverted ? -1 : 1)); tb.put(0.5f).put(1); } IndexBuffer ib = getIndexBuffer(); int index = 0; // Connectivity for (int axisCount = 0, axisStart = 0; axisCount < axisSamples - 1; axisCount++) { int i0 = axisStart; int i1 = i0 + 1; axisStart += radialSamples + 1; int i2 = axisStart; int i3 = i2 + 1; for (int i = 0; i < radialSamples; i++) { if (closed && axisCount == 0) { if (!inverted) { ib.put(index++, i0++); ib.put(index++, vertCount - 2); ib.put(index++, i1++); } else { ib.put(index++, i0++); ib.put(index++, i1++); ib.put(index++, vertCount - 2); } } else if (closed && axisCount == axisSamples - 2) { ib.put(index++, i2++); ib.put(index++, inverted ? vertCount - 1 : i3++); ib.put(index++, inverted ? i3++ : vertCount - 1); } else { ib.put(index++, i0++); ib.put(index++, inverted ? i2 : i1); ib.put(index++, inverted ? i1 : i2); ib.put(index++, i1++); ib.put(index++, inverted ? i2++ : i3++); ib.put(index++, inverted ? i3++ : i2++); } } } updateBound(); }
/** * Updates the points array to contain the frustum corners of the given camera. The nearOverride * and farOverride variables can be used to override the camera's near/far values with own values. * * <p>TODO: Reduce creation of new vectors * * @param viewCam * @param nearOverride * @param farOverride */ public static void updateFrustumPoints( Camera viewCam, float nearOverride, float farOverride, float scale, Vector3f[] points) { Vector3f pos = viewCam.getLocation(); Vector3f dir = viewCam.getDirection(); Vector3f up = viewCam.getUp(); float depthHeightRatio = viewCam.getFrustumTop() / viewCam.getFrustumNear(); float near = nearOverride; float far = farOverride; float ftop = viewCam.getFrustumTop(); float fright = viewCam.getFrustumRight(); float ratio = fright / ftop; float near_height; float near_width; float far_height; float far_width; if (viewCam.isParallelProjection()) { near_height = ftop; near_width = near_height * ratio; far_height = ftop; far_width = far_height * ratio; } else { near_height = depthHeightRatio * near; near_width = near_height * ratio; far_height = depthHeightRatio * far; far_width = far_height * ratio; } Vector3f right = dir.cross(up).normalizeLocal(); Vector3f temp = new Vector3f(); temp.set(dir).multLocal(far).addLocal(pos); Vector3f farCenter = temp.clone(); temp.set(dir).multLocal(near).addLocal(pos); Vector3f nearCenter = temp.clone(); Vector3f nearUp = temp.set(up).multLocal(near_height).clone(); Vector3f farUp = temp.set(up).multLocal(far_height).clone(); Vector3f nearRight = temp.set(right).multLocal(near_width).clone(); Vector3f farRight = temp.set(right).multLocal(far_width).clone(); points[0].set(nearCenter).subtractLocal(nearUp).subtractLocal(nearRight); points[1].set(nearCenter).addLocal(nearUp).subtractLocal(nearRight); points[2].set(nearCenter).addLocal(nearUp).addLocal(nearRight); points[3].set(nearCenter).subtractLocal(nearUp).addLocal(nearRight); points[4].set(farCenter).subtractLocal(farUp).subtractLocal(farRight); points[5].set(farCenter).addLocal(farUp).subtractLocal(farRight); points[6].set(farCenter).addLocal(farUp).addLocal(farRight); points[7].set(farCenter).subtractLocal(farUp).addLocal(farRight); if (scale != 1.0f) { // find center of frustum Vector3f center = new Vector3f(); for (int i = 0; i < 8; i++) { center.addLocal(points[i]); } center.divideLocal(8f); Vector3f cDir = new Vector3f(); for (int i = 0; i < 8; i++) { cDir.set(points[i]).subtractLocal(center); cDir.multLocal(scale - 1.0f); points[i].addLocal(cDir); } } }
@Override public Vector2f getRelativePosition(int unit_in, Vector2f leaderPosition, float rotationAngle) { Vector2f ret; do { int unit_index; if ((true)) { unit_index = unit_in + position_offset; } else { unit_index = unit_in + position_offset_neg; } quater.fromAngleNormalAxis(rotationAngle * FastMath.DEG_TO_RAD, Vector3f.UNIT_Y); float index; float index_y; int row_num = ((int) FastMath.floor(FastMath.sqrt(unit_index))); int count_in_row = row_num * 2 + 1; int all_before_lines = 0; for (int i = 0; i < row_num; i++) { all_before_lines += i * 2 + 1; } int in_line_index = unit_index - all_before_lines; if (rev) { index_y = -row_num; index = (-(count_in_row / 2) + in_line_index); } else { index_y = -row_num; index = (-(count_in_row / 2) + in_line_index); } /* 0*0 0 +0 +0 1 0 1*1 1 +1 -1 3 1 2 +0 -1 1.41 3 -1 -1 1.73 2*2 4 +2 -2 5 2 5 +1 -2 2.23 6 +0 -2 2.44 7 -1 -2 2.64 8 -2 -2 2.82 3*3 9 +3 -3 7 */ Vector3f v = new Vector3f(index, 0, index_y); if ((rotationAngle / 45) % 2 == 1) { v.multLocal(FastMath.sqrt(2)); } Vector3f rot = quater.mult(v); // System.out.println("rotated: " + rot); ret = leaderPosition.clone().addLocal(rot.x, rot.z); ret.x = Math.round(ret.x); ret.y = Math.round(ret.y); if (ret.x < 0 || ret.y < 0 || ret.x > map.mapWidth - 1 || ret.y > map.mapHeight - 1) { return super.getReservistPosition(unit_in, leaderPosition); } if (!map.isTerrainAccessible(ret)) { if (true) { position_offset++; } else { position_offset_neg++; } } } while (!map.isTerrainAccessible(ret)); return ret; }
private static Mesh genTangentLines(Mesh mesh, float scale) { FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData(); FloatBuffer normalBuffer = (FloatBuffer) mesh.getBuffer(Type.Normal).getData(); FloatBuffer tangentBuffer = (FloatBuffer) mesh.getBuffer(Type.Tangent).getData(); FloatBuffer binormalBuffer = null; if (mesh.getBuffer(Type.Binormal) != null) { binormalBuffer = (FloatBuffer) mesh.getBuffer(Type.Binormal).getData(); } ColorRGBA originColor = ColorRGBA.White; ColorRGBA tangentColor = ColorRGBA.Red; ColorRGBA binormalColor = ColorRGBA.Green; ColorRGBA normalColor = ColorRGBA.Blue; Mesh lineMesh = new Mesh(); lineMesh.setMode(Mesh.Mode.Lines); Vector3f origin = new Vector3f(); Vector3f point = new Vector3f(); Vector3f tangent = new Vector3f(); Vector3f normal = new Vector3f(); IntBuffer lineIndex = BufferUtils.createIntBuffer(vertexBuffer.limit() / 3 * 6); FloatBuffer lineVertex = BufferUtils.createFloatBuffer(vertexBuffer.limit() * 4); FloatBuffer lineColor = BufferUtils.createFloatBuffer(vertexBuffer.limit() / 3 * 4 * 4); boolean hasParity = mesh.getBuffer(Type.Tangent).getNumComponents() == 4; float tangentW = 1; for (int i = 0; i < vertexBuffer.limit() / 3; i++) { populateFromBuffer(origin, vertexBuffer, i); populateFromBuffer(normal, normalBuffer, i); if (hasParity) { tangent.x = tangentBuffer.get(i * 4); tangent.y = tangentBuffer.get(i * 4 + 1); tangent.z = tangentBuffer.get(i * 4 + 2); tangentW = tangentBuffer.get(i * 4 + 3); } else { populateFromBuffer(tangent, tangentBuffer, i); } int index = i * 4; int id = i * 6; lineIndex.put(id, index); lineIndex.put(id + 1, index + 1); lineIndex.put(id + 2, index); lineIndex.put(id + 3, index + 2); lineIndex.put(id + 4, index); lineIndex.put(id + 5, index + 3); setInBuffer(origin, lineVertex, index); setInBuffer(originColor, lineColor, index); point.set(tangent); point.multLocal(scale); point.addLocal(origin); setInBuffer(point, lineVertex, index + 1); setInBuffer(tangentColor, lineColor, index + 1); // wvBinormal = cross(wvNormal, wvTangent) * -inTangent.w if (binormalBuffer == null) { normal.cross(tangent, point); point.multLocal(-tangentW); point.normalizeLocal(); } else { populateFromBuffer(point, binormalBuffer, i); } point.multLocal(scale); point.addLocal(origin); setInBuffer(point, lineVertex, index + 2); setInBuffer(binormalColor, lineColor, index + 2); point.set(normal); point.multLocal(scale); point.addLocal(origin); setInBuffer(point, lineVertex, index + 3); setInBuffer(normalColor, lineColor, index + 3); } lineMesh.setBuffer(Type.Index, 1, lineIndex); lineMesh.setBuffer(Type.Position, 3, lineVertex); lineMesh.setBuffer(Type.Color, 4, lineColor); lineMesh.setStatic(); // lineMesh.setInterleaved(); return lineMesh; }