List of usage examples for org.apache.commons.math3.geometry.euclidean.threed Vector3D Vector3D
public Vector3D(double x, double y, double z)
From source file:org.jtrfp.trcl.beh.MatchDirection.java
@Override public void _tick(long tickTimeMillis) { if (target != null) { final double[] hdg = target.getHeadingArray(); getParent().setHeading(new Vector3D(hdg[0], hdg[1], hdg[2])); final double[] top = target.getTopArray(); getParent().setTop(new Vector3D(top[0], top[1], top[2])); } //end if(!null) }
From source file:org.jtrfp.trcl.beh.SteadilyRotating.java
@Override public void _tick(long tickTime) { final WorldObject thisObject = getParent(); final double theta = ((double) tickTime / rotationPeriodMillis) * Math.PI * 2 + rotationPhase; thisObject.setHeading(new Vector3D(Math.sin(theta), 0, Math.cos(theta))); }
From source file:org.jtrfp.trcl.core.ResourceManager.java
public Model getBINModel(String name, TextureDescription defaultTexture, double scale, boolean cache, ColorPaletteVectorList palette, ColorPaletteVectorList ESTuTvPalette) throws FileLoadException, IOException, IllegalAccessException { if (name == null) throw new NullPointerException("Name is intolerably null"); if (palette == null) throw new NullPointerException("Palette is intolerably null"); if (modelCache.containsKey(name) && cache) return modelCache.get(name); //The models like to set up two line segments where there should be one. //This set is for identifying and culling redundant segs. final HashSet<Integer> alreadyVisitedLineSegs = new HashSet<Integer>(); boolean hasAlpha = false; try {/*from w w w . j av a 2 s . co m*/ BINFile.AnimationControl ac = null; Model result = new Model(true, tr); ac = aniBinNameMap.get(name); if (ac == null) { InputStream is = getInputStreamFromResource("MODELS\\" + name); //TODO: InputStream not guaranteed to close when exception is thrown. Wrap in try{}, close it, and re-throw. ac = new BINFile.AnimationControl(is);//This will throw an exception on and escape to the static model block is.close(); aniBinNameMap.put(name, ac); } System.out.println("Recognized as animation control file."); //Build the Model from the BINFile.Model Model[] frames = new Model[ac.getNumFrames()]; for (int i = 0; i < frames.length; i++) { frames[i] = getBINModel(ac.getBinFiles().get(i), defaultTexture, scale, cache, palette, ESTuTvPalette); } result.setDebugName(name + " triangles: " + frames[0].getRawTriangleLists().get(0).size()); //Consolidate the frames to one model for (int i = 0; i < frames.length; i++) { result.addFrame(frames[i]); } result.setFrameDelayInMillis((int) (((double) ac.getDelay() / 65535.) * 1000.)); //result.finalizeModel(); if (cache) modelCache.put(name, result); return result; } //end try{} catch (UnrecognizedFormatException e) {//ok fail. Static model try { BINFile.Model m = null; Model result = new Model(false, tr); result.setDebugName(name); m = modBinNameMap.get(name); if (m == null) { InputStream is = getInputStreamFromResource("MODELS\\" + name); m = new BINFile.Model(is); modBinNameMap.put(name, m); } //end if(null) final double cpScalar = (scale * TR.crossPlatformScalar * 256.) / (double) m.getScale(); System.out.println("Recognized as model file."); List<org.jtrfp.trcl.gpu.Vertex> vertices = new ArrayList<org.jtrfp.trcl.gpu.Vertex>(); for (BINFile.Model.Vertex binVtx : m.getVertices()) { vertices.add(new org.jtrfp.trcl.gpu.Vertex().setPosition(new Vector3D(binVtx.getX() * cpScalar, binVtx.getY() * cpScalar, binVtx.getZ() * cpScalar))); } //end try{} TextureDescription currentTexture = null; final double[] u = new double[4]; final double[] v = new double[4]; for (ThirdPartyParseable b : m.getDataBlocks()) { //Sort out types of block if (b instanceof TextureBlock) { TextureBlock tb = (TextureBlock) b; if (hasAlpha) currentTexture = getRAWAsTexture(tb.getTextureFileName(), palette, ESTuTvPalette, hasAlpha); else { currentTexture = getRAWAsTexture(tb.getTextureFileName(), palette, ESTuTvPalette, false); } System.out.println( "ResourceManager: TextureBlock specifies texture: " + tb.getTextureFileName()); } //end if(TextureBlock) else if (b instanceof FaceBlock) { //System.out.println("FaceBlock found: "+b.getClass().getSimpleName()); FaceBlock block = (FaceBlock) b; List<FaceBlockVertex> vertIndices = block.getVertices(); if (currentTexture == null) { System.out.println("Warning: Face texture not specified. Using fallback texture."); currentTexture = defaultTexture; } /* * "The two vb_tex_coord values map the vertices of the face to the texture. * They are both in the range of 0x0 to 0xFF00, with u=0x0, v=0x0 being the upper * left corner of the texture, and u=0xFF00, v=0xFF00 being the lower right corner." * - http://www.viaregio.de/pieper/mtm/bin_file_format.shtml */ //// Note: It appears that Stefan's 0xFF0000 approach works rather than the 0xFF00 value. typo? if (vertIndices.size() == 4) {//Quads org.jtrfp.trcl.gpu.Vertex[] vtx = new org.jtrfp.trcl.gpu.Vertex[4]; for (int i = 0; i < 4; i++) { vtx[i] = vertices.get(vertIndices.get(i).getVertexIndex() % (b instanceof FaceBlock05 ? 10 : Integer.MAX_VALUE)); } Vector3D blockNormal = new Vector3D(block.getNormalX(), block.getNormalY(), block.getNormalZ()); if (blockNormal.getNorm() == 0) blockNormal = new Vector3D(1, 0, 0);//Use filler if zero norm. if (vertIndices.get(0) instanceof FaceBlockVertexWithUV) { for (int i = 0; i < 4; i++) { final FaceBlockVertexWithUV fbvi = (FaceBlockVertexWithUV) vertIndices.get(i); u[i] = (double) (fbvi).getTextureCoordinateU() / (double) 0xFF0000; v[i] = (double) (fbvi).getTextureCoordinateV() / (double) 0xFF0000; } //end for(4) } else { u[0] = BOX_U[0]; v[0] = BOX_V[0]; u[1] = BOX_U[1]; v[1] = BOX_V[1]; u[2] = BOX_U[2]; v[2] = BOX_V[2]; u[3] = BOX_U[3]; v[3] = BOX_V[3]; } Triangle[] tris = Triangle.quad2Triangles(vtx, new Vector2D[] { new Vector2D(u[0], 1. - v[0]), new Vector2D(u[1], 1. - v[1]), new Vector2D(u[2], 1. - v[2]), new Vector2D(u[3], 1. - v[3]) }, currentTexture, RenderMode.DYNAMIC, hasAlpha, blockNormal.normalize(), "quad.BINmodel" + name); result.addTriangle(tris[0]); result.addTriangle(tris[1]); } else if (vertIndices.size() == 3)//Triangles { Triangle t = new Triangle(currentTexture); try { t.setCentroidNormal( new Vector3D(block.getNormalX(), block.getNormalY(), block.getNormalZ()) .normalize()); } catch (MathArithmeticException ee) { t.setCentroidNormal(Vector3D.ZERO); } t.setAlphaBlended(hasAlpha); t.setRenderMode(RenderMode.DYNAMIC); for (int vi = 0; vi < 3; vi++) { final org.jtrfp.trcl.gpu.Vertex vtx = vertices .get(vertIndices.get(vi).getVertexIndex() - (b instanceof FaceBlock05 ? m.getUnknown2() : 0)); t.setVertex(vtx, vi); if (b instanceof FaceBlock05 || !(vertIndices.get(0) instanceof FaceBlockVertexWithUV)) t.setUV(new Vector2D(BOX_U[vi], BOX_V[vi]), vi); else { t.setUV(new Vector2D( (double) ((FaceBlockVertexWithUV) vertIndices.get(vi)) .getTextureCoordinateU() / (double) 0xFF0000, 1. - (double) ((FaceBlockVertexWithUV) vertIndices.get(vi)) .getTextureCoordinateV() / (double) 0xFF0000), vi); } } //end for(vi) if (currentTexture == null) { System.err.println("WARNING: Texture never set for " + name + ". Using fallback."); currentTexture = tr.gpu.get().textureManager.get().getFallbackTexture(); } result.addTriangle(t); } //end if(3 vertices) else { System.err.println("ResourceManager: FaceBlock has " + vertIndices.size() + " vertices. Only 3 or 4 supported."); } } //end if(FaceBlock) else if (b instanceof ColorBlock) { final ColorBlock cb = (ColorBlock) b; final byte[] bytes = cb.getBytes(); final Color color = new Color(bytes[0] & 0xFF, bytes[1] & 0xFF, bytes[2] & 0xFF); currentTexture = tr.gpu.get().textureManager.get().solidColor(color); } else if (b instanceof FaceBlock19) { System.out.println(b.getClass().getSimpleName() + " (solid colored faces) not yet implemented. Skipping..."); } else if (b instanceof FaceBlock05) { } //TODO else if (b instanceof LineSegmentBlock) { LineSegmentBlock block = (LineSegmentBlock) b; org.jtrfp.trcl.gpu.Vertex v1 = vertices.get(block.getVertexID1()); org.jtrfp.trcl.gpu.Vertex v2 = vertices.get(block.getVertexID2()); if (!alreadyVisitedLineSegs.contains(v1.hashCode() * v2.hashCode())) { Triangle[] newTris = new Triangle[6]; LineSegment.buildTriPipe(v1.getPosition(), v2.getPosition(), tr.gpu.get().textureManager.get().getDefaultTriPipeTexture(), 200, newTris, 0); result.addTriangles(newTris); alreadyVisitedLineSegs.add(v1.hashCode() * v2.hashCode()); } //end if(not already visited) } //end if(LineSegmentBlock) else if (b instanceof Unknown12) { System.out.println("Found unknown12. Assuming this is a tag for a transparent texture..."); hasAlpha = true; } else if (b instanceof AnimatedTextureBlock) { System.out.println("Found animated texture block."); AnimatedTextureBlock block = (AnimatedTextureBlock) b; List<String> frames = block.getFrameNames(); double timeBetweenFramesInMillis = ((double) block.getDelay() / 65535.) * 1000.; Texture[] subTextures = new Texture[frames.size()]; for (int ti = 0; ti < frames.size(); ti++) { if (!hasAlpha) subTextures[ti] = (Texture) getRAWAsTexture(frames.get(ti), palette, ESTuTvPalette, false); else subTextures[ti] = (Texture) getRAWAsTexture(frames.get(ti), palette, ESTuTvPalette, true); //subTextures[ti]=tex instanceof Texture?new DummyTRFutureTask<Texture>((Texture)tex):(Texture)Texture.getFallbackTexture(); } //end for(frames) //fDelay, nFrames,interp currentTexture = new AnimatedTexture( new Sequencer((int) timeBetweenFramesInMillis, subTextures.length, false), subTextures); } else if (b instanceof EOFBlock) { System.out.println("...That's all, end of BIN"); } else { System.out.println("Failed to identify DataBlock: " + b.getClass().getName()); } } //end for(dataBlocks) //result.finalizeModel(); result.setDebugName(name); //if(result.getTriangleList()==null && result.getTransparentTriangleList()==null) // throw new RuntimeException("Resulting BIN has no triangleList"); if (cache) modelCache.put(name, result); return result; } //end try{} catch (UnrecognizedFormatException ee) { //Not-good fail throw new UnrecognizedFormatException( "Can't figure out what this is: " + name + ". Giving up. Expect trouble ahead."); } } //end catch(ok fail) //Bad fail. }
From source file:org.jtrfp.trcl.core.TR.java
public static Vector3D twosComplimentSubtract(Vector3D l, Vector3D r) { return new Vector3D(deltaRollover(l.getX() - r.getX()), deltaRollover(l.getY() - r.getY()), deltaRollover(l.getZ() - r.getZ())); }
From source file:org.jtrfp.trcl.Crosshairs.java
public Crosshairs(TR tr) { super(tr);/*from w ww . ja va 2 s. c o m*/ setImmuneToOpaqueDepthTest(true); // Crosshairs Model crossModel = null; final TextureManager tm = tr.gpu.get().textureManager.get(); // Fallback final int NUM_FRAMES = 16; final double LUM_STEP = 200. / NUM_FRAMES; Texture[] greenThrobFrames = new Texture[NUM_FRAMES]; for (int f = 0; f < NUM_FRAMES; f++) { greenThrobFrames[f] = greenThrobFrames[(NUM_FRAMES - 1) - f] = (Texture) tm.solidColor( new Color((int) (f * LUM_STEP * .8), (int) (f * LUM_STEP), (int) (f * LUM_STEP * .8), 170)); } //end for(NUM_FRAMES) TextureDescription greenThrob = new AnimatedTexture(new Sequencer(80, greenThrobFrames.length, false), greenThrobFrames);/*tr.gpu.get().textureManager.get().getFallbackTexture();*/ // TODO: Set crosshairs as a player-tracking object /* * The official crosshairs. We supply the 'green throb' TARGET.BIN has a * size range of [-8192,8192], a far cry from OpenGL's [-1,1] range. * Also has a Z offset of +204,800. Scaling down by 204800 and * subtracting 1 for a Z of zero we get correct size. In the real game * TARGET.BIN is apparently appended to the player ship model itself * such that the Z protrusion is real. Furthermore, enemies try to * attack the crosshairs instead of the plane, perhaps as a kludge for * motion-compensated aiming. */ try { crossModel = tr.getResourceManager().getBINModel("TARGET.BIN", greenThrob, 1. / 204800., true, tr.getGlobalPaletteVL(), null); } catch (Exception e) { tr.showStopper(e); } final List<Triangle> tl = crossModel.getRawTriangleLists().get(0); for (Triangle t : tl) t.setCentroidNormal(Vector3D.ZERO); this.setRenderFlags((byte) 1); setModel(crossModel); this.movePositionBy(new Vector3D(0, 0, -1)); installReactiveListeners(tr); }
From source file:org.jtrfp.trcl.file.LTEFile.java
/** * Reverse-compatible form of the emissive components in ESTuTv form where:<br> * R = E<br>// w ww. j av a 2 s. c o m * G = S<br> * B = Tu<br> * A = Tv<br> * @return * @since Feb 5, 2015 */ public Color[] toColors(Color[] referencePalette) { Color[] result = new Color[256]; for (int i = 0; i < 256; i++) { final Color rColor = referencePalette[i]; final Color loColor = referencePalette[gradientIndex(i, 0)]; final Color hiColor = referencePalette[gradientIndex(i, 15)]; final double loIntensity = new Vector3D(loColor.getRed(), loColor.getGreen(), loColor.getBlue()) .getNorm(); //Brightest final double hiIntensity = new Vector3D(hiColor.getRed(), hiColor.getGreen(), hiColor.getBlue()) .getNorm(); final float[] hsbVals = new float[3]; Color.RGBtoHSB(rColor.getRed(), rColor.getGreen(), rColor.getBlue(), hsbVals); final double saturation = hsbVals[1]; double dI = Math.pow(1 - (Math.abs(hiIntensity - loIntensity) / 442.), 1); //dI = nSaturation*128; if (dI > 255) dI = 255; else if (dI < 0) dI = 0; result[i] = new Color((int) (dI * saturation * 255.), 0, 0, 0); } return result; }
From source file:org.jtrfp.trcl.flow.Mission.java
public Result go() { setMissionMode(new Mission.LoadingMode()); synchronized (missionLock) { synchronized (missionEnd) { if (missionEnd[0] != null) return missionEnd[0]; }/*from w ww .j av a2 s.co m*/ tr.getThreadManager().setPaused(true); for (ProjectileFactory pf : tr.getResourceManager().getProjectileFactories()) for (Projectile proj : pf.getProjectiles()) proj.destroy(); System.out.println("Starting GampeplayLevel loading sequence..."); final LoadingProgressReporter rootProgress = LoadingProgressReporter.Impl .createRoot(new UpdateHandler() { @Override public void update(double unitProgress) { game.getLevelLoadingScreen().setLoadingProgress(unitProgress); } }); final LoadingProgressReporter[] progressStages = rootProgress .generateSubReporters(LoadingStages.values().length); final Renderer renderer = tr.mainRenderer.get(); renderer.getCamera().probeForBehavior(SkyCubeCloudModeUpdateBehavior.class).setEnable(false); renderer.getSkyCube().setSkyCubeGen(GameShell.DEFAULT_GRADIENT); final Camera camera = renderer.getCamera(); camera.setHeading(Vector3D.PLUS_I); camera.setTop(Vector3D.PLUS_J); game.setDisplayMode(game.levelLoadingMode); game.getUpfrontDisplay().submitPersistentMessage(levelName); try { final ResourceManager rm = tr.getResourceManager(); final Player player = tr.getGame().getPlayer(); final World world = tr.getWorld(); final TDFFile tdf = rm.getTDFData(lvl.getTunnelDefinitionFile()); player.setActive(false); // Abort check synchronized (missionEnd) { if (missionEnd[0] != null) return missionEnd[0]; } overworldSystem = new OverworldSystem(tr, progressStages[LoadingStages.overworld.ordinal()]); getOverworldSystem().loadLevel(lvl, tdf); System.out.println("\t...Done."); // Install NAVs final NAVSystem navSystem = tr.getGame().getNavSystem(); navSubObjects = rm.getNAVData(lvl.getNavigationFile()).getNavObjects(); START s = (START) navSubObjects.get(0); Location3D l3d = s.getLocationOnMap(); playerStartPosition[0] = TR.legacy2Modern(l3d.getZ()); playerStartPosition[2] = TR.legacy2Modern(l3d.getX()); final double HEIGHT_PADDING = 10000; playerStartPosition[1] = Math.max( HEIGHT_PADDING + (world.sizeY / 2) * getOverworldSystem().getAltitudeMap() .heightAt(TR.legacy2MapSquare(l3d.getZ()), TR.legacy2MapSquare(l3d.getX())), TR.legacy2Modern(l3d.getY())); playerStartDirection = new ObjectDirection(s.getRoll(), s.getPitch(), s.getYaw()); // ////// INITIAL HEADING player.setPosition(getPlayerStartPosition()); player.setDirection(getPlayerStartDirection()); player.setHeading(player.getHeading().negate());// Kludge to fix // incorrect heading ///////// STATE final Propelled propelled = player.probeForBehavior(Propelled.class); propelled.setPropulsion(propelled.getMinPropulsion()); installTunnels(tdf, progressStages[LoadingStages.tunnels.ordinal()]); Factory f = new NAVObjective.Factory(tr); final LoadingProgressReporter[] navProgress = progressStages[LoadingStages.navs.ordinal()] .generateSubReporters(navSubObjects.size()); for (int i = 0; i < navSubObjects.size(); i++) { final NAVSubObject obj = navSubObjects.get(i); f.create(tr, obj, navs); navProgress[i].complete(); } // end for(navSubObjects) navSystem.updateNAVState(); player.resetVelocityRotMomentum(); final String startX = System.getProperty("org.jtrfp.trcl.startX"); final String startY = System.getProperty("org.jtrfp.trcl.startY"); final String startZ = System.getProperty("org.jtrfp.trcl.startZ"); final double[] playerPos = player.getPosition(); if (startX != null && startY != null && startZ != null) { System.out.println("Using user-specified start point"); final int sX = Integer.parseInt(startX); final int sY = Integer.parseInt(startY); final int sZ = Integer.parseInt(startZ); playerPos[0] = sX; playerPos[1] = sY; playerPos[2] = sZ; player.notifyPositionChange(); } // end if(user start point) System.out.println("Start position set to " + player.getPosition()[0] + " " + player.getPosition()[1] + " " + player.getPosition()[2]); System.out.println("Setting sun vector"); final AbstractTriplet sunVector = lvl.getSunlightDirectionVector(); tr.getThreadManager().submitToGL(new Callable<Void>() { @Override public Void call() throws Exception { tr.mainRenderer.get().setSunVector( new Vector3D(sunVector.getX(), sunVector.getY(), sunVector.getZ()).normalize()); return null; } }).get(); System.out.println("\t...Done."); } catch (Exception e) { e.printStackTrace(); } if (System.getProperties().containsKey("org.jtrfp.trcl.flow.Mission.skipNavs")) { try { final int skips = Integer.parseInt(System.getProperty("org.jtrfp.trcl.flow.Mission.skipNavs")); System.out.println("Skipping " + skips + " navs."); for (int i = 0; i < skips; i++) { removeNAVObjective(currentNAVObjective()); } // end for(skips) } catch (NumberFormatException e) { System.err.println( "Invalid format for property \"org.jtrfp.trcl.flow.Mission.skipNavs\". Must be integer."); } } // end if(containsKey) //System.out.println("Invoking JVM's garbage collector..."); //TR.nuclearGC(); //System.out.println("Mission.go() complete."); // Transition to gameplay mode. // Abort check synchronized (missionEnd) { if (missionEnd[0] != null) return missionEnd[0]; } //end sync(missionEnd) tr.getThreadManager().submitToThreadPool(new Callable<Void>() { @Override public Void call() throws Exception { final SoundSystem ss = Mission.this.tr.soundSystem.get(); MusicPlaybackEvent evt; Mission.this.tr.soundSystem.get().enqueuePlaybackEvent(evt = ss.getMusicFactory().create( new GPUResidentMOD(tr, tr.getResourceManager().getMOD(lvl.getBackgroundMusicFile())), true)); synchronized (Mission.this) { if (bgMusic != null) return null; bgMusic = evt; bgMusic.play(); } //end sync(Mission.this) return null; }// end call() }); game.getUpfrontDisplay().removePersistentMessage(); tr.getThreadManager().setPaused(false); if (showIntro) { setMissionMode(new Mission.IntroMode()); game.getBriefingScreen().briefingSequence(lvl); } setMissionMode(new Mission.AboveGroundMode()); getOverworldSystem().activate(); final SkySystem skySystem = getOverworldSystem().getSkySystem(); tr.mainRenderer.get().getCamera().probeForBehavior(SkyCubeCloudModeUpdateBehavior.class) .setEnable(true); renderer.getSkyCube().setSkyCubeGen(skySystem.getBelowCloudsSkyCubeGen()); renderer.setAmbientLight(skySystem.getSuggestedAmbientLight()); renderer.setSunColor(skySystem.getSuggestedSunColor()); game.getNavSystem().activate(); game.setDisplayMode(game.gameplayMode); game.getPlayer().setActive(true); tr.getGame().setPaused(false); //Wait for mission end synchronized (missionEnd) { while (missionEnd[0] == null) { try { missionEnd.wait(); } catch (InterruptedException e) { break; } } } //Completion summary if (missionEnd[0] != null) if (!missionEnd[0].isAbort()) { setMissionMode(new Mission.MissionSummaryMode()); game.getBriefingScreen().missionCompleteSummary(lvl, missionEnd[0]); } //end if(proper ending) tr.getThreadManager().submitToThreadPool(new Callable<Void>() { @Override public Void call() throws Exception { bgMusic.stop(); return null; }// end call() }); cleanup(); return missionEnd[0]; } //end sync }
From source file:org.jtrfp.trcl.flow.Mission.java
public TunnelEntranceObject getNearestTunnelEntrance(double xInLegacyUnits, double yInLegacyUnits, double zInLegacyUnits) { TunnelEntranceObject result = null;/* w w w .jav a2 s . c o m*/ double closestDistance = Double.POSITIVE_INFINITY; final Vector3D entPos = new Vector3D(TR.legacy2Modern(zInLegacyUnits), //Intentionally backwards TR.legacy2Modern(yInLegacyUnits), TR.legacy2Modern(xInLegacyUnits)); System.out.println("Requested entry pos=" + entPos); for (TunnelEntranceObject teo : tunnelMap.values()) { final Vector3D pos = new Vector3D(teo.getPosition()); System.out.println("Found tunnel at " + pos); final double distance = pos.distance(entPos); if (distance < closestDistance) { closestDistance = distance; result = teo; } } // end for(tunnels) return result; }
From source file:org.jtrfp.trcl.InterpolatingAltitudeMap.java
public Vector3D normalAt(double x, double z) { final double magX = (heightAt(x - NUDGE, z) - heightAt(x + NUDGE, z)) / NUDGE; final double magZ = (heightAt(x, z - NUDGE) - heightAt(x, z + NUDGE)) / NUDGE; final double magY = Math.sqrt(1 - (magX * magX + magZ * magZ)); return new Vector3D(magX, magY, magZ).normalize(); }
From source file:org.jtrfp.trcl.LineSegment.java
public static Triangle[] buildTriPipe(Vector3D start, Vector3D end, TextureDescription texture, int thickness, Triangle[] dest, int destOffset) { Rotation rot = new Rotation(Vector3D.PLUS_K, end.subtract(start).normalize()); final double len = start.distance(end); // Start//from www . j ava 2 s . c om Vector3D sbl = new Vector3D(-thickness, -thickness, 0);// bottom left Vector3D sbr = new Vector3D(thickness, -thickness, 0);// bottom right Vector3D stp = new Vector3D(0, thickness, 0); // End Vector3D ebl = new Vector3D(-thickness, -thickness, len); Vector3D ebr = new Vector3D(thickness, -thickness, len); Vector3D etp = new Vector3D(0, thickness, len); Vector3D cl = new Vector3D(-1, 1, 0).normalize(); Vector3D cr = new Vector3D(1, 1, 0).normalize(); Vector3D cb = new Vector3D(0, -1, 0); cl = rot.applyTo(cl); cr = rot.applyTo(cr); cb = rot.applyTo(cb); sbl = rot.applyTo(sbl).add(start); sbr = rot.applyTo(sbr).add(start); stp = rot.applyTo(stp).add(start); ebl = rot.applyTo(ebl).add(start); ebr = rot.applyTo(ebr).add(start); etp = rot.applyTo(etp).add(start); final double u[] = { 0, 1, 1, 0 }; final double v[] = { 1, 1, 0, 0 }; // TOP LEFT Triangle.quad2Triangles(new double[] { sbl.getX(), stp.getX(), etp.getX(), ebl.getX() }, new double[] { sbl.getY(), stp.getY(), etp.getY(), ebl.getY() }, new double[] { sbl.getZ(), stp.getZ(), etp.getZ(), ebl.getZ() }, u, v, texture, RenderMode.STATIC, false, cl, dest, destOffset, "LineSegment.topLeft"); // TOP RIGHT Triangle.quad2Triangles(new double[] { sbr.getX(), stp.getX(), etp.getX(), ebr.getX() }, new double[] { sbr.getY(), stp.getY(), etp.getY(), ebr.getY() }, new double[] { sbr.getZ(), stp.getZ(), etp.getZ(), ebr.getZ() }, u, v, texture, RenderMode.STATIC, false, cr, dest, destOffset + 2, "LineSegment.topRight"); // BOTTOM Triangle.quad2Triangles(new double[] { sbl.getX(), sbr.getX(), ebr.getX(), ebl.getX() }, new double[] { sbl.getY(), sbr.getY(), ebr.getY(), ebl.getY() }, new double[] { sbr.getZ(), sbr.getZ(), ebr.getZ(), ebl.getZ() }, u, v, texture, RenderMode.STATIC, false, cb, dest, destOffset + 4, "LineSegment.bottom"); return dest; }