Commit 4e6966e0 authored by Andrey Filippov's avatar Andrey Filippov

Debugging gltf export

parent 82b27573
......@@ -27,6 +27,18 @@
<description>A Maven project implementing imagej-elphel plugin</description>
<dependencies>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple -->
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1</version>
</dependency>
<!-- ssh support - see https://www.baeldung.com/java-ssh-connection -->
<!-- https://mvnrepository.com/artifact/org.apache.sshd/sshd-core -->
<dependency>
......
......@@ -903,7 +903,7 @@ public class OpticalFlow {
* @param debug_level if > 0; print number of tiles to correlate
* @return flowXY vectors only for tiles to be updated or null if no tiles left
*/
double [][] recalculateFlowXY(
static double [][] recalculateFlowXY(
final double [][] flowXY, // will update
final double [][] flowXY_prev, // previous flowXY (may be null for tiles)
final double [][] corr_vectorsXY,
......
......@@ -65,6 +65,7 @@ import com.elphel.imagej.correction.EyesisCorrections;
import com.elphel.imagej.gpu.GpuQuad;
import com.elphel.imagej.gpu.TpTask;
import com.elphel.imagej.readers.ImagejJp4Tiff;
import com.elphel.imagej.x3d.export.TriMesh;
import com.elphel.imagej.x3d.export.WavefrontExport;
import com.elphel.imagej.x3d.export.X3dOutput;
......@@ -7552,11 +7553,11 @@ public class QuadCLTCPU {
double [] rel_lim = {
getMarginFromHist(
hist, // histogram
too_cold, // double cumul_val, // cummulative number of items to be ignored
too_cold, // double cumul_val, // cumulative number of items to be ignored
false), // boolean high_marg)
getMarginFromHist(
hist, // histogram
too_hot, // double cumul_val, // cummulative number of items to be ignored
too_hot, // double cumul_val, // cumulative number of items to be ignored
true)}; // boolean high_marg)
double [] abs_lim = {
rel_lim[0] * (hard_hot - hard_cold) + hard_cold,
......@@ -12455,6 +12456,7 @@ public class QuadCLTCPU {
double infinity_disparity = geometryCorrection.getDisparityFromZ(clt_parameters.infinityDistance);
X3dOutput x3dOutput = null;
WavefrontExport wfOutput = null;
ArrayList<TriMesh> tri_meshes = null;
if (clt_parameters.remove_scans){
System.out.println("Removing all scans but the first(background) and the last to save memory");
System.out.println("Will need to re-start the program to be able to output differently");
......@@ -12503,6 +12505,10 @@ public class QuadCLTCPU {
// do nothing, just keep
}
}
if (clt_parameters.output_glTF && (x3d_path != null)) {
tri_meshes = new ArrayList<TriMesh>();
}
if (x3dOutput != null) {
x3dOutput.generateBackground(clt_parameters.infinityDistance <= 0.0); // needs just first (background) scan
}
......@@ -12579,6 +12585,7 @@ public class QuadCLTCPU {
generateClusterX3d(
x3dOutput,
wfOutput, // output WSavefront if not null
tri_meshes, // ArrayList<TriMesh> tri_meshes,
texturePath,
"INFINITY", // id (scanIndex - next_pass), // id
"INFINITY", // class
......@@ -12590,7 +12597,11 @@ public class QuadCLTCPU {
showTri, // (scanIndex < next_pass + 1) && clt_parameters.show_triangles,
infinity_disparity, // 0.3
clt_parameters.grow_disp_max, // other_range, // 2.0 'other_range - difference from the specified (*_CM)
clt_parameters.maxDispTriangle);
clt_parameters.maxDispTriangle,
clt_parameters.maxZtoXY, // double maxZtoXY, // 10.0. <=0 - do not use
clt_parameters.maxZ,
clt_parameters.limitZ,
debugLevel + 1); // int debug_level) > 0
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
......@@ -12668,11 +12679,11 @@ public class QuadCLTCPU {
}
}
boolean showTri = !batch_mode && (debugLevel > -1) && (((scanIndex < next_pass + 1) && clt_parameters.show_triangles) ||((scanIndex - next_pass) == 73));
try {
generateClusterX3d(
x3dOutput,
wfOutput, // output WSavefront if not null
tri_meshes, // ArrayList<TriMesh> tri_meshes,
texturePath,
"shape_id-"+(scanIndex - next_pass), // id
null, // class
......@@ -12685,7 +12696,11 @@ public class QuadCLTCPU {
// FIXME: make a separate parameter:
infinity_disparity, // 0.25 * clt_parameters.bgnd_range, // 0.3
clt_parameters.grow_disp_max, // other_range, // 2.0 'other_range - difference from the specified (*_CM)
clt_parameters.maxDispTriangle);
clt_parameters.maxDispTriangle,
clt_parameters.maxZtoXY, // double maxZtoXY, // 10.0. <=0 - do not use
clt_parameters.maxZ,
clt_parameters.limitZ,
debugLevel + 1); // int debug_level) > 0
} catch (IOException e) {
e.printStackTrace();
return false;
......@@ -12718,6 +12733,7 @@ public class QuadCLTCPU {
public void generateClusterX3d( // USED in lwir
X3dOutput x3dOutput, // output x3d if not null
WavefrontExport wfOutput, // output WSavefront if not null
ArrayList<TriMesh> tri_meshes,
String texturePath,
String id,
String class_name,
......@@ -12729,18 +12745,23 @@ public class QuadCLTCPU {
boolean show_triangles,
double min_disparity,
double max_disparity,
double maxDispTriangle
double maxDispTriangle, // relative <=0 - do not use
double maxZtoXY, // 10.0. <=0 - do not use
double maxZ, // far clip (0 - do not clip). Negative - limit by max
boolean limitZ,
int debug_level
) throws IOException
{
// int debug_level = 1;
if (bounds == null) {
return; // not used in lwir
}
int [][] indices = tp.getCoordIndices( // starting with 0, -1 - not selected
int [][] indices = tp.getCoordIndices( // starting with 0, -1 - not selected // updated 09.18.2022
bounds,
selected);
double [][] texCoord = TileProcessor.getTexCoords( // get texture coordinates for indices
indices);
double [][] worldXYZ = tp.getCoords( // get world XYZ in meters for indices
double [][] worldXYZ = tp.getCoords( // get world XYZ in meters for indices // updated 09.18.2022
disparity,
min_disparity,
max_disparity,
......@@ -12750,7 +12771,7 @@ public class QuadCLTCPU {
correctDistortions, // requires backdrop image to be corrected also
this.geometryCorrection);
double [] indexedDisparity = tp.getIndexedDisparities( // get disparity for each index
double [] indexedDisparity = tp.getIndexedDisparities( // get disparity for each index // updated 09.18.2022
disparity,
min_disparity,
max_disparity,
......@@ -12761,12 +12782,83 @@ public class QuadCLTCPU {
int [][] triangles = TileProcessor.triangulateCluster(
indices);
// double maxZtoXY = 10.0; // maximal delta_z to sqrt(dx^23 + dy^2)
int num_removed = 0;
if (maxDispTriangle > 0.0) {
int pre_num = triangles.length;
triangles = TileProcessor.filterTriangles( // remove crazy triangles with large disparity difference
triangles,
indexedDisparity, // disparities per vertex index
maxDispTriangle); // maximal disparity difference in a triangle
maxDispTriangle, // maximal disparity difference in a triangle
debug_level + 0); // int debug_level);
if (triangles.length < pre_num) {
num_removed += pre_num - triangles.length;
if (debug_level > 0) {
System.out.println("filterTriangles() removed "+ (pre_num - triangles.length)+" triangles");
}
}
}
if ((maxZ != 0.0) && limitZ) {
for (int i = 0; i < worldXYZ.length; i++) {
if (worldXYZ[i][2] < -maxZ) {
double k = -maxZ/worldXYZ[i][2];
worldXYZ[i][0] *= k;
worldXYZ[i][1] *= k;
worldXYZ[i][2] *= k;
}
}
}
if ((maxZtoXY > 0.0) || ((maxZ != 0) && !limitZ) ) {
int pre_num = triangles.length;
triangles = TileProcessor.filterTrianglesWorld(
triangles,
worldXYZ, // world per vertex index
maxZtoXY,
maxZ);
if (triangles.length < pre_num) {
num_removed += pre_num - triangles.length;
if (debug_level > 0) {
System.out.println("filterTrianglesWorld() removed "+ (pre_num - triangles.length)+" triangles");
}
}
}
if (triangles.length == 0) {
if (debug_level > 0) {
System.out.println("generateClusterX3d() no triangles left in a cluster");
}
return; // all triangles removed
}
if (num_removed > 0) {
int [] re_index = TileProcessor.reIndex( // Move to TriMesh?
indices, // will be modified if needed (if some indices are removed
triangles);
if (re_index != null) {// need to update other arrays: texCoord, worldXYZ. indexedDisparity[] will not be used
int num_indices_old = worldXYZ.length;
int [] inv_index = new int [num_indices_old];
Arrays.fill(inv_index,-1); // just to get an error
for (int i = 0; i < re_index.length; i++) {
inv_index[re_index[i]] = i;
}
double [][] texCoord_new = new double [re_index.length][];
double [][] worldXYZ_new = new double [re_index.length][];
for (int i = 0; i < re_index.length; i++) {
texCoord_new[i] = texCoord[re_index[i]];
worldXYZ_new[i] = worldXYZ[re_index[i]];
}
texCoord = texCoord_new;
worldXYZ = worldXYZ_new;
for (int i = 0; i < triangles.length; i++) {
for (int j=0; j < triangles[i].length; j++) {
triangles[i][j] = inv_index[triangles[i][j]];
}
}
}
if (debug_level > 0) {
show_triangles = true; // show after removed
}
}
if (show_triangles) {
double [] ddisp = (disparity == null)?(new double[1]):disparity;
......@@ -12800,6 +12892,13 @@ public class QuadCLTCPU {
worldXYZ,
triangles);
}
if (tri_meshes != null) {
tri_meshes.add(new TriMesh(
texturePath, // String texture_image,
worldXYZ, // double [][] worldXYZ,
texCoord, // double [][] texCoord,
triangles)); // int [][] triangles
}
}
......
......@@ -76,6 +76,60 @@ class TileCluster{
public Rectangle getBounds() {return bounds;}
public boolean [] getBorder() {return border;}
public double [] getDisparity() {return disparity;}
public double [] getSubDisparity(int indx) { // disparity should be NaN for unused !
if (clust_list == null) {
return null;
}
Rectangle sub_bounds = clust_list.get(indx).bounds;
double [] sub_disparity = new double [sub_bounds.width * sub_bounds.height];
int src_x = sub_bounds.x - bounds.x;
for (int dst_y = 0; dst_y < sub_bounds.height; dst_y++) {
int src_y = dst_y + sub_bounds.y - bounds.y;
System.arraycopy(
disparity,
src_y * bounds.width + src_x,
sub_disparity,
dst_y * sub_bounds.width,
sub_bounds.width);
}
return sub_disparity;
}
public boolean [] getSubBorder(int indx) { // disparity should be NaN for unused !
if (clust_list == null) {
return null;
}
Rectangle sub_bounds = clust_list.get(indx).bounds;
boolean [] sub_border = new boolean [sub_bounds.width * sub_bounds.height];
int src_x = sub_bounds.x - bounds.x;
for (int dst_y = 0; dst_y < sub_bounds.height; dst_y++) {
int src_y = dst_y + sub_bounds.y - bounds.y;
System.arraycopy(
border,
src_y * bounds.width + src_x,
sub_border,
dst_y * sub_bounds.width,
sub_bounds.width);
}
return sub_border;
}
public boolean [] getSubSelected(int indx) { // disparity should be NaN for unused !
if (clust_list == null) {
return null;
}
double [] sub_disparity = getSubDisparity(indx);
boolean [] sub_selection = new boolean [sub_disparity.length];
for (int i = 0; i < sub_disparity.length; i++) {
sub_selection[i] = !Double.isNaN(sub_disparity[i]);
}
return sub_selection;
}
public boolean [] getSelected() {
if (disparity == null) {
return null;
......@@ -132,42 +186,6 @@ class TileCluster{
}
/*
public TileCluster combine (TileCluster tileCluster) {
TileCluster outer, inner;
if (bounds.contains(tileCluster.bounds)) {
outer = this;
inner = tileCluster;
} else if (tileCluster.bounds.contains(bounds)) {
outer = tileCluster;
inner = this;
} else {
Rectangle outer_bounds = bounds.union(tileCluster.bounds);
outer = new TileCluster(outer_bounds, null, null);
outer.combine(this); //
inner = tileCluster;
}
int dst_x = inner.bounds.x - outer.bounds.x;
for (int src_y = 0; src_y < bounds.height; src_y++) {
int dst_y = src_y + inner.bounds.y - outer.bounds.y;
System.arraycopy(
inner.border,
src_y * bounds.width,
outer.border,
dst_y * outer.bounds.width + dst_x,
bounds.width);
System.arraycopy(
inner.disparity,
src_y * bounds.width,
outer.disparity,
dst_y * outer.bounds.width + dst_x,
bounds.width);
}
return outer;
}
*/
public void add(TileCluster tileCluster) {
if (!bounds.contains(tileCluster.bounds)) {
throw new IllegalArgumentException ("TileCluster.add(): Added cluster should fit into this ");
......@@ -193,16 +211,6 @@ class TileCluster{
disparity,
dst_y * bounds.width + dst_x,
tileCluster.bounds.width);
/**
if ((cluster_index != null) && (tileCluster.cluster_index != null)) {
System.arraycopy(
tileCluster.cluster_index,
src_y * tileCluster.bounds.width,
cluster_index,
dst_y * bounds.width + dst_x,
tileCluster.bounds.width);
}
*/
}
return;
}
......
......@@ -8626,6 +8626,7 @@ ImageDtt.startAndJoin(threads);
{
int [][] indices = new int [bounds.height][bounds.width];
int indx = 0;
if (selected.length > (bounds.height * bounds.width)) { // old version - selected is full size
for (int y = 0; y < bounds.height; y++) {
for (int x = 0; x < bounds.width; x++){
if (selected[this.tilesX * (bounds.y + y) + (bounds.x + x)]){
......@@ -8635,6 +8636,17 @@ ImageDtt.startAndJoin(threads);
}
}
}
} else { // 09.18.2022
for (int y = 0; y < bounds.height; y++) {
for (int x = 0; x < bounds.width; x++){
if (selected[bounds.width * y + x]){
indices[y][x] = indx++;
} else {
indices[y][x] = -1;
}
}
}
}
return indices;
}
......@@ -8680,6 +8692,7 @@ ImageDtt.startAndJoin(threads);
int maxIndex = getMaxIndex(indices);
double [] indexedDisparity = new double [maxIndex+1];
int indx = 0;
if (disparity.length > (bounds.height * bounds.width)) { // old version - selected is full size
for (int y = 0; indx <= maxIndex; y++) {
for (int x = 0; (x < width) && (indx <= maxIndex); x++){
if (indices[y][x] >=0){
......@@ -8692,6 +8705,20 @@ ImageDtt.startAndJoin(threads);
}
}
}
} else { // 09.18.2022
for (int y = 0; indx <= maxIndex; y++) {
for (int x = 0; (x < width) && (indx <= maxIndex); x++){
if (indices[y][x] >=0){
// center coordinates for 8*8 tile is [3.5,3.5]
double disp = (disparity == null)? min_disparity:( disparity[bounds.width *y + x]);
if (disp < min_disparity) disp = min_disparity;
else if (disp > max_disparity) disp = max_disparity;
indexedDisparity[indx] =disp;
indx ++;
}
}
}
}
return indexedDisparity;
}
......@@ -8711,6 +8738,7 @@ ImageDtt.startAndJoin(threads);
int maxIndex = getMaxIndex(indices);
double [][] coordinate = new double [maxIndex+1][];
int indx = 0;
if (disparity.length > (bounds.height * bounds.width)) { // old version - selected is full size
for (int y = 0; indx <= maxIndex; y++) {
for (int x = 0; (x < width) && (indx <= maxIndex); x++){
if (indices[y][x] >=0){
......@@ -8729,6 +8757,27 @@ ImageDtt.startAndJoin(threads);
}
}
}
} else { // 09.18.2022
for (int y = 0; indx <= maxIndex; y++) {
for (int x = 0; (x < width) && (indx <= maxIndex); x++){
if (indices[y][x] >=0){
// center coordinates for 8*8 tile is [3.5,3.5]
double px = (bounds.x + x + 0.5) * tile_size - 0.5;
double py = (bounds.y + y + 0.5) * tile_size - 0.5;
double disp = (disparity == null)? min_disparity:( disparity[bounds.width * y + x]);
if (disp < min_disparity) disp = min_disparity;
else if (disp > max_disparity) disp = max_disparity;
coordinate[indx] = geometryCorrection.getWorldCoordinates(
px,
py,
disp,
correctDistortions);
indx ++;
}
}
}
}
return coordinate;
}
......@@ -8749,9 +8798,10 @@ ImageDtt.startAndJoin(threads);
public static int [][] filterTriangles(
int [][] triangles,
double [] disparity, // disparities per vertex index
double maxDispDiff) // maximal disparity difference in a triangle
{
final double min_avg = 0.5; // minimal average disparity to normalize triangle
double maxDispDiff, // maximal relative disparity difference in a triangle
int debug_level)
{
final double min_avg = 3.0; // 0.5; // minimal average disparity to normalize triangle
class Triangle {
int [] points = new int [3];
Triangle (int i1, int i2, int i3){
......@@ -8762,12 +8812,19 @@ ImageDtt.startAndJoin(threads);
}
ArrayList<Triangle> triList = new ArrayList<Triangle>();
for (int i = 0; i < triangles.length; i++){
double disp_avg = (triangles[i][0] + triangles[i][1]+ triangles[i][2])/3.0;
double disp_avg = (disparity[triangles[i][0]] + disparity[triangles[i][1]]+ disparity[triangles[i][2]])/3.0; // fixed 09.18.2022!
if (disp_avg < min_avg) disp_avg = min_avg;
loop:{
for (int j = 0; j < 3; j++){
int j1 = (j + 1) % 3;
if (Math.abs(disparity[triangles[i][j]] - disparity[triangles[i][j1]]) > (disp_avg* maxDispDiff)) break loop;
if (Math.abs(disparity[triangles[i][j]] - disparity[triangles[i][j1]]) > (disp_avg* maxDispDiff)) {
if (debug_level > 1) {
System.out.println("removed triangle "+i+": "+
disparity[triangles[i][0]]+". "+disparity[triangles[i][1]]+". "+disparity[triangles[i][2]]+
". Avg = "+disp_avg);
}
break loop;
}
}
triList.add(new Triangle(
triangles[i][0],
......@@ -8780,7 +8837,100 @@ ImageDtt.startAndJoin(threads);
filteredTriangles[i] = triList.get(i).points;
}
return filteredTriangles;
}
}
public static int [][] filterTrianglesWorld(
int [][] triangles,
double [][] worldXYZ, // world per vertex index
double maxZtoXY,
double maxZ)
{
final double maxZtoXY2 = maxZtoXY * maxZtoXY;
class Triangle {
int [] points = new int [3];
Triangle (int i1, int i2, int i3){
points[0] = i1;
points[1] = i2;
points[2] = i3;
}
}
ArrayList<Triangle> triList = new ArrayList<Triangle>();
for (int i = 0; i < triangles.length; i++){
double [][] min_max = new double[3][2];
boolean not_too_far = true;
for (int di = 0; di < 3; di++) {
min_max[di][0] = worldXYZ[triangles[i][0]][di];
min_max[di][1] = min_max[di][0]; // both min and max to the same vertex 0
}
if (maxZ != 0) {
not_too_far &= worldXYZ[triangles[i][0]][2] > -maxZ;
}
for (int vi = 1; vi < 3; vi++) {
for (int di = 0; di < 3; di++) {
min_max[di][0] = Math.min(min_max[di][0], worldXYZ[triangles[i][vi]][di]);
min_max[di][1] = Math.max(min_max[di][1], worldXYZ[triangles[i][vi]][di]);
}
}
double dx = min_max[0][1]-min_max[0][0];
double dy = min_max[1][1]-min_max[1][0];
double dz = min_max[2][1]-min_max[2][0];
double ratio2 = dz*dz/(dx*dx+dy*dy + 0.001);
if (not_too_far && ((maxZtoXY == 0) || (ratio2 < maxZtoXY2))) {
triList.add(new Triangle(
triangles[i][0],
triangles[i][1],
triangles[i][2]));
}
}
int [][] filteredTriangles = new int [triList.size()][3];
for (int i = 0; i < filteredTriangles.length; i++){
filteredTriangles[i] = triList.get(i).points;
}
return filteredTriangles;
}
public static int [] reIndex(
int [][] indices,
int [][] triangles) {
int last_index = -1;
for (int i = 0; i < indices.length; i++) {
for (int j = 0; j < indices[i].length; j++) {
if (indices[i][j] > last_index) {
last_index = indices[i][j];
}
}
}
boolean [] used_indices = new boolean[last_index+1];
for (int i = 0; i < triangles.length; i++) {
for (int j = 0; j < triangles[i].length; j++) { // always 3
used_indices[triangles[i][j]] = true;
}
}
int new_len = 0;
for (int i = 0; i < used_indices.length; i++) if (used_indices[i]) {
new_len++;
}
if (new_len == used_indices.length) {
return null; // no re-indexing is needed
}
int [] re_index = new int [new_len];
int indx = 0;
for (int i = 0; i < indices.length; i++) {
for (int j = 0; j < indices[i].length; j++) {
int old_index=indices[i][j];
if (old_index >= 0) {
if (used_indices[old_index]) { // keep
re_index[indx] = old_index;
indices[i][j] = indx++;
} else {
indices[i][j] = -1;
}
}
}
}
return re_index;
}
public static int [][] triangulateCluster(
......@@ -8851,6 +9001,8 @@ ImageDtt.startAndJoin(threads);
{
String [] titles = {"disparity","triangles"};
double [][] dbg_img = new double [titles.length][tilesX*tilesY*tile_size*tile_size];
Arrays.fill(dbg_img[0], Double.NaN);
if (selected.length > (bounds.height * bounds.width)) { // old version - selected is full size
for (int i = 0; i < selected.length; i++ ){
double d = selected[i]? ((disparity.length >1) ? disparity[i] : disparity[0]):Double.NaN;
int y = i / tilesX;
......@@ -8861,6 +9013,18 @@ ImageDtt.startAndJoin(threads);
}
}
}
} else { // 09.18.2022
for (int i = 0; i < selected.length; i++ ){
double d = selected[i]? ((disparity.length > 1) ? disparity[i] : disparity[0]):Double.NaN;
int y = i / bounds.width + bounds.y;
int x = i % bounds.width + bounds.x;
for (int dy = 0; dy <tile_size; dy ++){
for (int dx = 0; dx <tile_size; dx ++){
dbg_img[0][(y * tile_size + dy)*(tile_size*tilesX) + (x * tile_size + dx)] = d;
}
}
}
}
int maxIndex = getMaxIndex(indices);
int [][] pxy = new int [maxIndex+1][2];
int height = indices.length;
......@@ -8885,12 +9049,7 @@ ImageDtt.startAndJoin(threads);
for (int j = 0; j < tile_size; j++){
int x = pxy[pntIndx[0]][0] + dx*j;
int y = pxy[pntIndx[0]][1] + dy*j;
// int indx = y * tile_size * tilesX + x;
// if (indx < dbg_img[1].length) {
dbg_img[1][y * tile_size * tilesX + x] = 10.0; //1711748
// } else {
// indx += 0;
// }
}
}
}
......
This diff is collapsed.
package com.elphel.imagej.x3d.export;
/**
**
** TriMesh - triangular mesh representation
**
** Copyright (C) 2022 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** TriMesh.java is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------**
**
*/
public class TriMesh {
public String texture_image;
public double [][] worldXYZ;
public double [][] texCoord;
public int [][] triangles;
public TriMesh (
String texture_image,
double [][] worldXYZ,
double [][] texCoord,
int [][] triangles) {
this.texture_image = texture_image;
this.worldXYZ = worldXYZ;
this.texCoord = texCoord;
this.triangles = triangles;
}
public String getImage() {return texture_image;}
int [][] getTriangles() {return triangles;}
double [][] getTexCoord() {
return texCoord;
}
public double [][] getTexCoord(boolean inv_x, boolean inv_y, boolean swap_xy) {
if (!inv_x && !inv_y && !swap_xy) {
return texCoord;
}
double [][] inv_tex_coord = new double [texCoord.length][2];
double scale_x = inv_x ? -1.0 : 1.0;
double scale_y = inv_y ? -1.0 : 1.0;
if (swap_xy) {
for (int i = 0; i <texCoord.length; i++) {
inv_tex_coord[i][0] = scale_y * texCoord[i][1];
inv_tex_coord[i][1] = scale_x * texCoord[i][0];
}
} else {
for (int i = 0; i <texCoord.length; i++) {
inv_tex_coord[i][0] = scale_x * texCoord[i][0];
inv_tex_coord[i][1] = scale_y * texCoord[i][1];
}
}
return inv_tex_coord;
}
public double [][] getCoordinates(){
return worldXYZ;
}
/**
* 0: XYZ -> XYZ
* 1: XYZ -> YZX
* 2: XYZ -> ZXY
* 3: XYZ -> XZY
* 4: XYZ -> ZYX
* 5: XYZ -> YXZ
* @param inv_x
* @param inv_y
* @param inv_z
* @param swap3
* @return
*/
public double [][] getCoordinates(boolean inv_x, boolean inv_y, boolean inv_z, int swap3) {
if (!inv_x && !inv_y && !inv_y && (swap3 == 0)) {
return worldXYZ;
}
double [][] inv_worldXYZ = new double [worldXYZ.length][3];
double scale_x = inv_x ? -1.0 : 1.0;
double scale_y = inv_y ? -1.0 : 1.0;
double scale_z = inv_z ? -1.0 : 1.0;
switch (swap3) {
case 0: // XYZ -> XYZ
for (int i = 0; i <texCoord.length; i++) {
inv_worldXYZ[i][0] = scale_x * worldXYZ[i][0];
inv_worldXYZ[i][1] = scale_y * worldXYZ[i][1];
inv_worldXYZ[i][2] = scale_z * worldXYZ[i][2];
}
break;
case 1: // XYZ -> YZX
for (int i = 0; i <texCoord.length; i++) {
inv_worldXYZ[i][1] = scale_x * worldXYZ[i][0];
inv_worldXYZ[i][2] = scale_y * worldXYZ[i][1];
inv_worldXYZ[i][0] = scale_z * worldXYZ[i][2];
}
break;
case 2: // XYZ -> ZXY
for (int i = 0; i <texCoord.length; i++) {
inv_worldXYZ[i][2] = scale_x * worldXYZ[i][0];
inv_worldXYZ[i][0] = scale_y * worldXYZ[i][1];
inv_worldXYZ[i][1] = scale_z * worldXYZ[i][2];
}
break;
case 3: // XYZ -> XZY
for (int i = 0; i <texCoord.length; i++) {
inv_worldXYZ[i][0] = scale_x * worldXYZ[i][0];
inv_worldXYZ[i][2] = scale_y * worldXYZ[i][1];
inv_worldXYZ[i][1] = scale_z * worldXYZ[i][2];
}
break;
case 4: // XYZ -> ZYX
for (int i = 0; i <texCoord.length; i++) {
inv_worldXYZ[i][2] = scale_x * worldXYZ[i][0];
inv_worldXYZ[i][1] = scale_y * worldXYZ[i][1];
inv_worldXYZ[i][0] = scale_z * worldXYZ[i][2];
}
break;
case 5: // XYZ -> YXZ
for (int i = 0; i <texCoord.length; i++) {
inv_worldXYZ[i][1] = scale_x * worldXYZ[i][0];
inv_worldXYZ[i][0] = scale_y * worldXYZ[i][1];
inv_worldXYZ[i][2] = scale_z * worldXYZ[i][2];
}
break;
default: return null;
}
return inv_worldXYZ;
}
}
package com.elphel.imagej.x3d.export;
/**
**
** WavefrontExport - generate Wavefront OBJ representation of the model
**
** Copyright (C) 2018 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** WavefrontExport.java is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------**
**
*/
import java.io.FileWriter;
import java.io.IOException;
......
......@@ -76,6 +76,7 @@ public class X3dOutput {
this.clt_3d_passes = clt_3d_passes;
}
// init document, bounding box, backdrop
// 09.18.2022 - made work w/o background
public void generateBackground(boolean use_backdrop)
{
try {
......@@ -105,6 +106,11 @@ public class X3dOutput {
el_Scene.appendChild(el_TopGroup);
if (clt_3d_passes == null) {
System.out.println("Not using background without clt_3d_passes");
return;
}
CLTPass3d bgnd_pass = clt_3d_passes.get(0);
Element el_Bgnd = x3dDoc.createElement("Background");
......@@ -167,6 +173,10 @@ public class X3dOutput {
sb_tex_coords.append(String.format("%.4f %.4f", texCoord[i][0], texCoord[i][1]));
}
String sindex = sb_coord_index.toString(); // for both coordIndex and texCoordIndex
if (sindex.length() == 0) {
System.out.println("addCluster(): sindex.length() == 0");
System.out.println("addCluster(): sindex.length() == 0");
}
String scoord = sb_coords.toString();
String stcoord = sb_tex_coords.toString();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment