Commit 15b80649 authored by Andrey Filippov's avatar Andrey Filippov
Browse files

added wavefront export

parent 0a050e16
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -2131,6 +2131,8 @@ public class EyesisCorrectionParameters {
  		
  		public int        max_clusters     = 500;   // Maximal number of clusters to generate for one run
  		public boolean    remove_scans     = true;  // Remove all unneeded scans when generating x3d output to save memory
  		public boolean    output_x3d       = true;  // Generate x3d output
  		public boolean    output_obj       = true;  // Generate Wavefront obj output
  		
  		
  		public boolean    correct_distortions = false; // Correct lens geometric distortions in a model (will need backdrop to be corrected too)
@@ -2749,6 +2751,8 @@ public class EyesisCorrectionParameters {
			
			properties.setProperty(prefix+"max_clusters",     this.max_clusters+"");
			properties.setProperty(prefix+"remove_scans",     this.remove_scans+"");
			properties.setProperty(prefix+"output_x3d",       this.output_x3d+"");
			properties.setProperty(prefix+"output_obj",       this.output_obj+"");
			properties.setProperty(prefix+"correct_distortions",this.correct_distortions+"");
			properties.setProperty(prefix+"show_triangles",   this.show_triangles+"");
			properties.setProperty(prefix+"avg_cluster_disp", this.avg_cluster_disp+"");
@@ -3324,6 +3328,8 @@ public class EyesisCorrectionParameters {
  			
  			if (properties.getProperty(prefix+"max_clusters")!=null)      this.max_clusters=Integer.parseInt(properties.getProperty(prefix+"max_clusters"));
  			if (properties.getProperty(prefix+"remove_scans")!=null)      this.remove_scans=Boolean.parseBoolean(properties.getProperty(prefix+"remove_scans"));
  			if (properties.getProperty(prefix+"output_x3d")!=null)        this.output_x3d=Boolean.parseBoolean(properties.getProperty(prefix+"output_x3d"));
  			if (properties.getProperty(prefix+"output_obj")!=null)        this.output_obj=Boolean.parseBoolean(properties.getProperty(prefix+"output_obj"));
  			if (properties.getProperty(prefix+"correct_distortions")!=null) this.correct_distortions=Boolean.parseBoolean(properties.getProperty(prefix+"correct_distortions"));
  			if (properties.getProperty(prefix+"show_triangles")!=null)    this.show_triangles=Boolean.parseBoolean(properties.getProperty(prefix+"show_triangles"));
  			if (properties.getProperty(prefix+"avg_cluster_disp")!=null)  this.avg_cluster_disp=Boolean.parseBoolean(properties.getProperty(prefix+"avg_cluster_disp"));
@@ -3927,6 +3933,8 @@ public class EyesisCorrectionParameters {
  			
  			gd.addNumericField("Maximal number of clusters to generate for one run",                           this.max_clusters,   0);
  			gd.addCheckbox    ("Remove all unneeded scans when generating x3d output to save memory",          this.remove_scans);
  			gd.addCheckbox    ("Generate x3d output",                                                          this.output_x3d);
  			gd.addCheckbox    ("Generate Wavefront obj output",                                                this.output_obj);
  			gd.addCheckbox    ("Correct lens geometric distortions in a model (will need backdrop to be corrected too)", this.correct_distortions);
  			gd.addCheckbox    ("Show generated triangles",                                                     this.show_triangles);
  			gd.addCheckbox    ("Weight-average disparity for the whole cluster ",                              this.avg_cluster_disp);
@@ -4534,6 +4542,8 @@ public class EyesisCorrectionParameters {

  			this.max_clusters=    (int) gd.getNextNumber();
  			this.remove_scans=          gd.getNextBoolean();
  			this.output_x3d=            gd.getNextBoolean();
  			this.output_obj=            gd.getNextBoolean();
  			this.correct_distortions=   gd.getNextBoolean();
  			this.show_triangles=        gd.getNextBoolean();
  			this.avg_cluster_disp=      gd.getNextBoolean();
+105 −58
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@

//import java.awt.Polygon;
import java.awt.Rectangle;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
@@ -6171,7 +6172,8 @@ public class QuadCLT {
		  if (this.image_data == null){
			  return false;
		  }
		  
		  X3dOutput x3dOutput = null;
		  WavefrontExport wfOutput = 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");
@@ -6199,18 +6201,37 @@ public class QuadCLT {
		  tp.showScan(
				  tp.clt_3d_passes.get(next_pass-1),   // CLTPass3d   scan,
				  "after_pass3-"+(next_pass-1)); //String title)
 		  String x3d_path= correctionsParameters.selectX3dDirectory( // for x3d and obj
				  true,  // smart,
				  true);  //newAllowed, // save

 			// create x3d file
		  X3dOutput x3dOutput = new X3dOutput(
		  if (clt_parameters.output_x3d) {
			  x3dOutput = new X3dOutput(
					clt_parameters,
					correctionsParameters,
					geometryCorrection,
					tp.clt_3d_passes);
		  
		  }
		  if (clt_parameters.output_obj && (x3d_path != null)) {
			  try {
				wfOutput = new WavefrontExport(
						  x3d_path,
						  this.image_name,
						  clt_parameters,
						  correctionsParameters,
						  geometryCorrection,
						  tp.clt_3d_passes);
			} catch (IOException e) {
				System.out.println("Failed to open Wavefront files for writing");
				// TODO Auto-generated catch block
				e.printStackTrace();
				// do nothing, just keep 
			}
		  }
		  if (x3dOutput != null) {
			  x3dOutput.generateBackground(clt_parameters.infinityDistance <= 0.0); // needs just first (background) scan
 		  String x3d_path= correctionsParameters.selectX3dDirectory(
				  true,  // smart,
				  true);  //newAllowed, // save
		 
		  }
 		  
 		  if (clt_parameters.infinityDistance > 0.0){ // generate background as a billboard
// 			  tp.showScan(
@@ -6272,8 +6293,10 @@ public class QuadCLT {
//    				  "infinityDistance");
			  
			  boolean showTri = false; // ((scanIndex < next_pass + 1) && clt_parameters.show_triangles) ||((scanIndex - next_pass) == 73);
			  try {
				generateClusterX3d(
						  x3dOutput,
						  wfOutput,  // output WSavefront if not null
						  texturePath,
						  "INFINITY", // id (scanIndex - next_pass), // id
						  "INFINITY", // class
@@ -6286,6 +6309,11 @@ public class QuadCLT {
						  infinity_disparity,  // 0.3
						  clt_parameters.grow_disp_max, // other_range, // 2.0 'other_range - difference from the specified (*_CM)
						  clt_parameters.maxDispTriangle);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return false;
			}
			  // maybe not needed
 			  scan.setBorderTiles(bg_border_backup);
 			  scan.setSelected(bg_sel_backup);
@@ -6376,8 +6404,10 @@ public class QuadCLT {
			  boolean showTri = ((scanIndex < next_pass + 1) && clt_parameters.show_triangles) ||((scanIndex - next_pass) == 73);
			  
//			  boolean showTri = ((scanIndex < next_pass + 1) && clt_parameters.show_triangles) ||(scanIndex == 49) || (scanIndex == 54);
			  try {
				generateClusterX3d(
						  x3dOutput,
						  wfOutput,  // output WSavefront if not null
						  texturePath,
						  "shape_id-"+(scanIndex - next_pass), // id
						  null, // class
@@ -6390,17 +6420,23 @@ public class QuadCLT {
						  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);



			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return false;
			}
		  }

		  // now generate and save texture files (start with full, later use bounding rectangle?)


		  if (x3d_path != null){
			  x3d_path+=Prefs.getFileSeparator()+this.image_name+".x3d";
			  x3dOutput.generateX3D(x3d_path);
		  if ((x3d_path != null) && (x3dOutput != null)){
//			  x3d_path+=Prefs.getFileSeparator()+this.image_name+".x3d";
//			  x3dOutput.generateX3D(x3d_path);
			  x3dOutput.generateX3D(x3d_path+Prefs.getFileSeparator()+this.image_name+".x3d");
		  }
		  if (wfOutput != null){
			  wfOutput.close();
		  }
		  return true;
//		  return imp_bgnd; // relative (to x3d directory) path - (String) imp_bgnd.getProperty("name");
@@ -6410,7 +6446,8 @@ public class QuadCLT {
	  
	  
	  public void generateClusterX3d(
			  X3dOutput  x3dOutput,
			  X3dOutput       x3dOutput, // output x3d if not null
			  WavefrontExport wfOutput,  // output WSavefront if not null
			  String          texturePath,
			  String          id,
			  String          class_name,
@@ -6423,7 +6460,7 @@ public class QuadCLT {
			  double          min_disparity,
			  double          max_disparity,
			  double          maxDispTriangle
			  ) 
			  ) throws IOException 
	  {
		  int [][] indices =  tp.getCoordIndices( // starting with 0, -1 - not selected
				  bounds,
@@ -6472,7 +6509,7 @@ public class QuadCLT {
					  indices,
					  triangles);
		  }

		  if (x3dOutput != null) {
		  x3dOutput.addCluster(
				  texturePath,
				  id,
@@ -6481,6 +6518,16 @@ public class QuadCLT {
				  worldXYZ,
				  triangles);
		  }
		  if (wfOutput != null) {
			  wfOutput.addCluster(
				  texturePath,
				  id,
//				  class_name,
				  texCoord,
				  worldXYZ,
				  triangles);
		  }
	  }
	  
	  
	  public ImagePlus getBackgroundImage(
+153 −0
Original line number Diff line number Diff line
import java.io.FileWriter;
import java.io.IOException;

/**
 **
 ** generate Wavefront representation of the model
 **
 ** Copyright (C) 2017 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.util.ArrayList;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import ij.Prefs;

public class WavefrontExport {
	static final String MTL_EXT=".mtl";
	static final String OBJ_EXT=".obj";
		GeometryCorrection                                     geometry_correction;
		public ArrayList <CLTPass3d>             clt_3d_passes;
		public  EyesisCorrectionParameters.CLTParameters       clt_parameters;
		public EyesisCorrectionParameters.CorrectionParameters correctionsParameters;
		public int debugLevel = 1;
		FileWriter obj_writer; // f0 = new FileWriter("output.txt");
		FileWriter mtl_writer; // f0 = new FileWriter("output.txt");
		Document    x3dDoc;
		Element     el_X3d;
		Element     el_Scene;
		Element     el_TopGroup;
		public int  max_line_length = 0; // 100; // 0 - no limit
		public int v_index =  1; // first index is 1, not 0
		public int vt_index = 1; // first index is 1, not 0
		public int f_index =  1; // first index is 1, not 0

		public WavefrontExport(
				String                                          out_dir,
				String                                          project_name,
				EyesisCorrectionParameters.CLTParameters        clt_parameters,
				EyesisCorrectionParameters.CorrectionParameters correctionsParameters,
				GeometryCorrection                              geometry_correction,
				ArrayList <CLTPass3d>             clt_3d_passes) throws IOException{
			this.clt_parameters =        clt_parameters;
			this.correctionsParameters = correctionsParameters;
			this.geometry_correction =    geometry_correction;
			this.clt_3d_passes = clt_3d_passes;
			mtl_writer = new FileWriter(out_dir+Prefs.getFileSeparator()+project_name+MTL_EXT);
			obj_writer = new FileWriter(out_dir+Prefs.getFileSeparator()+project_name+OBJ_EXT); // .close();
			mtl_writer.write("#\n# Wavefront material file\n#\n");
			obj_writer.write("#\n# Wavefront object file\n#\n");
			obj_writer.write("mtllib ./"+project_name+MTL_EXT+"\n\n"); // add "./" to indicate relative path? // ./1488240527_408296.obj.mtl\n");
			
		}
		public void close()
		{
			try {
				mtl_writer.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				obj_writer.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		public void addCluster(
				String      texture_path,
				String      material_id,
				double [][] texCoord,
				double [][] coordinate,
				int [][] triangles) throws IOException
		{
			// Write to material file
/*
newmtl material_0
Ka 0.200000 0.200000 0.200000
Kd 1.000000 1.000000 1.000000
Ks 1.000000 1.000000 1.000000
Tr 1.000000
illum 2
Ns 0.000000
map_Kd 1488240527_408296-img2-texture.png
 */
			mtl_writer.write("\nnewmtl "+material_id+"\n");
			mtl_writer.write("Ka 0.200000 0.200000 0.200000\n");
			mtl_writer.write("Kd 1.000000 1.000000 1.000000\n");
			mtl_writer.write("Ks 1.000000 1.000000 1.000000\n");
			mtl_writer.write("Tr 1.000000\n");
			mtl_writer.write("illum 2\n");
//			mtl_writer.write("illum 0\n"); // should it be 0 orf 2?
			mtl_writer.write("Ns 0.000000\n");
			mtl_writer.write("map_Kd "+texture_path+"\n");
			
			// Write OBJ file
			// start using new material
			
			obj_writer.write("usemtl "+material_id+"\n");
			// output all vertices
			obj_writer.write("# start from vertex :         "+ v_index+ "\n");
			obj_writer.write("# start from texture vertex:  "+ vt_index+"\n");
			obj_writer.write("# start from face (triangle): "+ f_index+ "\n");
			for (int i = 0; i < coordinate.length; i++){
				obj_writer.write(String.format("v %.3f %.3f %.3f\n", coordinate[i][0], coordinate[i][1], coordinate[i][2]));
			}
			// output all texture vertices
			for (int i = 0; i < texCoord.length; i++){
				obj_writer.write(String.format("vt %.5f %.5f\n", texCoord[i][0], texCoord[i][1]));
			}
			// output all triangles (faces)
			for (int i = 0; i < triangles.length; i++){
				obj_writer.write(String.format("f %d/%d %d/%d %d/%d\n",
						triangles[i][0]+v_index,triangles[i][0]+vt_index, // actually v_index and vt_index should =be the same
						triangles[i][1]+v_index,triangles[i][1]+vt_index,
						triangles[i][2]+v_index,triangles[i][2]+vt_index));
			}
			obj_writer.write("# end of material "+   material_id+"\n");
			obj_writer.write("# vertices:          "+         coordinate.length+"\n");
			obj_writer.write("# texture vertices:  "+ texCoord.length+"\n");
			obj_writer.write("# faces (triangles): "+ triangles.length+"\n");
			
			obj_writer.write("\n");
			// increment indices
			v_index +=  coordinate.length;
			vt_index += texCoord.length;
			f_index +=  triangles.length;
//f 27151/27139/27151 27141/27140/27141 27140/27141/27140			 * 
			
		}
		
		
		
}
+0 −1
Original line number Diff line number Diff line

/**
 **
 ** X3dOutput - generate x3d representation of the model