Using three.js in my Qt QML Program



  • Hi, I'd like to use three.js in my program to render .obj files. I've looked online at https://github.com/tronlec/three.js which describes a simple example that I can run on my own. I changed the program to have the following code for rendering an .obj file:

    var manager = new THREE.LoadingManager();
    loader = new THREE.OBJLoader(manager);
    loader.load('C:/Users/dillydill123/Documents/Qt/exampleProj/object.obj', function (object) {
    
        object.traverse(function (child) {
            if (child instanceof THREE.Mesh) {
                child.material.side = THREE.Material.DoubleSide;
            }
        });
    
        scene.add(object);
    });
    

    Unfortunately, when I run this code, I get type errors, saying that OBJLoader is not a type. It looks like the three.js library from https://github.com/tronlec/three.js/blob/master/build/three.js does not include OBJLoader. I've tried appending the source code of OBJLoader from https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/OBJLoader.js to the end of my three.js file in my QRC, but I get other type errors for FIleLoader. When I attempt to append that to three.js, I get other type errors.

    I also want to be able to use other extensions/modules from three.js, namely TrackBallControls. Unfortunately, I get other type errors when trying to append this to the end of my three.js.

    My questions are the following: How do I render a .obj file in Qt QML using three.js? And how can I easily add modules and extensions to three.js?



  • @dillydill123 in case this is still an issue :
    you have to include the loader code - copy the OBJLoader.js to a directory (e.g. loaders) where it gets found by this statement:
    Qt.include("loaders/OBJLoader.js")
    ....
    // load file :
    var objLoader = new THREE.OBJLoader( THREE.DefaultLoadingManager );
    objLoader.setMaterials( materials );
    objLoader.setPath('C:/Users/dillydill123/Documents/Qt/exampleProj/');
    objLoader.load('object.obj', function ( object ) {
    // here add the loaded object
    scene.add(object)
    } );

    best regards,
    Michael



  • Hi @IPO_DEV
    I just tried your approach with the three.js-master\qt-examples\quickitemtexture example, but I get the following error

    qrc:/loader/OBJLoader.js:381: TypeError: Type error
    

    Line 381 in OBJLoader.js is:

    var loader = new THREE.FileLoader( scope.manager );
    

    I tried with the mesh from Qt\Examples\Qt-5.11.0\datavisualization\customitems\refinery.obj which I copied to the quickitemtexture example dir and then used:

        // load file :
        var objLoader = new THREE.OBJLoader(THREE.DefaultLoadingManager );
        objLoader.setMaterials( material );
        objLoader.setPath('G:/Source/Qt/three.js-master/qt-examples/quickitemtexture/');
    
        objLoader.load('refinery.obj', function ( object ) {
            // here add the loaded object
            scene.add(object)
        } );
    

    Any ideas?



  • @Diracsbracket
    ok I've forgot to paste the MTLLoader part - here' s a complete snippet:

    
    
    Qt.include("loaders/MTLLoader.js")
    Qt.include("loaders/OBJLoader.js")
    
    function addOBJ(scene)
    {
        // suppose we load a campfire.obj with its material file campfire.mtl
        var baseName =  "campfire"
        var baseUrl = "file:///D:/_SOURCE/threejs_qt_74/examples/models/campfire/"
    
        var mtlLoader = new THREE.MTLLoader();
                // set baseurl + path to baseurl
                mtlLoader.setBaseUrl( baseUrl );
                mtlLoader.setPath(baseUrl);
                var materialFile =  baseName + ".mtl"
                console.log("matfile ->" + materialFile)
                // now load material file first
                mtlLoader.load(materialFile, function( materials ) {
    
    
                // make sure all materials are loaded
                materials.preload();
                console.log("LOADED MAT..");
    
                // define progress and error callbacks
                var onProgress = function ( xhr ) {
                    console.log("PRG " + xhr);
    
                    };
                var onError = function ( xhr ) {
                    console.log("ERROR" + xhr);
                    };
                   // now load OBJ with materials already loaded
                var objLoader = new THREE.OBJLoader( THREE.DefaultLoadingManager );
                objLoader.setMaterials( materials );
                objLoader.setPath(baseUrl );
                objLoader.load( baseName+".obj", function ( object ) {
                        // callback for model loaded :
                        console.log("LOADED OBJ");
                        // get some info about loaded model
                        var box = new  THREE.Box3();
                        box.setFromObject(object);
                        var center = box.center();
                        var size = box.size();
                        console.log("SIZE:" + JSON.stringify( size))
                        console.log("CENTER:" + JSON.stringify( center))
                        scene.add(object)
                        // sample manipulation, move the loaded object -17 along z
                        object.position.z = -17.0;
                        }
                ) //  objLoader.load
    
                }) // mtlLoader.load
    
    
    }
    

    call addOBJ() with your scene...



  • Thanks for the code @IPO_DEV !
    I tried it but I still get the same error at the same line:

    var loader = new THREE.FileLoader( scope.manager );
    

    No worries though, as I am a complete NOOB concerning JavaScript (apart from the little I use for QML), three.js and 3D graphics, really. I was just trying to test something out by taking a working example and replacing the object added to the scene by the one read from the .obj file...

    I know I must be missing some simple stuff that will become obvious if I learn more, which I will.

    Cheers!



  • @Diracsbracket hm this is strange, i've also used the quickitemtexture example and just added the code i've posted - it seems that u're using a different loader code - the line in my OBJLoader.js looks different (var loader = new THREE.XHRLoader( scope.manager ); )
    Here is the complete source for both files:

    OBJLoader.js:

    /**
     * @author mrdoob / http://mrdoob.com/
     */
    
    THREE.OBJLoader = function ( manager ) {
    
    	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
    
    	this.materials = null;
    
    };
    
    THREE.OBJLoader.prototype = {
    
    	constructor: THREE.OBJLoader,
    
    	load: function ( url, onLoad, onProgress, onError ) {
    
    		var scope = this;
    
    		var loader = new THREE.XHRLoader( scope.manager );
    		loader.setPath( this.path );
    		loader.load( url, function ( text ) {
    
    			onLoad( scope.parse( text ) );
    
    		}, onProgress, onError );
    
    	},
    
    	setPath: function ( value ) {
    
    		this.path = value;
    
    	},
    
    	setMaterials: function ( materials ) {
    
    		this.materials = materials;
    
    	},
    
    	parse: function ( text ) {
    
    		console.time( 'OBJLoader' );
    
    		var objects = [];
    		var object;
    		var foundObjects = false;
    		var vertices = [];
    		var normals = [];
    		var uvs = [];
    
    		function addObject( name ) {
    
    			var geometry = {
    				vertices: [],
    				normals: [],
    				uvs: []
    			};
    
    			var material = {
    				name: '',
    				smooth: true
    			};
    
    			object = {
    				name: name,
    				geometry: geometry,
    				material: material
    			};
    
    			objects.push( object );
    
    		}
    
    		function parseVertexIndex( value ) {
    
    			var index = parseInt( value );
    
    			return ( index >= 0 ? index - 1 : index + vertices.length / 3 ) * 3;
    
    		}
    
    		function parseNormalIndex( value ) {
    
    			var index = parseInt( value );
    
    			return ( index >= 0 ? index - 1 : index + normals.length / 3 ) * 3;
    
    		}
    
    		function parseUVIndex( value ) {
    
    			var index = parseInt( value );
    
    			return ( index >= 0 ? index - 1 : index + uvs.length / 2 ) * 2;
    
    		}
    
    		function addVertex( a, b, c ) {
    
    			object.geometry.vertices.push(
    				vertices[ a ], vertices[ a + 1 ], vertices[ a + 2 ],
    				vertices[ b ], vertices[ b + 1 ], vertices[ b + 2 ],
    				vertices[ c ], vertices[ c + 1 ], vertices[ c + 2 ]
    			);
    
    		}
    
    		function addNormal( a, b, c ) {
    
    			object.geometry.normals.push(
    				normals[ a ], normals[ a + 1 ], normals[ a + 2 ],
    				normals[ b ], normals[ b + 1 ], normals[ b + 2 ],
    				normals[ c ], normals[ c + 1 ], normals[ c + 2 ]
    			);
    
    		}
    
    		function addUV( a, b, c ) {
    
    			object.geometry.uvs.push(
    				uvs[ a ], uvs[ a + 1 ],
    				uvs[ b ], uvs[ b + 1 ],
    				uvs[ c ], uvs[ c + 1 ]
    			);
    
    		}
    
    		function addFace( a, b, c, d,  ua, ub, uc, ud, na, nb, nc, nd ) {
    
    			var ia = parseVertexIndex( a );
    			var ib = parseVertexIndex( b );
    			var ic = parseVertexIndex( c );
    			var id;
    
    			if ( d === undefined ) {
    
    				addVertex( ia, ib, ic );
    
    			} else {
    
    				id = parseVertexIndex( d );
    
    				addVertex( ia, ib, id );
    				addVertex( ib, ic, id );
    
    			}
    
    			if ( ua !== undefined ) {
    
    				ia = parseUVIndex( ua );
    				ib = parseUVIndex( ub );
    				ic = parseUVIndex( uc );
    
    				if ( d === undefined ) {
    
    					addUV( ia, ib, ic );
    
    				} else {
    
    					id = parseUVIndex( ud );
    
    					addUV( ia, ib, id );
    					addUV( ib, ic, id );
    
    				}
    
    			}
    
    			if ( na !== undefined ) {
    
    				ia = parseNormalIndex( na );
    				ib = parseNormalIndex( nb );
    				ic = parseNormalIndex( nc );
    
    				if ( d === undefined ) {
    
    					addNormal( ia, ib, ic );
    
    				} else {
    
    					id = parseNormalIndex( nd );
    
    					addNormal( ia, ib, id );
    					addNormal( ib, ic, id );
    
    				}
    
    			}
    
    		}
    
    		addObject( '' );
    
    		// v float float float
    		var vertex_pattern = /^v\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)/;
    
    		// vn float float float
    		var normal_pattern = /^vn\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)/;
    
    		// vt float float
    		var uv_pattern = /^vt\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)/;
    
    		// f vertex vertex vertex ...
    		var face_pattern1 = /^f\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)(?:\s+(-?\d+))?/;
    
    		// f vertex/uv vertex/uv vertex/uv ...
    		var face_pattern2 = /^f\s+((-?\d+)\/(-?\d+))\s+((-?\d+)\/(-?\d+))\s+((-?\d+)\/(-?\d+))(?:\s+((-?\d+)\/(-?\d+)))?/;
    
    		// f vertex/uv/normal vertex/uv/normal vertex/uv/normal ...
    		var face_pattern3 = /^f\s+((-?\d+)\/(-?\d+)\/(-?\d+))\s+((-?\d+)\/(-?\d+)\/(-?\d+))\s+((-?\d+)\/(-?\d+)\/(-?\d+))(?:\s+((-?\d+)\/(-?\d+)\/(-?\d+)))?/;
    
    		// f vertex//normal vertex//normal vertex//normal ...
    		var face_pattern4 = /^f\s+((-?\d+)\/\/(-?\d+))\s+((-?\d+)\/\/(-?\d+))\s+((-?\d+)\/\/(-?\d+))(?:\s+((-?\d+)\/\/(-?\d+)))?/;
    
    		var object_pattern = /^[og]\s+(.+)/;
    
    		var smoothing_pattern = /^s\s+([01]|on|off)/;
    
    		//
    
    		var lines = text.split( '\n' );
    
    		for ( var i = 0; i < lines.length; i ++ ) {
    
    			var line = lines[ i ];
    			line = line.trim();
    
    			var result;
    
    			if ( line.length === 0 || line.charAt( 0 ) === '#' ) {
    
    				continue;
    
    			} else if ( ( result = vertex_pattern.exec( line ) ) !== null ) {
    
    				// ["v 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
    
    				vertices.push(
    					parseFloat( result[ 1 ] ),
    					parseFloat( result[ 2 ] ),
    					parseFloat( result[ 3 ] )
    				);
    
    			} else if ( ( result = normal_pattern.exec( line ) ) !== null ) {
    
    				// ["vn 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
    
    				normals.push(
    					parseFloat( result[ 1 ] ),
    					parseFloat( result[ 2 ] ),
    					parseFloat( result[ 3 ] )
    				);
    
    			} else if ( ( result = uv_pattern.exec( line ) ) !== null ) {
    
    				// ["vt 0.1 0.2", "0.1", "0.2"]
    
    				uvs.push(
    					parseFloat( result[ 1 ] ),
    					parseFloat( result[ 2 ] )
    				);
    
    			} else if ( ( result = face_pattern1.exec( line ) ) !== null ) {
    
    				// ["f 1 2 3", "1", "2", "3", undefined]
    
    				addFace(
    					result[ 1 ], result[ 2 ], result[ 3 ], result[ 4 ]
    				);
    
    			} else if ( ( result = face_pattern2.exec( line ) ) !== null ) {
    
    				// ["f 1/1 2/2 3/3", " 1/1", "1", "1", " 2/2", "2", "2", " 3/3", "3", "3", undefined, undefined, undefined]
    
    				addFace(
    					result[ 2 ], result[ 5 ], result[ 8 ], result[ 11 ],
    					result[ 3 ], result[ 6 ], result[ 9 ], result[ 12 ]
    				);
    
    			} else if ( ( result = face_pattern3.exec( line ) ) !== null ) {
    
    				// ["f 1/1/1 2/2/2 3/3/3", " 1/1/1", "1", "1", "1", " 2/2/2", "2", "2", "2", " 3/3/3", "3", "3", "3", undefined, undefined, undefined, undefined]
    
    				addFace(
    					result[ 2 ], result[ 6 ], result[ 10 ], result[ 14 ],
    					result[ 3 ], result[ 7 ], result[ 11 ], result[ 15 ],
    					result[ 4 ], result[ 8 ], result[ 12 ], result[ 16 ]
    				);
    
    			} else if ( ( result = face_pattern4.exec( line ) ) !== null ) {
    
    				// ["f 1//1 2//2 3//3", " 1//1", "1", "1", " 2//2", "2", "2", " 3//3", "3", "3", undefined, undefined, undefined]
    
    				addFace(
    					result[ 2 ], result[ 5 ], result[ 8 ], result[ 11 ],
    					undefined, undefined, undefined, undefined,
    					result[ 3 ], result[ 6 ], result[ 9 ], result[ 12 ]
    				);
    
    			} else if ( ( result = object_pattern.exec( line ) ) !== null ) {
    
    				// o object_name
    				// or
    				// g group_name
    
    				var name = result[ 1 ].trim();
    
    				if ( foundObjects === false ) {
    
    					foundObjects = true;
    					object.name = name;
    
    				} else {
    
    					addObject( name );
    
    				}
    
    			} else if ( /^usemtl /.test( line ) ) {
    
    				// material
    
    				object.material.name = line.substring( 7 ).trim();
    
    			} else if ( /^mtllib /.test( line ) ) {
    
    				// mtl file
    
    			} else if ( ( result = smoothing_pattern.exec( line ) ) !== null ) {
    
    				// smooth shading
    
    				object.material.smooth = result[ 1 ] === "1" || result[ 1 ] === "on";
    
    			} else {
    
    				throw new Error( "Unexpected line: " + line );
    
    			}
    
    		}
    
    		var container = new THREE.Group();
    
    		for ( var i = 0, l = objects.length; i < l; i ++ ) {
    
    			object = objects[ i ];
    			var geometry = object.geometry;
    
    			var buffergeometry = new THREE.BufferGeometry();
    
    			buffergeometry.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( geometry.vertices ), 3 ) );
    
    			if ( geometry.normals.length > 0 ) {
    
    				buffergeometry.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( geometry.normals ), 3 ) );
    
    			} else {
    
    				buffergeometry.computeVertexNormals();
    
    			}
    
    			if ( geometry.uvs.length > 0 ) {
    
    				buffergeometry.addAttribute( 'uv', new THREE.BufferAttribute( new Float32Array( geometry.uvs ), 2 ) );
    
    			}
    
    			var material;
    
    			if ( this.materials !== null ) {
    
    				material = this.materials.create( object.material.name );
    
    			}
    
    			if ( !material ) {
    
    				material = new THREE.MeshPhongMaterial();
    				material.name = object.material.name;
    
    			}
    
    			material.shading = object.material.smooth ? THREE.SmoothShading : THREE.FlatShading;
    
    			var mesh = new THREE.Mesh( buffergeometry, material );
    			mesh.name = object.name;
    
    			container.add( mesh );
    
    		}
    
    		console.timeEnd( 'OBJLoader' );
    
    		return container;
    
    	}
    
    };
    
    

    MTLLoader.js

    /**
     * Loads a Wavefront .mtl file specifying materials
     *
     * @author angelxuanchang
     */
    
    THREE.MTLLoader = function( manager ) {
    
    	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
    
    };
    
    THREE.MTLLoader.prototype = {
    
    	constructor: THREE.MTLLoader,
    
    	load: function ( url, onLoad, onProgress, onError ) {
    
    		var scope = this;
    
    		var loader = new THREE.XHRLoader( this.manager );
    		loader.setPath( this.path );
    		loader.load( url, function ( text ) {
    
    			onLoad( scope.parse( text ) );
    
    		}, onProgress, onError );
    
    	},
    
    	setPath: function ( value ) {
    
    		this.path = value;
    
    	},
    
    	setBaseUrl: function( value ) {
    
    		// TODO: Merge with setPath()? Or rename to setTexturePath?
    
    		this.baseUrl = value;
    
    	},
    
    	setCrossOrigin: function ( value ) {
    
    		this.crossOrigin = value;
    
    	},
    
    	setMaterialOptions: function ( value ) {
    
    		this.materialOptions = value;
    
    	},
    
    	/**
    	 * Parses loaded MTL file
    	 * @param text - Content of MTL file
    	 * @return {THREE.MTLLoader.MaterialCreator}
    	 */
    	parse: function ( text ) {
    
    		var lines = text.split( "\n" );
    		var info = {};
    		var delimiter_pattern = /\s+/;
    		var materialsInfo = {};
    
    		for ( var i = 0; i < lines.length; i ++ ) {
    
    			var line = lines[ i ];
    			line = line.trim();
    
    			if ( line.length === 0 || line.charAt( 0 ) === '#' ) {
    
    				// Blank line or comment ignore
    				continue;
    
    			}
    
    			var pos = line.indexOf( ' ' );
    
    			var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line;
    			key = key.toLowerCase();
    
    			var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : "";
    			value = value.trim();
    
    			if ( key === "newmtl" ) {
    
    				// New material
    
    				info = { name: value };
    				materialsInfo[ value ] = info;
    
    			} else if ( info ) {
    
    				if ( key === "ka" || key === "kd" || key === "ks" ) {
    
    					var ss = value.split( delimiter_pattern, 3 );
    					info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ];
    
    				} else {
    
    					info[ key ] = value;
    
    				}
    
    			}
    
    		}
    
    		var materialCreator = new THREE.MTLLoader.MaterialCreator( this.baseUrl, this.materialOptions );
    		materialCreator.setCrossOrigin( this.crossOrigin );
    		materialCreator.setManager( this.manager );
    		materialCreator.setMaterials( materialsInfo );
    		return materialCreator;
    
    	}
    
    };
    
    /**
     * Create a new THREE-MTLLoader.MaterialCreator
     * @param baseUrl - Url relative to which textures are loaded
     * @param options - Set of options on how to construct the materials
     *                  side: Which side to apply the material
     *                        THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide
     *                  wrap: What type of wrapping to apply for textures
     *                        THREE.RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping
     *                  normalizeRGB: RGBs need to be normalized to 0-1 from 0-255
     *                                Default: false, assumed to be already normalized
     *                  ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's
     *                                  Default: false
     * @constructor
     */
    
    THREE.MTLLoader.MaterialCreator = function( baseUrl, options ) {
    
    	this.baseUrl = baseUrl;
    	this.options = options;
    	this.materialsInfo = {};
    	this.materials = {};
    	this.materialsArray = [];
    	this.nameLookup = {};
    
    	this.side = ( this.options && this.options.side ) ? this.options.side : THREE.FrontSide;
    	this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : THREE.RepeatWrapping;
    
    };
    
    THREE.MTLLoader.MaterialCreator.prototype = {
    
    	constructor: THREE.MTLLoader.MaterialCreator,
    
    	setCrossOrigin: function ( value ) {
    
    		this.crossOrigin = value;
    
    	},
    
    	setManager: function ( value ) {
    
    		this.manager = value;
    
    	},
    
    	setMaterials: function( materialsInfo ) {
    
    		this.materialsInfo = this.convert( materialsInfo );
    		this.materials = {};
    		this.materialsArray = [];
    		this.nameLookup = {};
    
    	},
    
    	convert: function( materialsInfo ) {
    
    		if ( ! this.options ) return materialsInfo;
    
    		var converted = {};
    
    		for ( var mn in materialsInfo ) {
    
    			// Convert materials info into normalized form based on options
    
    			var mat = materialsInfo[ mn ];
    
    			var covmat = {};
    
    			converted[ mn ] = covmat;
    
    			for ( var prop in mat ) {
    
    				var save = true;
    				var value = mat[ prop ];
    				var lprop = prop.toLowerCase();
    
    				switch ( lprop ) {
    
    					case 'kd':
    					case 'ka':
    					case 'ks':
    
    						// Diffuse color (color under white light) using RGB values
    
    						if ( this.options && this.options.normalizeRGB ) {
    
    							value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ];
    
    						}
    
    						if ( this.options && this.options.ignoreZeroRGBs ) {
    
    							if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 1 ] === 0 ) {
    
    								// ignore
    
    								save = false;
    
    							}
    
    						}
    
    						break;
    
    					default:
    
    						break;
    				}
    
    				if ( save ) {
    
    					covmat[ lprop ] = value;
    
    				}
    
    			}
    
    		}
    
    		return converted;
    
    	},
    
    	preload: function () {
    
    		for ( var mn in this.materialsInfo ) {
    
    			this.create( mn );
    
    		}
    
    	},
    
    	getIndex: function( materialName ) {
    
    		return this.nameLookup[ materialName ];
    
    	},
    
    	getAsArray: function() {
    
    		var index = 0;
    
    		for ( var mn in this.materialsInfo ) {
    
    			this.materialsArray[ index ] = this.create( mn );
    			this.nameLookup[ mn ] = index;
    			index ++;
    
    		}
    
    		return this.materialsArray;
    
    	},
    
    	create: function ( materialName ) {
    
    		if ( this.materials[ materialName ] === undefined ) {
    
    			this.createMaterial_( materialName );
    
    		}
    
    		return this.materials[ materialName ];
    
    	},
    
    	createMaterial_: function ( materialName ) {
    
    		// Create material
    
    		var mat = this.materialsInfo[ materialName ];
    		var params = {
    
    			name: materialName,
    			side: this.side
    
    		};
    
    		for ( var prop in mat ) {
    
    			var value = mat[ prop ];
    
    			if ( value === '' ) {
    				continue;
    			}
    
    			switch ( prop.toLowerCase() ) {
    
    				// Ns is material specular exponent
    
    				case 'kd':
    
    					// Diffuse color (color under white light) using RGB values
    
    					params[ 'color' ] = new THREE.Color().fromArray( value );
    
    					break;
    
    				case 'ks':
    
    					// Specular color (color when light is reflected from shiny surface) using RGB values
    					params[ 'specular' ] = new THREE.Color().fromArray( value );
    
    					break;
    
    				case 'map_kd':
    
    					// Diffuse texture map
    
    					params[ 'map' ] = this.loadTexture( this.baseUrl + value );
    					params[ 'map' ].wrapS = this.wrap;
    					params[ 'map' ].wrapT = this.wrap;
    
    					break;
    
    				case 'ns':
    
    					// The specular exponent (defines the focus of the specular highlight)
    					// A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.
    
    					params[ 'shininess' ] = parseFloat( value );
    
    					break;
    
    				case 'd':
    
    					if ( value < 1 ) {
    
    						params[ 'opacity' ] = value;
    						params[ 'transparent' ] = true;
    
    					}
    
    					break;
    
    				case 'Tr':
    
    					if ( value > 0 ) {
    
    						params[ 'opacity' ] = 1 - value;
    						params[ 'transparent' ] = true;
    
    					}
    
    					break;
    
    				case 'map_bump':
    				case 'bump':
    
    					// Bump texture map
    
    					if ( params[ 'bumpMap' ] ) break; // Avoid loading twice.
    
    					params[ 'bumpMap' ] = this.loadTexture( this.baseUrl + value );
    					params[ 'bumpMap' ].wrapS = this.wrap;
    					params[ 'bumpMap' ].wrapT = this.wrap;
    
    					break;
    
    				default:
    					break;
    
    			}
    
    		}
    
    		this.materials[ materialName ] = new THREE.MeshPhongMaterial( params );
    		return this.materials[ materialName ];
    
    	},
    
    
    	loadTexture: function ( url, mapping, onLoad, onProgress, onError ) {
    
    		var texture;
    		var loader = THREE.Loader.Handlers.get( url );
    		var manager = ( this.manager !== undefined ) ? this.manager : THREE.DefaultLoadingManager;
    
    		if ( loader === null ) {
    
    			loader = new THREE.TextureLoader( manager );
    
    		}
    
    		if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin );
    		texture = loader.load( url, onLoad, onProgress, onError );
    
    		if ( mapping !== undefined ) texture.mapping = mapping;
    
    		return texture;
    
    	}
    
    };
    
    THREE.EventDispatcher.prototype.apply( THREE.MTLLoader.prototype );
    
    


  • Hi @IPO_DEV
    I am an idiot... as you already suspected...

    I indeed copied the wrong versions of the files (from the latest three.js version at https://github.com/mrdoob/three.js/archive/master.zip) and not those from https://github.com/tronlec/three.js...

    Your example then works beautifully! I just needed to add

    mesh = object
    

    before the line

    scene.add(object)
    

    for the quickitemtexture example to work completely, since function paintGL(canvas) expects the object to be referenced by the variable mesh.

    function paintGL(canvas) {
        mesh.rotation.x = degToRad(canvas.xRotAnim);
        mesh.rotation.y = degToRad(canvas.yRotAnim);
        mesh.rotation.z = degToRad(canvas.zRotAnim);
        mesh.position.x = (canvas.yRotAnim - 120.0) / 120.0;
        mesh.position.y = (canvas.xRotAnim -  60.0) / 50.0;
        mesh.position.z = -7.0;
        renderer.render( scene, camera );
    }
    

    Thanks again!



  • @Diracsbracket ok thanks for your feedback, glad that it works for you, so have fun :-)
    p.s. you might want to add light sources to the scene in order for the model to appear not completely black



  • @IPO_DEV said in Using three.js in my Qt QML Program:

    you might want to add light sources to the scene in order for the model to appear not completely black

    Thanks, I wondered why the texture looked black like that^^. Now I know.



  • @IPO_DEV Hi IPO_DEV , I wanna use three.js the newest version r99. but I copy the qt example to r99 ,can not find the THREE type ? only use the r74 version can run it successful . how can I do to run this qt canvas 3d demo in three.js r99


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.