Loading src/main/java/com/elphel/imagej/tileprocessor/TexturedModel.java +26 −14 Original line number Original line Diff line number Diff line Loading @@ -1969,7 +1969,7 @@ public class TexturedModel { scenes, // final QuadCLT [] scenes, scenes, // final QuadCLT [] scenes, scenes_sel, // final boolean [] scenes_sel, // null or which scenes to process scenes_sel, // final boolean [] scenes_sel, // null or which scenes to process tileClusters, // final TileCluster [] tileClusters, // disparities, borders, selections for texture passes tileClusters, // final TileCluster [] tileClusters, // disparities, borders, selections for texture passes renormalize, // final boolean renormalize, // false - use normalizations from previous scenes to keep consistent colors renormalize, // final boolean re-normalize, // false - use normalizations from previous scenes to keep consistent colors max_disparity_lim, // final double max_disparity_lim, // 100.0; // do not allow stray disparities above this max_disparity_lim, // final double max_disparity_lim, // 100.0; // do not allow stray disparities above this min_trim_disparity, // final double min_trim_disparity, // 2.0; // do not try to trim texture outlines with lower disparities min_trim_disparity, // final double min_trim_disparity, // 2.0; // do not try to trim texture outlines with lower disparities debugLevel); // final int debug_level) debugLevel); // final int debug_level) Loading Loading @@ -2080,11 +2080,6 @@ public class TexturedModel { dbg_mesh_imgs = new double[tileClusters.length][dbg_scaled_width * dbg_scaled_height]; dbg_mesh_imgs = new double[tileClusters.length][dbg_scaled_width * dbg_scaled_height]; // maybe fill with NaN? // maybe fill with NaN? } } // double [][] dbg /* tp.getTilesX(), // int tilesX, tp.getTilesY(), // int tilesY, */ for (int nslice = 0; nslice < tileClusters.length; nslice++){ for (int nslice = 0; nslice < tileClusters.length; nslice++){ if (dbg_tri_disp != null) { if (dbg_tri_disp != null) { Arrays.fill(dbg_tri_disp[nslice], Double.NaN); Arrays.fill(dbg_tri_disp[nslice], Double.NaN); Loading @@ -2094,28 +2089,34 @@ public class TexturedModel { ((dbg_tri_disp != null)? (new double[][] {dbg_tri_disp[nslice], dbg_tri_tri[nslice]}): ((dbg_tri_disp != null)? (new double[][] {dbg_tri_disp[nslice], dbg_tri_tri[nslice]}): (new double[][] {dbg_tri_tri[nslice]}) ): null; (new double[][] {dbg_tri_tri[nslice]}) ): null; if (debugLevel > -1){ if (debugLevel > -2){ System.out.println("Generating cluster images from texture slice "+nslice); System.out.println("Generating cluster images from texture slice "+nslice); } } int [] indices = tileClusters[nslice].getSubIndices(); int [] indices = tileClusters[nslice].getSubIndices(); Rectangle [] bounds = tileClusters[nslice].getSubBounds(); Rectangle [] bounds = tileClusters[nslice].getSubBounds(); // tiles? Rectangle texture_bounds = null; // if not null - allows trimmed combo textures tiles? int dbg_tri_indx = 3; // showing triangles for cluster 3 int dbg_tri_indx = 3; // showing triangles for cluster 3 for (int sub_i = 0; sub_i < indices.length; sub_i++) { for (int sub_i = 0; sub_i < indices.length; sub_i++) { Rectangle roi = bounds[sub_i]; Rectangle roi = bounds[sub_i]; int cluster_index = indices[sub_i]; int cluster_index = indices[sub_i]; ImagePlus imp_texture_cluster = combined_textures[nslice]; ImagePlus imp_texture_cluster = combined_textures[nslice]; boolean [] alpha = (combined_alphas != null) ? combined_alphas[nslice] : null; boolean [] alpha = (combined_alphas != null) ? combined_alphas[nslice] : null; if (imp_textures != null) { if (imp_textures != null) { // wrong? roi is in tiles or pixels? //transform_size imp_texture_cluster = imp_textures[cluster_index]; imp_texture_cluster = imp_textures[cluster_index]; if (combined_alphas != null) { if (combined_alphas != null) { alpha = new boolean[roi.height * roi.width]; int alpha_width = roi.width * transform_size; for (int row = 0; row < roi.height; row++) { int alpha_height = roi.height * transform_size; int alpha_x0 = roi.x * transform_size; int alpha_y0 = roi.y * transform_size; alpha = new boolean[alpha_width * alpha_height]; for (int row = 0; row < alpha_height; row++) { System.arraycopy( System.arraycopy( combined_alphas[nslice], combined_alphas[nslice], (roi.y + row) * width + roi.x, (alpha_y0 + row) * width + alpha_x0, alpha, alpha, row * roi.width, row * alpha_width, roi.width); alpha_width); } } } } } } Loading Loading @@ -2170,6 +2171,7 @@ public class TexturedModel { "shape_id-"+cluster_index, // id "shape_id-"+cluster_index, // id null, // class null, // class roi, // scan.getTextureBounds(), roi, // scan.getTextureBounds(), texture_bounds, // Rectangle texture_bounds, // if not null - allows trimmed combo textures scan_selected, // scan.getSelected(), scan_selected, // scan.getSelected(), scan_disparity, // scan.disparity_map[ImageDtt.DISPARITY_INDEX_CM], scan_disparity, // scan.disparity_map[ImageDtt.DISPARITY_INDEX_CM], clt_parameters.transform_size, clt_parameters.transform_size, Loading Loading @@ -2198,6 +2200,16 @@ public class TexturedModel { } } // if (imp_textures[nslice] != null) // if (imp_textures[nslice] != null) } // for (int nslice = 0; nslice < tileClusters.length; nslice++){ } // for (int nslice = 0; nslice < tileClusters.length; nslice++){ if (dbg_mesh_imgs != null) { ShowDoubleFloatArrays.showArrays( dbg_mesh_imgs, dbg_scaled_width, dbg_scaled_height, true, ref_scene.getImageName()+"-tri-meshes"); } if (dbg_tri_disp != null) { if (dbg_tri_disp != null) { ShowDoubleFloatArrays.showArrays( ShowDoubleFloatArrays.showArrays( dbg_tri_disp, dbg_tri_disp, Loading src/main/java/com/elphel/imagej/x3d/export/TriMesh.java +103 −66 Original line number Original line Diff line number Diff line Loading @@ -235,19 +235,21 @@ public class TriMesh { final int [] num_indices final int [] num_indices ) { ) { //TODO: add optimization (merging some in-tile triangles) //TODO: add optimization (merging some in-tile triangles) final boolean full_image = selected_tiles.length > (bounds.height * bounds.width); final boolean full_selection = selected_tiles.length > (bounds.height * bounds.width); // applies to selected_tiles final boolean full_alpha = alpha.length > (bounds.height * bounds.width * tile_size * tile_size); final int [][][][] indices = new int [bounds.height][bounds.width][][]; final int [][][][] indices = new int [bounds.height][bounds.width][][]; final Thread[] threads = ImageDtt.newThreadArray(TexturedModel.THREADS_MAX); final Thread[] threads = ImageDtt.newThreadArray(TexturedModel.THREADS_MAX); final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0); final int source_tile_width = full_image? tilesX : bounds.width; final int source_tile_width = full_selection? tilesX : bounds.width; final int source_pix_width = source_tile_width * tile_size; // final int source_pix_width = source_tile_width * tile_size; final int source_tile_offsx = full_image? bounds.x : 0; final int source_tile_offsx = full_selection? bounds.x : 0; final int source_tile_offsy = full_image? bounds.y : 0; final int source_tile_offsy = full_selection? bounds.y : 0; // final int source_tile_offs = source_tile_offsx + source_tile_offsy * source_tile_width; // final int source_pix_offsx = source_tile_offsx * tile_size; final int source_pix_offsx = source_tile_offsx * tile_size; // final int source_pix_offsy = source_tile_offsy * tile_size; final int source_pix_offsy = source_tile_offsy * tile_size; final int source_pix_offsx = (full_alpha? bounds.x : 0) * tile_size; // final int source_pix_offs = source_pix_offsx + source_pix_offsy * source_pix_width; final int source_pix_offsy = (full_alpha? bounds.y : 0) * tile_size; // final int sub_size = Math.max(tile_size / subdiv, 1); final int source_pix_width = (full_alpha? tilesX : bounds.width) * tile_size; final int btiles = bounds.width * bounds.height; final int btiles = bounds.width * bounds.height; final AtomicInteger aindx = new AtomicInteger(0); final AtomicInteger aindx = new AtomicInteger(0); Loading Loading @@ -474,7 +476,7 @@ public class TriMesh { switch (dir) { switch (dir) { case 0: for (int i = 0; i < subdiv; i++) {edge[i] = tile[0][subdiv - i - 1];} break; case 0: for (int i = 0; i < subdiv; i++) {edge[i] = tile[0][subdiv - i - 1];} break; case 1: for (int i = 0; i < subdiv; i++) {edge[i] = tile[subdiv - i - 1][subdiv-1];} break; case 1: for (int i = 0; i < subdiv; i++) {edge[i] = tile[subdiv - i - 1][subdiv-1];} break; case 4: for (int i = 0; i < subdiv; i++) {edge[i] = tile[subdiv-1][i];} break; case 2: for (int i = 0; i < subdiv; i++) {edge[i] = tile[subdiv-1][i];} break; case 3: for (int i = 0; i < subdiv; i++) {edge[i] = tile[i][0];} break; case 3: for (int i = 0; i < subdiv; i++) {edge[i] = tile[i][0];} break; } } return edge; return edge; Loading Loading @@ -652,7 +654,7 @@ public class TriMesh { if (tris[btiley][btilex][y][x] == null) { if (tris[btiley][btilex][y][x] == null) { tris[btiley][btilex][y][x] = TRI_NONE.clone(); tris[btiley][btilex][y][x] = TRI_NONE.clone(); } } tris[btiley][btilex][y][x][1 << TRI_DOWN_LEFT] = atri.getAndIncrement(); tris[btiley][btilex][y][x][TRI_DOWN_LEFT] = atri.getAndIncrement(); } } } } Arrays.fill(quad_corners, false); Arrays.fill(quad_corners, false); Loading @@ -664,32 +666,33 @@ public class TriMesh { x = subdiv - 1; x = subdiv - 1; y = i - subdiv; y = i - subdiv; } } int num_corn = 0; quad_corners[0] = tneib_indices[8][y][x] >= 0; // this subtile if (quad_corners[0]) { // all following triangles assume that top-left corner exists int num_corn = 1; for (int dir = 1; dir < 4; dir++) { // skipping top-left corner for (int dir = 1; dir < 4; dir++) { // skipping top-left corner int x1 = x + TRI_OFFS_XY[dir][0]; int x1 = x + TRI_OFFS_XY[dir][0]; int y1 = y + TRI_OFFS_XY[dir][1]; int y1 = y + TRI_OFFS_XY[dir][1]; int [] xyd = getNeibNode(x1, y1, subdiv); int [] xyd = getNeibNode(x1, y1, subdiv); boolean exists = false; boolean exists = false; if (tneib_indices[xyd[2]] != null) { exists = (tneib_indices[xyd[2]] != null) && (tneib_indices[xyd[2]][xyd[1]][xyd[0]] >= 0); // is populated exists = tneib_indices[xyd[2]][xyd[1]][xyd[0]] >= 0; // is populated quad_corners[dir] = exists; quad_corners[dir] = exists; } if (exists) { if (exists) { num_corn ++; num_corn ++; } } } } if ((num_corn >= 3) && quad_corners[0]) { // that triangle (TRI_DOWN_LEFT) should already exist if (num_corn >= 3) { if (tris[btiley][btilex][y][x] == null) { if (tris[btiley][btilex][y][x] == null) { tris[btiley][btilex][y][x] = TRI_NONE.clone(); tris[btiley][btilex][y][x] = TRI_NONE.clone(); } } if (quad_corners[3]) { if (quad_corners[3]) { if (quad_corners[1]) { if (quad_corners[1]) { tris[btiley][btilex][y][x][1 << TRI_RIGHT_DOWNLEFT] = atri.getAndIncrement(); tris[btiley][btilex][y][x][TRI_RIGHT_DOWNLEFT] = atri.getAndIncrement(); } else { } else { tris[btiley][btilex][y][x][1 << TRI_DOWNRIGHT_LEFT] = atri.getAndIncrement(); tris[btiley][btilex][y][x][TRI_DOWNRIGHT_LEFT] = atri.getAndIncrement(); } } } else { } else { tris[btiley][btilex][y][x][1 << TRI_RIGHT_DOWN] = atri.getAndIncrement(); tris[btiley][btilex][y][x][TRI_RIGHT_DOWN] = atri.getAndIncrement(); } } } } } } } Loading Loading @@ -794,6 +797,8 @@ public class TriMesh { // type 4 (4 dirs, 2 triangles): // type 4 (4 dirs, 2 triangles): // 1 in ortho, 1 CCW from it, 2 CCW from 1. Does not need mirror, as the mirror will be if looking // 1 in ortho, 1 CCW from it, 2 CCW from 1. Does not need mirror, as the mirror will be if looking // from the last 2 (90 degrees CCW from the first 1) // from the last 2 (90 degrees CCW from the first 1) // type 5 (4 dirs, 1 triangle): // 1 in ortho, 2 CCW from it, 1 CCW from 1. Does not need mirror // First pass - reserving triangles indices // First pass - reserving triangles indices final Thread[] threads = ImageDtt.newThreadArray(TexturedModel.THREADS_MAX); final Thread[] threads = ImageDtt.newThreadArray(TexturedModel.THREADS_MAX); Loading @@ -817,14 +822,18 @@ public class TriMesh { if ((btx >= 0) && (btx < bwidth) && (bty >= 0) && (bty < bheight) && if ((btx >= 0) && (btx < bwidth) && (bty >= 0) && (bty < bheight) && (indices[bty][btx] != null)) { (indices[bty][btx] != null)) { tneib_types[dir] = 0; tneib_types[dir] = 0; if (indices[bty][btx] != null) { // if (indices[bty][btx] != null) { tneib_types[dir] = (indices[bty][btx].length > 1) ? 2 : 1; tneib_types[dir] = (indices[bty][btx].length > 1) ? 2 : 1; } // } has_full_neib |= (tneib_types[dir] == 1); // all modes 0..4 require 2-1 in ortho direction has_full_neib |= (tneib_types[dir] == 1) && ((dir & 1) == 0); } } } } if (has_full_neib) { if (has_full_neib) { tris[btiley][btilex] = new int [5][4]; // [types][directions tris[btiley][btilex] = new int [6][4]; // [types][directions for (int i = 0; i < tris[btiley][btilex].length; i++) { Arrays.fill(tris[btiley][btilex][i], -1); } // reserve indices for type0: // reserve indices for type0: for (int dir = 0; dir < 4; dir++) { for (int dir = 0; dir < 4; dir++) { int tneib = tneib_types[2*dir]; int tneib = tneib_types[2*dir]; Loading Loading @@ -868,6 +877,15 @@ public class TriMesh { tris[btiley][btilex][4][dir] = atri.getAndAdd(2); tris[btiley][btilex][4][dir] = atri.getAndAdd(2); } } } } // reserve indices for type5: for (int dir = 0; dir < 4; dir++) { int tneib = tneib_types[2*dir]; // pointed int tneib1= tneib_types[(2*dir+7) % 8]; // CCW 1 from pointed int tneib2= tneib_types[(2*dir+6) % 8]; // CCW 2 from pointed if ((tneib == 1) && (tneib1 == 2) && (tneib2 == 1)) { tris[btiley][btilex][5][dir] = atri.getAndAdd(1); } } } } } } } } Loading Loading @@ -905,7 +923,7 @@ public class TriMesh { int tri_index = tris[btiley][btilex][0][dir4]; // type0 int tri_index = tris[btiley][btilex][0][dir4]; // type0 if (tri_index >= 0) { if (tri_index >= 0) { int [] edge = getEdgeIndices(tneib_indices [8], dir4); int [] edge = getEdgeIndices(tneib_indices [8], dir4); int indx_1 = tneib_indices[2 * dir4][0][0]; int indx_1 = tneib_indices[2 * dir4][0][0]; // null pointer for (int i = 0; i < subdiv_m1; i++) { for (int i = 0; i < subdiv_m1; i++) { tri_indices[tri_index + i][0] = indx_1; tri_indices[tri_index + i][0] = indx_1; tri_indices[tri_index + i][1] = edge[i]; tri_indices[tri_index + i][1] = edge[i]; Loading Loading @@ -964,7 +982,19 @@ public class TriMesh { tri_indices[tri_index + 1][0] = indx_2; tri_indices[tri_index + 1][0] = indx_2; tri_indices[tri_index + 1][1] = edge[subdiv_m1]; tri_indices[tri_index + 1][1] = edge[subdiv_m1]; tri_indices[tri_index + 1][2] = edge[0]; tri_indices[tri_index + 1][2] = edge1[0]; } } // build triangles for type5: for (int dir4 = 0; dir4 < 4; dir4++) { int tri_index = tris[btiley][btilex][5][dir4]; // type5 if (tri_index >= 0) { int [] edge = getEdgeIndices(tneib_indices [8], dir4); int [] edge1 = getEdgeIndices(tneib_indices [(2 * dir4 + 7) % 8], (dir4 + 2) % 4); int indx_1 = tneib_indices[2 * dir4][0][0]; tri_indices[tri_index][0] = edge [subdiv_m1]; tri_indices[tri_index][1] = edge1[subdiv_m1]; tri_indices[tri_index][2] = indx_1; } } } } } } Loading Loading @@ -1876,6 +1906,7 @@ public class TriMesh { String id, String id, String class_name, String class_name, Rectangle bounds, Rectangle bounds, Rectangle texture_bounds, // if not null - allows trimmed combo textures // Below selected and disparity are bounds.width*bounds.height // Below selected and disparity are bounds.width*bounds.height boolean [] selected, // may be either tilesX * tilesY or bounds.width*bounds.height boolean [] selected, // may be either tilesX * tilesY or bounds.width*bounds.height double [] disparity, // if null, will use min_disparity double [] disparity, // if null, will use min_disparity Loading @@ -1900,7 +1931,7 @@ public class TriMesh { if (bounds == null) { if (bounds == null) { return; // not used in lwir return; // not used in lwir } } boolean display_triangles = debug_level > 0; /* /* Loading Loading @@ -1933,8 +1964,19 @@ public class TriMesh { indices, // int [][][][] indices) indices, // int [][][][] indices) subdivide_mesh); // final int [] num_indices) { subdivide_mesh); // final int [] num_indices) { Rectangle tex_rect = full_texture ? new Rectangle(bounds.x, bounds.y, tilesX, tilesY) : null; Rectangle tex_rect = full_texture ? ( (texture_bounds != null) ? new Rectangle( // when combo texture is trimmed (alpha should still be for the full image) bounds.x - texture_bounds.x, bounds.y - texture_bounds.y, texture_bounds.width, texture_bounds.height): new Rectangle( // when combo texture is full tilesX * tilesY bounds.x, bounds.y, tilesX, tilesY)) : null; // when texture is for cluster only /* /* * Get texture coordinates (0..1) for horizontal (positive - to the right) and vertical (positive - up) * Get texture coordinates (0..1) for horizontal (positive - to the right) and vertical (positive - up) */ */ Loading @@ -1954,23 +1996,13 @@ public class TriMesh { tile_size, // final int tile_size, tile_size, // final int tile_size, correctDistortions, // requires backdrop image to be corrected also correctDistortions, // requires backdrop image to be corrected also geometryCorrection);// final GeometryCorrection geometryCorrection) geometryCorrection);// final GeometryCorrection geometryCorrection) /* double [] indexedDisparity = getIndexedDisparities( // get disparity for each index // updated 09.18.2022 disparity, min_disparity, max_disparity, bounds, pnum_indices[0], // final int num_indices, indices, tilesX); */ /* /* * Triangulate all vertice indices - combine triangulation of same-size equailateral 45-degree * Triangulate all vertice indices - combine triangulation of same-size equailateral 45-degree * large (tile size) and small (tile subdivisions) and add connections between large and small ones * large (tile size) and small (tile subdivisions) and add connections between large and small ones */ */ int [][] triangles = triangulateAll( int [][] triangles = triangulateAll( indices); indices); System.out.println("generateClusterX3d(): got "+triangles.length+" triangles"); final boolean plot_center = true; final boolean plot_center = true; final double line_color = 1.0; final double line_color = 1.0; final double center_color = 3.0; final double center_color = 3.0; Loading @@ -1983,9 +2015,14 @@ public class TriMesh { plot_center, // final boolean plot_center, plot_center, // final boolean plot_center, line_color, // final double line_color, line_color, // final double line_color, center_color); // final double center_color) center_color); // final double center_color) if (display_triangles) { ShowDoubleFloatArrays.showArrays( tri_img, tri_img_width, tri_img.length / tri_img_width, "this-triangles"); } } } if (x3dOutput != null) { if (x3dOutput != null) { x3dOutput.addCluster( x3dOutput.addCluster( Loading Loading
src/main/java/com/elphel/imagej/tileprocessor/TexturedModel.java +26 −14 Original line number Original line Diff line number Diff line Loading @@ -1969,7 +1969,7 @@ public class TexturedModel { scenes, // final QuadCLT [] scenes, scenes, // final QuadCLT [] scenes, scenes_sel, // final boolean [] scenes_sel, // null or which scenes to process scenes_sel, // final boolean [] scenes_sel, // null or which scenes to process tileClusters, // final TileCluster [] tileClusters, // disparities, borders, selections for texture passes tileClusters, // final TileCluster [] tileClusters, // disparities, borders, selections for texture passes renormalize, // final boolean renormalize, // false - use normalizations from previous scenes to keep consistent colors renormalize, // final boolean re-normalize, // false - use normalizations from previous scenes to keep consistent colors max_disparity_lim, // final double max_disparity_lim, // 100.0; // do not allow stray disparities above this max_disparity_lim, // final double max_disparity_lim, // 100.0; // do not allow stray disparities above this min_trim_disparity, // final double min_trim_disparity, // 2.0; // do not try to trim texture outlines with lower disparities min_trim_disparity, // final double min_trim_disparity, // 2.0; // do not try to trim texture outlines with lower disparities debugLevel); // final int debug_level) debugLevel); // final int debug_level) Loading Loading @@ -2080,11 +2080,6 @@ public class TexturedModel { dbg_mesh_imgs = new double[tileClusters.length][dbg_scaled_width * dbg_scaled_height]; dbg_mesh_imgs = new double[tileClusters.length][dbg_scaled_width * dbg_scaled_height]; // maybe fill with NaN? // maybe fill with NaN? } } // double [][] dbg /* tp.getTilesX(), // int tilesX, tp.getTilesY(), // int tilesY, */ for (int nslice = 0; nslice < tileClusters.length; nslice++){ for (int nslice = 0; nslice < tileClusters.length; nslice++){ if (dbg_tri_disp != null) { if (dbg_tri_disp != null) { Arrays.fill(dbg_tri_disp[nslice], Double.NaN); Arrays.fill(dbg_tri_disp[nslice], Double.NaN); Loading @@ -2094,28 +2089,34 @@ public class TexturedModel { ((dbg_tri_disp != null)? (new double[][] {dbg_tri_disp[nslice], dbg_tri_tri[nslice]}): ((dbg_tri_disp != null)? (new double[][] {dbg_tri_disp[nslice], dbg_tri_tri[nslice]}): (new double[][] {dbg_tri_tri[nslice]}) ): null; (new double[][] {dbg_tri_tri[nslice]}) ): null; if (debugLevel > -1){ if (debugLevel > -2){ System.out.println("Generating cluster images from texture slice "+nslice); System.out.println("Generating cluster images from texture slice "+nslice); } } int [] indices = tileClusters[nslice].getSubIndices(); int [] indices = tileClusters[nslice].getSubIndices(); Rectangle [] bounds = tileClusters[nslice].getSubBounds(); Rectangle [] bounds = tileClusters[nslice].getSubBounds(); // tiles? Rectangle texture_bounds = null; // if not null - allows trimmed combo textures tiles? int dbg_tri_indx = 3; // showing triangles for cluster 3 int dbg_tri_indx = 3; // showing triangles for cluster 3 for (int sub_i = 0; sub_i < indices.length; sub_i++) { for (int sub_i = 0; sub_i < indices.length; sub_i++) { Rectangle roi = bounds[sub_i]; Rectangle roi = bounds[sub_i]; int cluster_index = indices[sub_i]; int cluster_index = indices[sub_i]; ImagePlus imp_texture_cluster = combined_textures[nslice]; ImagePlus imp_texture_cluster = combined_textures[nslice]; boolean [] alpha = (combined_alphas != null) ? combined_alphas[nslice] : null; boolean [] alpha = (combined_alphas != null) ? combined_alphas[nslice] : null; if (imp_textures != null) { if (imp_textures != null) { // wrong? roi is in tiles or pixels? //transform_size imp_texture_cluster = imp_textures[cluster_index]; imp_texture_cluster = imp_textures[cluster_index]; if (combined_alphas != null) { if (combined_alphas != null) { alpha = new boolean[roi.height * roi.width]; int alpha_width = roi.width * transform_size; for (int row = 0; row < roi.height; row++) { int alpha_height = roi.height * transform_size; int alpha_x0 = roi.x * transform_size; int alpha_y0 = roi.y * transform_size; alpha = new boolean[alpha_width * alpha_height]; for (int row = 0; row < alpha_height; row++) { System.arraycopy( System.arraycopy( combined_alphas[nslice], combined_alphas[nslice], (roi.y + row) * width + roi.x, (alpha_y0 + row) * width + alpha_x0, alpha, alpha, row * roi.width, row * alpha_width, roi.width); alpha_width); } } } } } } Loading Loading @@ -2170,6 +2171,7 @@ public class TexturedModel { "shape_id-"+cluster_index, // id "shape_id-"+cluster_index, // id null, // class null, // class roi, // scan.getTextureBounds(), roi, // scan.getTextureBounds(), texture_bounds, // Rectangle texture_bounds, // if not null - allows trimmed combo textures scan_selected, // scan.getSelected(), scan_selected, // scan.getSelected(), scan_disparity, // scan.disparity_map[ImageDtt.DISPARITY_INDEX_CM], scan_disparity, // scan.disparity_map[ImageDtt.DISPARITY_INDEX_CM], clt_parameters.transform_size, clt_parameters.transform_size, Loading Loading @@ -2198,6 +2200,16 @@ public class TexturedModel { } } // if (imp_textures[nslice] != null) // if (imp_textures[nslice] != null) } // for (int nslice = 0; nslice < tileClusters.length; nslice++){ } // for (int nslice = 0; nslice < tileClusters.length; nslice++){ if (dbg_mesh_imgs != null) { ShowDoubleFloatArrays.showArrays( dbg_mesh_imgs, dbg_scaled_width, dbg_scaled_height, true, ref_scene.getImageName()+"-tri-meshes"); } if (dbg_tri_disp != null) { if (dbg_tri_disp != null) { ShowDoubleFloatArrays.showArrays( ShowDoubleFloatArrays.showArrays( dbg_tri_disp, dbg_tri_disp, Loading
src/main/java/com/elphel/imagej/x3d/export/TriMesh.java +103 −66 Original line number Original line Diff line number Diff line Loading @@ -235,19 +235,21 @@ public class TriMesh { final int [] num_indices final int [] num_indices ) { ) { //TODO: add optimization (merging some in-tile triangles) //TODO: add optimization (merging some in-tile triangles) final boolean full_image = selected_tiles.length > (bounds.height * bounds.width); final boolean full_selection = selected_tiles.length > (bounds.height * bounds.width); // applies to selected_tiles final boolean full_alpha = alpha.length > (bounds.height * bounds.width * tile_size * tile_size); final int [][][][] indices = new int [bounds.height][bounds.width][][]; final int [][][][] indices = new int [bounds.height][bounds.width][][]; final Thread[] threads = ImageDtt.newThreadArray(TexturedModel.THREADS_MAX); final Thread[] threads = ImageDtt.newThreadArray(TexturedModel.THREADS_MAX); final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0); final int source_tile_width = full_image? tilesX : bounds.width; final int source_tile_width = full_selection? tilesX : bounds.width; final int source_pix_width = source_tile_width * tile_size; // final int source_pix_width = source_tile_width * tile_size; final int source_tile_offsx = full_image? bounds.x : 0; final int source_tile_offsx = full_selection? bounds.x : 0; final int source_tile_offsy = full_image? bounds.y : 0; final int source_tile_offsy = full_selection? bounds.y : 0; // final int source_tile_offs = source_tile_offsx + source_tile_offsy * source_tile_width; // final int source_pix_offsx = source_tile_offsx * tile_size; final int source_pix_offsx = source_tile_offsx * tile_size; // final int source_pix_offsy = source_tile_offsy * tile_size; final int source_pix_offsy = source_tile_offsy * tile_size; final int source_pix_offsx = (full_alpha? bounds.x : 0) * tile_size; // final int source_pix_offs = source_pix_offsx + source_pix_offsy * source_pix_width; final int source_pix_offsy = (full_alpha? bounds.y : 0) * tile_size; // final int sub_size = Math.max(tile_size / subdiv, 1); final int source_pix_width = (full_alpha? tilesX : bounds.width) * tile_size; final int btiles = bounds.width * bounds.height; final int btiles = bounds.width * bounds.height; final AtomicInteger aindx = new AtomicInteger(0); final AtomicInteger aindx = new AtomicInteger(0); Loading Loading @@ -474,7 +476,7 @@ public class TriMesh { switch (dir) { switch (dir) { case 0: for (int i = 0; i < subdiv; i++) {edge[i] = tile[0][subdiv - i - 1];} break; case 0: for (int i = 0; i < subdiv; i++) {edge[i] = tile[0][subdiv - i - 1];} break; case 1: for (int i = 0; i < subdiv; i++) {edge[i] = tile[subdiv - i - 1][subdiv-1];} break; case 1: for (int i = 0; i < subdiv; i++) {edge[i] = tile[subdiv - i - 1][subdiv-1];} break; case 4: for (int i = 0; i < subdiv; i++) {edge[i] = tile[subdiv-1][i];} break; case 2: for (int i = 0; i < subdiv; i++) {edge[i] = tile[subdiv-1][i];} break; case 3: for (int i = 0; i < subdiv; i++) {edge[i] = tile[i][0];} break; case 3: for (int i = 0; i < subdiv; i++) {edge[i] = tile[i][0];} break; } } return edge; return edge; Loading Loading @@ -652,7 +654,7 @@ public class TriMesh { if (tris[btiley][btilex][y][x] == null) { if (tris[btiley][btilex][y][x] == null) { tris[btiley][btilex][y][x] = TRI_NONE.clone(); tris[btiley][btilex][y][x] = TRI_NONE.clone(); } } tris[btiley][btilex][y][x][1 << TRI_DOWN_LEFT] = atri.getAndIncrement(); tris[btiley][btilex][y][x][TRI_DOWN_LEFT] = atri.getAndIncrement(); } } } } Arrays.fill(quad_corners, false); Arrays.fill(quad_corners, false); Loading @@ -664,32 +666,33 @@ public class TriMesh { x = subdiv - 1; x = subdiv - 1; y = i - subdiv; y = i - subdiv; } } int num_corn = 0; quad_corners[0] = tneib_indices[8][y][x] >= 0; // this subtile if (quad_corners[0]) { // all following triangles assume that top-left corner exists int num_corn = 1; for (int dir = 1; dir < 4; dir++) { // skipping top-left corner for (int dir = 1; dir < 4; dir++) { // skipping top-left corner int x1 = x + TRI_OFFS_XY[dir][0]; int x1 = x + TRI_OFFS_XY[dir][0]; int y1 = y + TRI_OFFS_XY[dir][1]; int y1 = y + TRI_OFFS_XY[dir][1]; int [] xyd = getNeibNode(x1, y1, subdiv); int [] xyd = getNeibNode(x1, y1, subdiv); boolean exists = false; boolean exists = false; if (tneib_indices[xyd[2]] != null) { exists = (tneib_indices[xyd[2]] != null) && (tneib_indices[xyd[2]][xyd[1]][xyd[0]] >= 0); // is populated exists = tneib_indices[xyd[2]][xyd[1]][xyd[0]] >= 0; // is populated quad_corners[dir] = exists; quad_corners[dir] = exists; } if (exists) { if (exists) { num_corn ++; num_corn ++; } } } } if ((num_corn >= 3) && quad_corners[0]) { // that triangle (TRI_DOWN_LEFT) should already exist if (num_corn >= 3) { if (tris[btiley][btilex][y][x] == null) { if (tris[btiley][btilex][y][x] == null) { tris[btiley][btilex][y][x] = TRI_NONE.clone(); tris[btiley][btilex][y][x] = TRI_NONE.clone(); } } if (quad_corners[3]) { if (quad_corners[3]) { if (quad_corners[1]) { if (quad_corners[1]) { tris[btiley][btilex][y][x][1 << TRI_RIGHT_DOWNLEFT] = atri.getAndIncrement(); tris[btiley][btilex][y][x][TRI_RIGHT_DOWNLEFT] = atri.getAndIncrement(); } else { } else { tris[btiley][btilex][y][x][1 << TRI_DOWNRIGHT_LEFT] = atri.getAndIncrement(); tris[btiley][btilex][y][x][TRI_DOWNRIGHT_LEFT] = atri.getAndIncrement(); } } } else { } else { tris[btiley][btilex][y][x][1 << TRI_RIGHT_DOWN] = atri.getAndIncrement(); tris[btiley][btilex][y][x][TRI_RIGHT_DOWN] = atri.getAndIncrement(); } } } } } } } Loading Loading @@ -794,6 +797,8 @@ public class TriMesh { // type 4 (4 dirs, 2 triangles): // type 4 (4 dirs, 2 triangles): // 1 in ortho, 1 CCW from it, 2 CCW from 1. Does not need mirror, as the mirror will be if looking // 1 in ortho, 1 CCW from it, 2 CCW from 1. Does not need mirror, as the mirror will be if looking // from the last 2 (90 degrees CCW from the first 1) // from the last 2 (90 degrees CCW from the first 1) // type 5 (4 dirs, 1 triangle): // 1 in ortho, 2 CCW from it, 1 CCW from 1. Does not need mirror // First pass - reserving triangles indices // First pass - reserving triangles indices final Thread[] threads = ImageDtt.newThreadArray(TexturedModel.THREADS_MAX); final Thread[] threads = ImageDtt.newThreadArray(TexturedModel.THREADS_MAX); Loading @@ -817,14 +822,18 @@ public class TriMesh { if ((btx >= 0) && (btx < bwidth) && (bty >= 0) && (bty < bheight) && if ((btx >= 0) && (btx < bwidth) && (bty >= 0) && (bty < bheight) && (indices[bty][btx] != null)) { (indices[bty][btx] != null)) { tneib_types[dir] = 0; tneib_types[dir] = 0; if (indices[bty][btx] != null) { // if (indices[bty][btx] != null) { tneib_types[dir] = (indices[bty][btx].length > 1) ? 2 : 1; tneib_types[dir] = (indices[bty][btx].length > 1) ? 2 : 1; } // } has_full_neib |= (tneib_types[dir] == 1); // all modes 0..4 require 2-1 in ortho direction has_full_neib |= (tneib_types[dir] == 1) && ((dir & 1) == 0); } } } } if (has_full_neib) { if (has_full_neib) { tris[btiley][btilex] = new int [5][4]; // [types][directions tris[btiley][btilex] = new int [6][4]; // [types][directions for (int i = 0; i < tris[btiley][btilex].length; i++) { Arrays.fill(tris[btiley][btilex][i], -1); } // reserve indices for type0: // reserve indices for type0: for (int dir = 0; dir < 4; dir++) { for (int dir = 0; dir < 4; dir++) { int tneib = tneib_types[2*dir]; int tneib = tneib_types[2*dir]; Loading Loading @@ -868,6 +877,15 @@ public class TriMesh { tris[btiley][btilex][4][dir] = atri.getAndAdd(2); tris[btiley][btilex][4][dir] = atri.getAndAdd(2); } } } } // reserve indices for type5: for (int dir = 0; dir < 4; dir++) { int tneib = tneib_types[2*dir]; // pointed int tneib1= tneib_types[(2*dir+7) % 8]; // CCW 1 from pointed int tneib2= tneib_types[(2*dir+6) % 8]; // CCW 2 from pointed if ((tneib == 1) && (tneib1 == 2) && (tneib2 == 1)) { tris[btiley][btilex][5][dir] = atri.getAndAdd(1); } } } } } } } } Loading Loading @@ -905,7 +923,7 @@ public class TriMesh { int tri_index = tris[btiley][btilex][0][dir4]; // type0 int tri_index = tris[btiley][btilex][0][dir4]; // type0 if (tri_index >= 0) { if (tri_index >= 0) { int [] edge = getEdgeIndices(tneib_indices [8], dir4); int [] edge = getEdgeIndices(tneib_indices [8], dir4); int indx_1 = tneib_indices[2 * dir4][0][0]; int indx_1 = tneib_indices[2 * dir4][0][0]; // null pointer for (int i = 0; i < subdiv_m1; i++) { for (int i = 0; i < subdiv_m1; i++) { tri_indices[tri_index + i][0] = indx_1; tri_indices[tri_index + i][0] = indx_1; tri_indices[tri_index + i][1] = edge[i]; tri_indices[tri_index + i][1] = edge[i]; Loading Loading @@ -964,7 +982,19 @@ public class TriMesh { tri_indices[tri_index + 1][0] = indx_2; tri_indices[tri_index + 1][0] = indx_2; tri_indices[tri_index + 1][1] = edge[subdiv_m1]; tri_indices[tri_index + 1][1] = edge[subdiv_m1]; tri_indices[tri_index + 1][2] = edge[0]; tri_indices[tri_index + 1][2] = edge1[0]; } } // build triangles for type5: for (int dir4 = 0; dir4 < 4; dir4++) { int tri_index = tris[btiley][btilex][5][dir4]; // type5 if (tri_index >= 0) { int [] edge = getEdgeIndices(tneib_indices [8], dir4); int [] edge1 = getEdgeIndices(tneib_indices [(2 * dir4 + 7) % 8], (dir4 + 2) % 4); int indx_1 = tneib_indices[2 * dir4][0][0]; tri_indices[tri_index][0] = edge [subdiv_m1]; tri_indices[tri_index][1] = edge1[subdiv_m1]; tri_indices[tri_index][2] = indx_1; } } } } } } Loading Loading @@ -1876,6 +1906,7 @@ public class TriMesh { String id, String id, String class_name, String class_name, Rectangle bounds, Rectangle bounds, Rectangle texture_bounds, // if not null - allows trimmed combo textures // Below selected and disparity are bounds.width*bounds.height // Below selected and disparity are bounds.width*bounds.height boolean [] selected, // may be either tilesX * tilesY or bounds.width*bounds.height boolean [] selected, // may be either tilesX * tilesY or bounds.width*bounds.height double [] disparity, // if null, will use min_disparity double [] disparity, // if null, will use min_disparity Loading @@ -1900,7 +1931,7 @@ public class TriMesh { if (bounds == null) { if (bounds == null) { return; // not used in lwir return; // not used in lwir } } boolean display_triangles = debug_level > 0; /* /* Loading Loading @@ -1933,8 +1964,19 @@ public class TriMesh { indices, // int [][][][] indices) indices, // int [][][][] indices) subdivide_mesh); // final int [] num_indices) { subdivide_mesh); // final int [] num_indices) { Rectangle tex_rect = full_texture ? new Rectangle(bounds.x, bounds.y, tilesX, tilesY) : null; Rectangle tex_rect = full_texture ? ( (texture_bounds != null) ? new Rectangle( // when combo texture is trimmed (alpha should still be for the full image) bounds.x - texture_bounds.x, bounds.y - texture_bounds.y, texture_bounds.width, texture_bounds.height): new Rectangle( // when combo texture is full tilesX * tilesY bounds.x, bounds.y, tilesX, tilesY)) : null; // when texture is for cluster only /* /* * Get texture coordinates (0..1) for horizontal (positive - to the right) and vertical (positive - up) * Get texture coordinates (0..1) for horizontal (positive - to the right) and vertical (positive - up) */ */ Loading @@ -1954,23 +1996,13 @@ public class TriMesh { tile_size, // final int tile_size, tile_size, // final int tile_size, correctDistortions, // requires backdrop image to be corrected also correctDistortions, // requires backdrop image to be corrected also geometryCorrection);// final GeometryCorrection geometryCorrection) geometryCorrection);// final GeometryCorrection geometryCorrection) /* double [] indexedDisparity = getIndexedDisparities( // get disparity for each index // updated 09.18.2022 disparity, min_disparity, max_disparity, bounds, pnum_indices[0], // final int num_indices, indices, tilesX); */ /* /* * Triangulate all vertice indices - combine triangulation of same-size equailateral 45-degree * Triangulate all vertice indices - combine triangulation of same-size equailateral 45-degree * large (tile size) and small (tile subdivisions) and add connections between large and small ones * large (tile size) and small (tile subdivisions) and add connections between large and small ones */ */ int [][] triangles = triangulateAll( int [][] triangles = triangulateAll( indices); indices); System.out.println("generateClusterX3d(): got "+triangles.length+" triangles"); final boolean plot_center = true; final boolean plot_center = true; final double line_color = 1.0; final double line_color = 1.0; final double center_color = 3.0; final double center_color = 3.0; Loading @@ -1983,9 +2015,14 @@ public class TriMesh { plot_center, // final boolean plot_center, plot_center, // final boolean plot_center, line_color, // final double line_color, line_color, // final double line_color, center_color); // final double center_color) center_color); // final double center_color) if (display_triangles) { ShowDoubleFloatArrays.showArrays( tri_img, tri_img_width, tri_img.length / tri_img_width, "this-triangles"); } } } if (x3dOutput != null) { if (x3dOutput != null) { x3dOutput.addCluster( x3dOutput.addCluster( Loading