S3DB: roof shape profiles (#744)
This commit is contained in:
@@ -28,7 +28,7 @@ import org.oscim.theme.VtmThemes;
|
|||||||
public class ExtrusionsTest extends GdxMapApp {
|
public class ExtrusionsTest extends GdxMapApp {
|
||||||
|
|
||||||
enum GroundShape {
|
enum GroundShape {
|
||||||
HEXAGON, RECTANGLE, SHAPE_L, SHAPE_O, SHAPE_T, SHAPE_U, SHAPE_V, SHAPE_X, SHAPE_Z, TEST
|
HEXAGON, RECTANGLE, SHAPE_L, SHAPE_M, SHAPE_O, SHAPE_T, SHAPE_U, SHAPE_V, SHAPE_X, SHAPE_Z, TEST
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -123,6 +123,9 @@ public class ExtrusionsTest extends GdxMapApp {
|
|||||||
case SHAPE_L:
|
case SHAPE_L:
|
||||||
shapeLGround(e);
|
shapeLGround(e);
|
||||||
break;
|
break;
|
||||||
|
case SHAPE_M:
|
||||||
|
shapeMGround(e);
|
||||||
|
break;
|
||||||
case SHAPE_O:
|
case SHAPE_O:
|
||||||
shapeOGround(e);
|
shapeOGround(e);
|
||||||
break;
|
break;
|
||||||
@@ -181,6 +184,19 @@ public class ExtrusionsTest extends GdxMapApp {
|
|||||||
e.addPoint(0, 10);
|
e.addPoint(0, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void shapeMGround(MapElement e) {
|
||||||
|
e.addPoint(0, 0);
|
||||||
|
e.addPoint(10, 0);
|
||||||
|
e.addPoint(10, 5);
|
||||||
|
e.addPoint(20, 5);
|
||||||
|
e.addPoint(20, 20);
|
||||||
|
e.addPoint(37, 20);
|
||||||
|
e.addPoint(37, 25);
|
||||||
|
e.addPoint(12, 25);
|
||||||
|
e.addPoint(12, 15);
|
||||||
|
e.addPoint(0, 15);
|
||||||
|
}
|
||||||
|
|
||||||
private void shapeOGround(MapElement e) {
|
private void shapeOGround(MapElement e) {
|
||||||
hexagonGround(e);
|
hexagonGround(e);
|
||||||
e.reverse();
|
e.reverse();
|
||||||
|
|||||||
@@ -16,12 +16,7 @@
|
|||||||
package org.oscim.layers.tile.buildings;
|
package org.oscim.layers.tile.buildings;
|
||||||
|
|
||||||
import org.oscim.backend.canvas.Color;
|
import org.oscim.backend.canvas.Color;
|
||||||
import org.oscim.core.Box;
|
import org.oscim.core.*;
|
||||||
import org.oscim.core.GeometryBuffer;
|
|
||||||
import org.oscim.core.MapElement;
|
|
||||||
import org.oscim.core.Tag;
|
|
||||||
import org.oscim.core.TagSet;
|
|
||||||
import org.oscim.core.Tile;
|
|
||||||
import org.oscim.layers.tile.MapTile;
|
import org.oscim.layers.tile.MapTile;
|
||||||
import org.oscim.layers.tile.vector.VectorTileLayer;
|
import org.oscim.layers.tile.vector.VectorTileLayer;
|
||||||
import org.oscim.map.Map;
|
import org.oscim.map.Map;
|
||||||
@@ -302,12 +297,12 @@ public class S3DBLayer extends BuildingLayer {
|
|||||||
case Tag.VALUE_GABLED:
|
case Tag.VALUE_GABLED:
|
||||||
case Tag.VALUE_GAMBREL:
|
case Tag.VALUE_GAMBREL:
|
||||||
specialParts = new GeometryBuffer(0, 0); // No data in GeometryBuffer needed
|
specialParts = new GeometryBuffer(0, 0); // No data in GeometryBuffer needed
|
||||||
success = S3DBUtils.calcRidgeMesh(gElement, minHeight, maxHeight, roofOrientationAcross, true, specialParts);
|
success = S3DBUtils.calcRidgeMesh(gElement, minHeight, maxHeight, roofOrientationAcross, v, specialParts);
|
||||||
break;
|
break;
|
||||||
case Tag.VALUE_MANSARD:
|
case Tag.VALUE_MANSARD:
|
||||||
case Tag.VALUE_HALF_HIPPED:
|
case Tag.VALUE_HALF_HIPPED:
|
||||||
case Tag.VALUE_HIPPED:
|
case Tag.VALUE_HIPPED:
|
||||||
success = S3DBUtils.calcRidgeMesh(gElement, minHeight, maxHeight, roofOrientationAcross, false, null);
|
success = S3DBUtils.calcRidgeMesh(gElement, minHeight, maxHeight, roofOrientationAcross, v, null);
|
||||||
break;
|
break;
|
||||||
case Tag.VALUE_SKILLION:
|
case Tag.VALUE_SKILLION:
|
||||||
// ROOF_SLOPE_DIRECTION is not supported yet
|
// ROOF_SLOPE_DIRECTION is not supported yet
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public final class S3DBUtils {
|
|||||||
* @param element the GeometryBuffer which is used to write the 3D mesh
|
* @param element the GeometryBuffer which is used to write the 3D mesh
|
||||||
* @return true if calculation succeeded, false otherwise
|
* @return true if calculation succeeded, false otherwise
|
||||||
*/
|
*/
|
||||||
public static boolean calcCircleMesh(GeometryBuffer element, float minHeight, float maxHeight, String type) {
|
public static boolean calcCircleMesh(GeometryBuffer element, float minHeight, float maxHeight, String roofShape) {
|
||||||
float[] points = element.points;
|
float[] points = element.points;
|
||||||
int[] index = element.index;
|
int[] index = element.index;
|
||||||
|
|
||||||
@@ -81,30 +81,7 @@ public final class S3DBUtils {
|
|||||||
|
|
||||||
// Init mesh
|
// Init mesh
|
||||||
GeometryBuffer mesh;
|
GeometryBuffer mesh;
|
||||||
switch (type) {
|
mesh = initCircleMesh(getProfile(roofShape), numSections);
|
||||||
case Tag.VALUE_ONION:
|
|
||||||
float[][] onionShape = new float[][]{
|
|
||||||
{1, 0, 0},
|
|
||||||
{0.2f, 0, 0.01f},
|
|
||||||
{0.875f, 0, 0.1875f},
|
|
||||||
{1, 0, 0.375f},
|
|
||||||
{0.875f, 0, 0.5625f},
|
|
||||||
{0.5f, 0, 0.75f},
|
|
||||||
{0.2f, 0, 0.8125f},
|
|
||||||
{0, 0, 1}};
|
|
||||||
mesh = initCircleMesh(onionShape, numSections);
|
|
||||||
break;
|
|
||||||
case Tag.VALUE_DOME:
|
|
||||||
default:
|
|
||||||
float[][] domeShape = new float[][]{
|
|
||||||
{1, 0, 0},
|
|
||||||
{0.825f, 0, 0.5f},
|
|
||||||
{0.5f, 0, 0.825f},
|
|
||||||
{0, 0, 1}};
|
|
||||||
mesh = initCircleMesh(domeShape, numSections);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Calculate center and load points
|
// Calculate center and load points
|
||||||
float centerX = 0;
|
float centerX = 0;
|
||||||
@@ -363,14 +340,16 @@ public final class S3DBUtils {
|
|||||||
* @param minHeight the minimum height
|
* @param minHeight the minimum height
|
||||||
* @param maxHeight the maximum height
|
* @param maxHeight the maximum height
|
||||||
* @param orientationAcross indicates if ridge is parallel to short side
|
* @param orientationAcross indicates if ridge is parallel to short side
|
||||||
* @param isGabled indicates if should calculate a gable
|
* @param roofShape the roof shape
|
||||||
* @param specialParts element to add missing parts of underlying element
|
* @param specialParts element to add missing parts of underlying element
|
||||||
* @return true if calculation succeeded, false otherwise
|
* @return true if calculation succeeded, false otherwise
|
||||||
*/
|
*/
|
||||||
public static boolean calcRidgeMesh(GeometryBuffer element, float minHeight, float maxHeight, boolean orientationAcross, boolean isGabled, GeometryBuffer specialParts) {
|
public static boolean calcRidgeMesh(GeometryBuffer element, float minHeight, float maxHeight, boolean orientationAcross, String roofShape, GeometryBuffer specialParts) {
|
||||||
float[] points = element.points;
|
float[] points = element.points;
|
||||||
int[] index = element.index;
|
int[] index = element.index;
|
||||||
|
|
||||||
|
boolean isGabled = isGabled(roofShape);
|
||||||
|
|
||||||
for (int i = 0, pointPos = 0; i < index.length; i++) {
|
for (int i = 0, pointPos = 0; i < index.length; i++) {
|
||||||
if (index[i] < 0) {
|
if (index[i] < 0) {
|
||||||
break;
|
break;
|
||||||
@@ -395,9 +374,10 @@ public final class S3DBUtils {
|
|||||||
point3Fs.add(new float[]{x, y, minHeight});
|
point3Fs.add(new float[]{x, y, minHeight});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calc vectors
|
// Number of ground points
|
||||||
int groundSize = point3Fs.size();
|
int groundSize = point3Fs.size();
|
||||||
|
|
||||||
|
// Calc vectors
|
||||||
List<Float> lengths = new ArrayList<>();
|
List<Float> lengths = new ArrayList<>();
|
||||||
List<float[]> normVectors = GeometryUtils.normalizedVectors2D(point3Fs, lengths);
|
List<float[]> normVectors = GeometryUtils.normalizedVectors2D(point3Fs, lengths);
|
||||||
|
|
||||||
@@ -627,9 +607,13 @@ public final class S3DBUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float[][] profile = getProfile(roofShape);
|
||||||
|
int profileSize = profile.length - 2;
|
||||||
|
int profileSizePlus = profile.length - 1; // profile roof shape size + ground size (+1)
|
||||||
|
|
||||||
// Allocate the indices to the points
|
// Allocate the indices to the points
|
||||||
int ridgePointSize = ridgePoints.size();
|
int ridgePointSize = ridgePoints.size();
|
||||||
float[] meshPoints = new float[(groundSize + ridgePointSize) * 3]; //(ridgePoints * 3 = 6)
|
float[] meshPoints = new float[(groundSize * profileSizePlus + ridgePointSize) * 3]; //(ridgePoints * 3 = 6)
|
||||||
List<Integer> meshVarIndex = new ArrayList<>();
|
List<Integer> meshVarIndex = new ArrayList<>();
|
||||||
|
|
||||||
// Add special building parts
|
// Add special building parts
|
||||||
@@ -638,41 +622,93 @@ public final class S3DBUtils {
|
|||||||
meshPartVarIndex = new ArrayList<>();
|
meshPartVarIndex = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int k = 0; k < groundSize; k++) {
|
float heightRange = maxHeight - minHeight;
|
||||||
|
|
||||||
|
// Number of 3D-points for the roof (groundSize * inner profile + groundSize)
|
||||||
|
int grRsSize = groundSize * profileSizePlus;
|
||||||
|
|
||||||
|
// WRITE MESH
|
||||||
|
|
||||||
|
for (int l = 0; l < groundSize; l++) {
|
||||||
|
// l: #ground points
|
||||||
|
// k: #(shape points + ground points)
|
||||||
|
int k = l * profileSizePlus;
|
||||||
|
|
||||||
// Add first face
|
// Add first face
|
||||||
float[] p = point3Fs.get(k);
|
float[] p = point3Fs.get(l);
|
||||||
int ridgePointIndex1 = k;
|
int ridgePointIndex1 = l;
|
||||||
while (!ridgePoints.containsKey(ridgePointIndex1)) {
|
while (!ridgePoints.containsKey(ridgePointIndex1)) {
|
||||||
ridgePointIndex1 = (ridgePointIndex1 + groundSize - 1) % groundSize; // Decrease ridgePointIndex
|
ridgePointIndex1 = (ridgePointIndex1 + groundSize - 1) % groundSize; // Decrease ridgePointIndex until a ridge point is found for the k point.
|
||||||
}
|
}
|
||||||
int ridgeIndex1 = ridgePoints.headMap(ridgePointIndex1).size(); // set ridgeIndex to shift in ridgePoints
|
int ridgeIndex1 = ridgePoints.headMap(ridgePointIndex1).size(); // set ridgeIndex to shift in ridgePoints
|
||||||
if (meshPartVarIndex != null && gablePoints.contains(ridgePointIndex1) && getIndexNextTurn(ridgePointIndex1, simpleAngles).equals(getIndexNextTurn(k, simpleAngles))) {
|
boolean isGable = false;
|
||||||
meshPartVarIndex.add(k);
|
if (meshPartVarIndex != null && gablePoints.contains(ridgePointIndex1) && getIndexNextTurn(ridgePointIndex1, simpleAngles).equals(getIndexNextTurn(l, simpleAngles))) {
|
||||||
meshPartVarIndex.add((k + 1) % groundSize);
|
isGable = true;
|
||||||
meshPartVarIndex.add(ridgeIndex1 + groundSize);
|
// Add missing parts to building
|
||||||
|
meshPartVarIndex.add(k + profileSize);
|
||||||
|
meshPartVarIndex.add((k + profileSizePlus + profileSize) % grRsSize);
|
||||||
|
meshPartVarIndex.add(ridgeIndex1 + grRsSize);
|
||||||
} else {
|
} else {
|
||||||
meshVarIndex.add(k);
|
// Add first roof face
|
||||||
meshVarIndex.add((k + 1) % groundSize);
|
meshVarIndex.add(k + profileSize);
|
||||||
meshVarIndex.add(ridgeIndex1 + groundSize);
|
meshVarIndex.add((k + profileSizePlus + profileSize) % grRsSize);
|
||||||
|
meshVarIndex.add(ridgeIndex1 + grRsSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add second face, if necessary
|
// Add second face, if necessary
|
||||||
int ridgePointIndex2 = (k + 1) % groundSize;
|
int ridgePointIndex2 = (l + 1) % groundSize;
|
||||||
while (!ridgePoints.containsKey(ridgePointIndex2)) {
|
while (!ridgePoints.containsKey(ridgePointIndex2)) {
|
||||||
ridgePointIndex2 = (ridgePointIndex2 + groundSize - 1) % groundSize; // Decrease ridgePointIndex
|
ridgePointIndex2 = (ridgePointIndex2 + groundSize - 1) % groundSize; // Decrease ridgePointIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ridgePointIndex2 != ridgePointIndex1) {
|
if (ridgePointIndex2 != ridgePointIndex1) {
|
||||||
int ridgeIndex2 = ridgePoints.headMap(ridgePointIndex2).size(); // Set ridgeIndex to position in ridgePoints
|
int ridgeIndex2 = ridgePoints.headMap(ridgePointIndex2).size(); // Set ridgeIndex to position in ridgePoints
|
||||||
meshVarIndex.add(ridgeIndex1 + groundSize);
|
meshVarIndex.add(ridgeIndex1 + grRsSize);
|
||||||
meshVarIndex.add((k + 1) % groundSize);
|
meshVarIndex.add((k + profileSizePlus + profileSize) % grRsSize);
|
||||||
meshVarIndex.add(ridgeIndex2 + groundSize);
|
meshVarIndex.add(ridgeIndex2 + grRsSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write points
|
// Write ground points
|
||||||
meshPoints[3 * k + 0] = p[0];
|
int offset = 3 * k;
|
||||||
meshPoints[3 * k + 1] = p[1];
|
meshPoints[offset + 0] = p[0];
|
||||||
meshPoints[3 * k + 2] = p[2];
|
meshPoints[offset + 1] = p[1];
|
||||||
|
meshPoints[offset + 2] = p[2];
|
||||||
|
|
||||||
|
// Write profile roof shape points, skip ground points and ridge points of profile
|
||||||
|
float[] rp1 = ridgePoints.get(ridgePointIndex1);
|
||||||
|
float[] dif = GeometryUtils.diffVec(p, rp1); // Vector from ridge point to ground point
|
||||||
|
float phi = (float) Math.atan2(dif[0], dif[1]); // direction of diff
|
||||||
|
float r = (float) GeometryUtils.length(dif);
|
||||||
|
for (int m = 1; m < profileSizePlus; m++) {
|
||||||
|
offset = 3 * (k + m); // (+ 1 - 1 = 0)
|
||||||
|
int o = k + m - 1; // the ground + actual point of profile (m = 0 is the ground point)
|
||||||
|
|
||||||
|
// Add profile roof faces (2 per side and profile point)
|
||||||
|
if (isGable) {
|
||||||
|
// Add missing parts to building
|
||||||
|
meshPartVarIndex.add(o); // ground
|
||||||
|
meshPartVarIndex.add((o + profileSizePlus) % grRsSize); // ground
|
||||||
|
meshPartVarIndex.add((o + 1) % grRsSize); // profile
|
||||||
|
|
||||||
|
meshPartVarIndex.add((o + profileSizePlus) % grRsSize); // ground + 1
|
||||||
|
meshPartVarIndex.add((o + 1 + profileSizePlus) % grRsSize); // profile
|
||||||
|
meshPartVarIndex.add((o + 1) % grRsSize); // profile
|
||||||
|
} else {
|
||||||
|
meshVarIndex.add(o); // ground
|
||||||
|
meshVarIndex.add((o + profileSizePlus) % grRsSize); // ground + 1
|
||||||
|
meshVarIndex.add((o + 1) % grRsSize); // profile
|
||||||
|
|
||||||
|
meshVarIndex.add((o + profileSizePlus) % grRsSize); // ground + 1
|
||||||
|
meshVarIndex.add((o + 1 + profileSizePlus) % grRsSize); // profile + 1
|
||||||
|
meshVarIndex.add((o + 1) % grRsSize); // profile
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate position of profile point.
|
||||||
|
// profile[m][0] is same length for x and y
|
||||||
|
meshPoints[offset + 0] = rp1[0] + (float) (r * profile[m][0] * Math.sin(phi));
|
||||||
|
meshPoints[offset + 1] = rp1[1] + (float) (r * profile[m][0] * Math.cos(phi));
|
||||||
|
meshPoints[offset + 2] = p[2] + heightRange * profile[m][2];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tessellate top, if necessary (can be used to improve wrong rendered roofs)
|
// Tessellate top, if necessary (can be used to improve wrong rendered roofs)
|
||||||
@@ -723,7 +759,7 @@ public final class S3DBUtils {
|
|||||||
if (Tessellator.tessellate(buffer, buffer) != 0) {
|
if (Tessellator.tessellate(buffer, buffer) != 0) {
|
||||||
for (int ind : buffer.index) {
|
for (int ind : buffer.index) {
|
||||||
// Get position in ridgePoints, considering skipped points
|
// Get position in ridgePoints, considering skipped points
|
||||||
meshVarIndex.add(ridgePoints.headMap(faceIndex.get(ind)).size() + groundSize);
|
meshVarIndex.add(ridgePoints.headMap(faceIndex.get(ind)).size() + grRsSize);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO Improve wrong or not tessellated faces
|
// TODO Improve wrong or not tessellated faces
|
||||||
@@ -746,11 +782,10 @@ public final class S3DBUtils {
|
|||||||
// Add ridge points
|
// Add ridge points
|
||||||
float[] tmp = ridgePoints.get(k);
|
float[] tmp = ridgePoints.get(k);
|
||||||
if (tmp != null) {
|
if (tmp != null) {
|
||||||
float[] p = new float[]{tmp[0], tmp[1], maxHeight};
|
int ppos = 3 * (l + grRsSize);
|
||||||
int ppos = 3 * (l + groundSize);
|
meshPoints[ppos + 0] = tmp[0];
|
||||||
meshPoints[ppos + 0] = p[0];
|
meshPoints[ppos + 1] = tmp[1];
|
||||||
meshPoints[ppos + 1] = p[1];
|
meshPoints[ppos + 2] = maxHeight;
|
||||||
meshPoints[ppos + 2] = p[2];
|
|
||||||
l++;
|
l++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1292,6 +1327,58 @@ public final class S3DBUtils {
|
|||||||
return hsv.mod(c, relative);
|
return hsv.mod(c, relative);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the profile (half cross section) of roof shape.
|
||||||
|
*
|
||||||
|
* @param roofShape the roof shape value
|
||||||
|
* @return the profile as 2D array
|
||||||
|
*/
|
||||||
|
public static float[][] getProfile(String roofShape) {
|
||||||
|
float[][] shape;
|
||||||
|
switch (roofShape) {
|
||||||
|
case Tag.VALUE_ONION:
|
||||||
|
shape = new float[][]{
|
||||||
|
{1, 0, 0},
|
||||||
|
{0.2f, 0, 0.01f},
|
||||||
|
{0.875f, 0, 0.1875f},
|
||||||
|
{1, 0, 0.375f},
|
||||||
|
{0.875f, 0, 0.5625f},
|
||||||
|
{0.5f, 0, 0.75f},
|
||||||
|
{0.2f, 0, 0.8125f},
|
||||||
|
{0, 0, 1}};
|
||||||
|
break;
|
||||||
|
case Tag.VALUE_ROUND:
|
||||||
|
case Tag.VALUE_DOME:
|
||||||
|
shape = new float[][]{
|
||||||
|
{1, 0, 0},
|
||||||
|
{0.825f, 0, 0.5f},
|
||||||
|
{0.5f, 0, 0.825f},
|
||||||
|
{0, 0, 1}};
|
||||||
|
break;
|
||||||
|
case Tag.VALUE_SALTBOX:
|
||||||
|
shape = new float[][]{
|
||||||
|
{1, 0, 0},
|
||||||
|
{0.5f, 0, 1},
|
||||||
|
{0, 0, 1}};
|
||||||
|
break;
|
||||||
|
case Tag.VALUE_MANSARD:
|
||||||
|
case Tag.VALUE_GAMBREL:
|
||||||
|
shape = new float[][]{
|
||||||
|
{1, 0, 0},
|
||||||
|
{0.75f, 0, 0.75f},
|
||||||
|
{0, 0, 1}};
|
||||||
|
break;
|
||||||
|
case Tag.VALUE_GABLED:
|
||||||
|
case Tag.VALUE_HIPPED:
|
||||||
|
default:
|
||||||
|
shape = new float[][]{
|
||||||
|
{1, 0, 0},
|
||||||
|
{0, 0, 1}};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return shape;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param normVectors the normalized vectors
|
* @param normVectors the normalized vectors
|
||||||
* @return a list of simple angles:
|
* @return a list of simple angles:
|
||||||
@@ -1342,32 +1429,32 @@ public final class S3DBUtils {
|
|||||||
return simpAngls;
|
return simpAngls;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static GeometryBuffer initCircleMesh(float[][] circleShape, int numSections) {
|
private static GeometryBuffer initCircleMesh(float[][] profile, int numSections) {
|
||||||
int indexSize = numSections * (circleShape.length - 1) * 2 * 3; // * 2 faces * 3 vertices
|
int indexSize = numSections * (profile.length - 1) * 2 * 3; // * 2 faces * 3 vertices
|
||||||
int[] meshIndex = new int[indexSize];
|
int[] meshIndex = new int[indexSize];
|
||||||
|
|
||||||
int meshSize = numSections * circleShape.length;
|
int meshSize = numSections * profile.length;
|
||||||
float[] meshPoints = new float[meshSize * 3];
|
float[] meshPoints = new float[meshSize * 3];
|
||||||
for (int i = 0; i < numSections; i++) {
|
for (int i = 0; i < numSections; i++) {
|
||||||
for (int j = 0; j < circleShape.length; j++) {
|
for (int j = 0; j < profile.length; j++) {
|
||||||
// Write point mesh
|
// Write point mesh
|
||||||
int pPos = 3 * (i * circleShape.length + j);
|
int pPos = 3 * (i * profile.length + j);
|
||||||
meshPoints[pPos + 0] = circleShape[j][0];
|
meshPoints[pPos + 0] = profile[j][0];
|
||||||
meshPoints[pPos + 1] = circleShape[j][1];
|
meshPoints[pPos + 1] = profile[j][1];
|
||||||
meshPoints[pPos + 2] = circleShape[j][2];
|
meshPoints[pPos + 2] = profile[j][2];
|
||||||
|
|
||||||
// Write point indices
|
// Write point indices
|
||||||
if (j != circleShape.length - 1) {
|
if (j != profile.length - 1) {
|
||||||
int iPos = 6 * (i * (circleShape.length - 1) + j); // 6 = 2 * Mesh * 3PointsPerMesh
|
int iPos = 6 * (i * (profile.length - 1) + j); // 6 = 2 * Mesh * 3PointsPerMesh
|
||||||
pPos = pPos / 3;
|
pPos = pPos / 3;
|
||||||
meshIndex[iPos + 2] = pPos + 0;
|
meshIndex[iPos + 2] = pPos + 0;
|
||||||
meshIndex[iPos + 1] = pPos + 1;
|
meshIndex[iPos + 1] = pPos + 1;
|
||||||
meshIndex[iPos + 0] = (pPos + circleShape.length) % meshSize;
|
meshIndex[iPos + 0] = (pPos + profile.length) % meshSize;
|
||||||
|
|
||||||
// FIXME if is last point, only one tris is needed, if top shape is closed
|
// FIXME if is last point, only one tris is needed, if top shape is closed
|
||||||
meshIndex[iPos + 5] = pPos + 1;
|
meshIndex[iPos + 5] = pPos + 1;
|
||||||
meshIndex[iPos + 4] = (pPos + circleShape.length + 1) % meshSize;
|
meshIndex[iPos + 4] = (pPos + profile.length + 1) % meshSize;
|
||||||
meshIndex[iPos + 3] = (pPos + circleShape.length) % meshSize;
|
meshIndex[iPos + 3] = (pPos + profile.length) % meshSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1376,6 +1463,21 @@ public final class S3DBUtils {
|
|||||||
return new GeometryBuffer(meshPoints, meshIndex);
|
return new GeometryBuffer(meshPoints, meshIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isGabled(String roofShape) {
|
||||||
|
switch (roofShape) {
|
||||||
|
case Tag.VALUE_ROUND:
|
||||||
|
case Tag.VALUE_SALTBOX:
|
||||||
|
case Tag.VALUE_GABLED:
|
||||||
|
case Tag.VALUE_GAMBREL:
|
||||||
|
return true;
|
||||||
|
case Tag.VALUE_MANSARD:
|
||||||
|
case Tag.VALUE_HALF_HIPPED:
|
||||||
|
case Tag.VALUE_HIPPED:
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void mergeMeshGeometryBuffer(GeometryBuffer gb1, GeometryBuffer gb2, GeometryBuffer out) {
|
private static void mergeMeshGeometryBuffer(GeometryBuffer gb1, GeometryBuffer gb2, GeometryBuffer out) {
|
||||||
if (!(gb1.isTris() && gb2.isTris())) return;
|
if (!(gb1.isTris() && gb2.isTris())) return;
|
||||||
int gb1PointSize = gb1.points.length;
|
int gb1PointSize = gb1.points.length;
|
||||||
|
|||||||
Reference in New Issue
Block a user