UV mapping Programatically and unwrapping with Blender

Hello I’ve come across the following thread UV_Unwrapping regarding to UV unwrapping in three.js . I want to make a 3D sculpting of the following 2D image -


I studied a little bit about photogrammetry but avoided SGBM algorithm (since it is compute intensive) and skipped to the last step - generating point cloud mesh from depth map. For depth map I graycycled the image and considered RGB values as depth. What I came up is like the following -

And my model is link is - model.zip (821.5 KB)
But I am facing problem with UV unwrapping. It looks like following -

How can I map the UV-coordinates properly ?
My code is the following -

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.CvType;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.io.*;
import java.util.Scanner;

public class trilinear_inp{
	public double round(double num){
		int floor = (int) num;
		double floor_d = (double) floor;
		double celing_d = floor_d + 1;
		double mid_d = (floor_d + celing_d)/2;
		if(num < mid_d){
			return floor_d;
		}else if(num >= mid_d){
			return celing_d;
		}else{
			System.out.println("Unable to round off");
			return 0;
		}
	}
	public Mat interpolate(Mat ip,int op_height,int op_width){
		trilinear_inp ob = new trilinear_inp();
		int ip_h = ip.rows();
		int ip_w = ip.cols();
		Mat op = new Mat(op_height,op_width,CvType.CV_8UC3);
		for(int i=0;i<op_height;i++){
			for(int j=0;j<op_width;j++){
				double uf = ((double)i)/op_height*ip_h;
				double vf = ((double)j)/op_width*ip_w;
				
				int ui = (int) uf;
				int vi = (int) vf;
				int u2 = ui+1, v2 = vi+1;
				double mu = uf - ui, nu = vf - vi;
				if(ui < 0){
					ui = 0;
				}else if(ui >= 0 && ui < ip_h){
					ui = ui;
				}else if(ui >= ip_h){
					ui = ip_h-1;
				}else{
					System.err.println("vi not found!");
				}
				if(u2 < 0){
					u2 = 0;
				}else if(u2 >= 0 && u2 < ip_h){
					u2 = u2;
				}else if(u2 >= ip_h){
					u2 = ip_h-1;
				}else{
					System.err.println("v2 not found!");
				}
				
				double[] a = ip.get(ui,vi % ip_w);
				double[] b = ip.get(ui,v2 % ip_w);
				double[] c = ip.get(u2,vi % ip_w);
				double[] d = ip.get(u2,v2 % ip_w);
				
				double[] dd = new double[3];
				dd[0] = a[0]*(1-mu)*(1-nu) + b[0]*mu*(1-nu) + c[0]*(1-mu)*nu + d[0]*mu*nu;
				dd[1] = a[1]*(1-mu)*(1-nu) + b[1]*mu*(1-nu) + c[1]*(1-mu)*nu + d[1]*mu*nu;
				dd[2] = a[2]*(1-mu)*(1-nu) + b[2]*mu*(1-nu) + c[2]*(1-mu)*nu + d[2]*mu*nu;
				
				double[] dd_r = new double[]{ ob.round(dd[0]),ob.round(dd[1]),ob.round(dd[2]) };
				try{
					op.put(i,j,dd_r);
				}catch(Exception e){}
			}
		}return op;
	}
	public double[] getNormal(double[] center,double[] h_coord,double[] v_coord){
		double x1 = center[0], y1 = center[1], z1 = center[2], x2 = h_coord[0], y2 = h_coord[1], z2 = h_coord[2], x3 = v_coord[0], y3 = v_coord[1], z3 = v_coord[2];
		double xf = (y2 - y1)*(z3 - z1) - (y3 - y1)*(z2 - z1);
		double yf = (x2 - x1)*(z3 - z1) - (x3 - x1)*(z2 - z1);
		double zf = (x2 - x1)*(y3 - y1) - (x3 - x1)*(y2 - y1);
		double a = Math.sqrt(xf*xf + yf*yf + zf*zf);
		xf = xf / a;
		yf = yf / a;
		zf = zf / a;
		return new double[]{xf,yf,zf};
	}
	public static void main(String[] args) throws Exception{
		trilinear_inp obj = new trilinear_inp();
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
		//System.out.print("Enter the path of the image: ");
		//String input = (new Scanner(System.in)).nextLine();
		Mat ip = Imgcodecs.imread("./img062.jpg");
		int ip_h = ip.rows();
		int ip_w = ip.cols();
		System.out.println("height: "+ip_h+" width: "+ip_w);
		System.out.print("Enter output width (length along x-axis): ");
		int op_width = (new Scanner(System.in)).nextInt();
		System.out.print("Enter output height (length along z-axis): ");
		int op_height = (new Scanner(System.in)).nextInt();
		System.out.print("Enter output depth (length along y-axis): ");
		double op_depth = (new Scanner(System.in)).nextDouble();
		FileWriter writer = new FileWriter("final.obj");
		writer.write("# sample obj file\no Sample\n");
		writer.write("mtllib final.mtl\n");
		Mat op = obj.interpolate(ip,op_height,op_width);
		double[][][] vertices = new double[op_height][op_width][3];
		String vtstr = "";
 		for(int i=0;i<op_height;i++){
			for(int j=0;j<op_width;j++){
				double[] color = op.get(i,j);
				double g = (color[0]+color[1]+color[2]) / 3;
				double z = ( g * ( (double)op_depth / 255 ) );
				double y = (1 - 2*((double)i/(op_height - 1)))*((double)op_height/op_width);
				double x = (2*((double)j/(op_width - 1)) - 1);
				vertices[i][j][0] = x;
				vertices[i][j][1] = y;
				vertices[i][j][2] = z;
				writer.write("v "+x+" "+y+" "+z+"\n");
				double u = 1 - ((double)i)/(op_height - 1);
				double v = ((double)j)/(op_width - 1);
				vtstr += "vt "+y+" "+x+"\n";
			}
		}
		writer.write(vtstr);
		double[][][] vn = new double[op_height][op_width][3];
		String str = "";int c = 1;
		for(int i=0;i<op_height;i++){
			for(int j=0;j<op_width;j++){
				if(i<op_height - 1&&j<op_width - 1){
					int index = i*op_width + j + 1;
					int index1 = (i + 1)*op_width + j + 1;
					int index2 = (i + 1)*op_width + (j + 1) + 1;
					int index3 = i*op_width + (j + 1) + 1;
					str += "f "+index+"/"+c+" "+index1+"/"+c+" "+index2+"/"+c+" "+index3+"/"+c+"\n";
				}c++;
			}
		}
		//System.out.println(c);
		writer.write("usemtl Material\n");
		writer.write(str);
		//f 200 50000 49801 1
		
		writer.close();
	}
}

I wrote it in JAVA with openCV(I took width: 200 height: 250 depth: 0.4).I am satisfied with the mesh.I will edit it further on blender.
Please help me to obtain the proper UV coordinates.
Ref: Object (.obj) files
Additional question: Is it has anything to do with vertex normal ?

I think you’ll get an answer much faster on Blender’s StackOverflow
It seems related to Blender UV mapping, not ThreeJS?

It relates to standard uv mapping convention for any obj files regardless of Blender or Maya or Cine4D or anything else. I am trying to get a workaround anyway. I am working on an webpage where I can upload an image and get a 3d sculpture and display it using three.js (and export it as obj )

I had to unwrap it then bake the texture according to my own requirement.
Unwrapped mesh looks as following


Final model image below -

I’ll do the sculpting later.

1 Like