⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rectangularnormaltessellator.java

📁 world wind java sdk 源码
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/*
Copyright (C) 2001, 2009 United States Government
as represented by the Administrator of the
National Aeronautics and Space Administration.
All Rights Reserved.
*/
package gov.nasa.worldwind.examples.sunlight;

import com.sun.opengl.util.BufferUtil;
import gov.nasa.worldwind.*;
import gov.nasa.worldwind.terrain.*;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.cache.*;
import gov.nasa.worldwind.geom.*;
import gov.nasa.worldwind.globes.Globe;
import gov.nasa.worldwind.pick.*;
import gov.nasa.worldwind.render.*;
import gov.nasa.worldwind.util.Logging;

import javax.media.opengl.GL;
import java.awt.*;
import java.nio.*;
import java.util.*;
import java.util.List;

/**
 * @author tag
 * @version $Id: RectangularNormalTessellator.java 10406 2009-04-22 18:28:45Z patrickmurris $
 *
 *          Modified by Michael de Hoog to add simple normals based on globe
 *          ellipse, (globe.computeSurfaceNormalAtPoint()), also added more
 *          exact normal calculator for terrain tiles, see getNormals()
 */
public class RectangularNormalTessellator extends WWObjectImpl implements Tessellator
{
    protected static class RenderInfo
    {
        private final int density;
        private final Vec4 referenceCenter;
        private final DoubleBuffer vertices;
        private final DoubleBuffer normals;
        private final DoubleBuffer texCoords;
        private final IntBuffer indices;
        private final long time;

        private RenderInfo(int density, DoubleBuffer vertices, DoubleBuffer texCoords, DoubleBuffer normals, Vec4 refCenter)
        {
            this.density = density;
            this.vertices = vertices;
            this.texCoords = texCoords;
            this.referenceCenter = refCenter;
            this.indices = getIndices(this.density);
            this.normals = normals;
            this.time = System.currentTimeMillis();
        }

        private long getSizeInBytes()
        {
            // Texture coordinates are shared among all tiles of the same density, so do not count towards size.
            // 8 references, doubles in buffer.
            return 8 * 4 + (this.vertices.limit()) * Double.SIZE;
        }
    }

	public static class RectTile implements SectorGeometry
	{
		private final RectangularNormalTessellator tessellator;
		private final int level;
		private final Sector sector;
		private final int density;
		private final double log10CellSize;
		private Extent extent; // extent of sector in object coordinates
		private RenderInfo ri;

		private int minColorCode = 0;
		private int maxColorCode = 0;

		public RectTile(RectangularNormalTessellator tessellator, Extent extent,
				int level, int density, Sector sector, double cellSize)
		{
			this.tessellator = tessellator;
			this.level = level;
			this.density = density;
			this.sector = sector;
			this.extent = extent;
			this.log10CellSize = Math.log10(cellSize);
		}

		public Sector getSector()
		{
			return this.sector;
		}

		public Extent getExtent()
		{
			return this.extent;
		}

		public void renderMultiTexture(DrawContext dc, int numTextureUnits)
		{
			this.tessellator.renderMultiTexture(dc, this, numTextureUnits);
		}

		public void render(DrawContext dc)
		{
			this.tessellator.render(dc, this);
		}

		public void renderWireframe(DrawContext dc, boolean showTriangles,
				boolean showTileBoundary)
		{
			this.tessellator.renderWireframe(dc, this, showTriangles,
					showTileBoundary);
		}

		public void renderBoundingVolume(DrawContext dc)
		{
			this.tessellator.renderBoundingVolume(dc, this);
		}

		public PickedObject[] pick(DrawContext dc, List<? extends Point> pickPoints)
		{
			return this.tessellator.pick(dc, this, pickPoints);
		}

		public void pick(DrawContext dc, Point pickPoint)
		{
			this.tessellator.pick(dc, this, pickPoint);
		}

		public Vec4 getSurfacePoint(Angle latitude, Angle longitude,
				double metersOffset)
		{
			return this.tessellator.getSurfacePoint(this, latitude, longitude,
					metersOffset);
		}

        public double getResolution()
        {
            return this.sector.getDeltaLatRadians() / this.density;
        }

        public Intersection[] intersect(Line line)
        {
            return this.tessellator.intersect(this, line);
        }

        public Intersection[] intersect(double elevation)
        {
            return this.tessellator.intersect(this,elevation);
        }

        public DoubleBuffer makeTextureCoordinates(GeographicTextureCoordinateComputer computer)
        {
            return this.tessellator.makeGeographicTexCoords(this, computer);
        }

        public ExtractedShapeDescription getIntersectingTessellationPieces(Plane[] p)
        {
            return this.tessellator.getIntersectingTessellationPieces(this,p);
        }

        public ExtractedShapeDescription getIntersectingTessellationPieces(Vec4 Cxyz,
            Vec4 uHat, Vec4 vHat, double uRadius, double vRadius)
        {
            return this.tessellator.getIntersectingTessellationPieces(this,Cxyz,
                uHat,vHat,uRadius,vRadius);
        }
	}

    private static class CacheKey
    {
        private final Sector sector;
        private final int density;
        private final Object globeStateKey;

        public CacheKey(DrawContext dc, Sector sector, int density)
        {
            this.sector = sector;
            this.density = density;
            this.globeStateKey = dc.getGlobe().getStateKey(dc);
        }

        @SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"})
        public boolean equals(Object o)
        {
            if (this == o) return true;

            CacheKey cacheKey = (CacheKey) o; // Note: no check of class type equivalence, for performance

            if (density != cacheKey.density) return false;
            if (globeStateKey != null ? !globeStateKey.equals(cacheKey.globeStateKey) : cacheKey.globeStateKey != null)
                return false;
            //noinspection RedundantIfStatement
            if (sector != null ? !sector.equals(cacheKey.sector) : cacheKey.sector != null) return false;

            return true;
        }

        public int hashCode()
        {
            int result;
            result = (sector != null ? sector.hashCode() : 0);
            result = 31 * result + density;
            result = 31 * result + (globeStateKey != null ? globeStateKey.hashCode() : 0);
            return result;
        }
    }

	// TODO: Make all this configurable
	private static final double DEFAULT_LOG10_RESOLUTION_TARGET = 1.3;
	private static final int DEFAULT_MAX_LEVEL = 12;
	private static final int DEFAULT_NUM_LAT_SUBDIVISIONS = 5;
	private static final int DEFAULT_NUM_LON_SUBDIVISIONS = 10;
	private static final int DEFAULT_DENSITY = 20;
	private static final String CACHE_NAME = "Terrain";
	private static final String CACHE_ID = RectangularNormalTessellator.class.getName();

	// Tri-strip indices and texture coordinates. These depend only on density and can therefore be statically cached.
	private static final HashMap<Integer, DoubleBuffer> parameterizations = new HashMap<Integer, DoubleBuffer>();
	private static final HashMap<Integer, IntBuffer> indexLists = new HashMap<Integer, IntBuffer>();

	private ArrayList<RectTile> topLevels;
	private PickSupport pickSupport = new PickSupport();
	private SectorGeometryList currentTiles = new SectorGeometryList();
	private Frustum currentFrustum;
	private Sector currentCoverage; // union of all tiles selected during call to render()
	private boolean makeTileSkirts = true;
	private int currentLevel;
	private int maxLevel = DEFAULT_MAX_LEVEL;
	private Globe globe;
	private int density = DEFAULT_DENSITY;

    // Lighting
    private Vec4 lightDirection;
    private Material material = new Material(Color.WHITE);
    private Color lightColor = Color.WHITE;
    private Color ambientColor = new Color(.1f, .1f, .1f);

    public SectorGeometryList tessellate(DrawContext dc)
	{
		if (dc == null)
		{
			String msg = Logging.getMessage("nullValue.DrawContextIsNull");
			Logging.logger().severe(msg);
			throw new IllegalArgumentException(msg);
		}

		if (dc.getView() == null)
		{
			String msg = Logging.getMessage("nullValue.ViewIsNull");
			Logging.logger().severe(msg);
			throw new IllegalStateException(msg);
		}

		if (!WorldWind.getMemoryCacheSet().containsCache(CACHE_ID))
		{
			long size = Configuration.getLongValue(
					AVKey.SECTOR_GEOMETRY_CACHE_SIZE, 20000000L);
			MemoryCache cache = new BasicMemoryCache((long) (0.85 * size), size);
			cache.setName(CACHE_NAME);
			WorldWind.getMemoryCacheSet().addCache(CACHE_ID, cache);
		}

		if (this.topLevels == null)
			this.topLevels = this.createTopLevelTiles(dc);

		this.currentTiles.clear();
		this.currentLevel = 0;
		this.currentCoverage = null;

		this.currentFrustum = dc.getView().getFrustumInModelCoordinates();
		for (RectTile tile : this.topLevels)
		{
			this.selectVisibleTiles(dc, tile);
		}

		this.currentTiles.setSector(this.currentCoverage);

		for (SectorGeometry tile : this.currentTiles)
		{
			this.makeVerts(dc, (RectTile) tile);
		}

		return this.currentTiles;
	}

	private ArrayList<RectTile> createTopLevelTiles(DrawContext dc)
	{
		ArrayList<RectTile> tops = new ArrayList<RectTile>(
				DEFAULT_NUM_LAT_SUBDIVISIONS * DEFAULT_NUM_LON_SUBDIVISIONS);

		this.globe = dc.getGlobe();
		double deltaLat = 180d / DEFAULT_NUM_LAT_SUBDIVISIONS;
		double deltaLon = 360d / DEFAULT_NUM_LON_SUBDIVISIONS;
		Angle lastLat = Angle.NEG90;

		for (int row = 0; row < DEFAULT_NUM_LAT_SUBDIVISIONS; row++)
		{
			Angle lat = lastLat.addDegrees(deltaLat);
			if (lat.getDegrees() + 1d > 90d)
				lat = Angle.POS90;

			Angle lastLon = Angle.NEG180;

			for (int col = 0; col < DEFAULT_NUM_LON_SUBDIVISIONS; col++)
			{
				Angle lon = lastLon.addDegrees(deltaLon);
				if (lon.getDegrees() + 1d > 180d)
					lon = Angle.POS180;

				Sector tileSector = new Sector(lastLat, lat, lastLon, lon);
				tops.add(this.createTile(dc, tileSector, 0));
				lastLon = lon;
			}
			lastLat = lat;
		}

		return tops;
	}

	private RectTile createTile(DrawContext dc, Sector tileSector, int level)
	{
		Cylinder cylinder = dc.getGlobe().computeBoundingCylinder(
				dc.getVerticalExaggeration(), tileSector);
		double cellSize = tileSector.getDeltaLatRadians()
				* dc.getGlobe().getRadius() / this.density;

		return new RectTile(this, cylinder, level, this.density, tileSector,
				cellSize);
	}

	public boolean isMakeTileSkirts()
	{
		return makeTileSkirts;
	}

	public void setMakeTileSkirts(boolean makeTileSkirts)
	{
		this.makeTileSkirts = makeTileSkirts;
	}

    public Vec4 getLightDirection()
    {
        return this.lightDirection;
    }

    public void setLightDirection(Vec4 direction)
    {
        this.lightDirection = direction;
    }

    public Color getLightColor()
    {
        return this.lightColor;
    }

    public void setLightColor(Color color)
    {
        if (color == null)
        {
            String msg = Logging.getMessage("nullValue.ColorIsNull");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }
        this.lightColor = color;
    }

    public Color getAmbientColor()
    {
        return this.ambientColor;
    }

    public void setAmbientColor(Color color)
    {
        if (color == null)
        {
            String msg = Logging.getMessage("nullValue.ColorIsNull");
            Logging.logger().severe(msg);
            throw new IllegalArgumentException(msg);
        }
        this.ambientColor = color;
    }

//	public int getTargetResolution(DrawContext dc, RectTile tile)
//	{
//		return dc.getGlobe().getElevationModel().getTargetResolution(dc, tile.sector, tile.density);
//	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -