-
Notifications
You must be signed in to change notification settings - Fork 107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle materials referenced by name specified outside the link object #72
Changes from 3 commits
b5c129a
d8cac12
f2e22b8
ad12889
39f2750
6c73100
38f2c75
b53fb19
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -132,11 +132,8 @@ class URDFLoader { | |
if (/\.stl$/i.test(path)) { | ||
|
||
this.STLLoader.load(path, geom => { | ||
|
||
const mesh = new THREE.Mesh(); | ||
mesh.geometry = geom; | ||
const mesh = new THREE.Mesh(geom, new THREE.MeshPhongMaterial()); | ||
done(mesh); | ||
|
||
}); | ||
|
||
} else if (/\.dae$/i.test(path)) { | ||
|
@@ -210,6 +207,7 @@ class URDFLoader { | |
// Process the <robot> node | ||
_processRobot(robot, packages, path, loadMeshCb) { | ||
|
||
const materials = robot.querySelectorAll('material'); | ||
const links = []; | ||
const joints = []; | ||
const obj = new THREE.Object3D(); | ||
|
@@ -221,15 +219,30 @@ class URDFLoader { | |
const type = n.nodeName.toLowerCase(); | ||
if (type === 'link') links.push(n); | ||
else if (type === 'joint') joints.push(n); | ||
}); | ||
|
||
// Create the <material> map | ||
const materialMap = {}; | ||
this.forEach(materials, m => { | ||
const name = m.getAttribute('name'); | ||
this.forEach(m.children, c => { | ||
const material = new THREE.MeshPhongMaterial(); | ||
materialMap[name] = materialMap[name] || this._processMaterial( | ||
material, | ||
c.nodeName.toLowerCase(), | ||
c.getAttribute('rgba') || c.getAttribute('filename').replace(/^(package:\/\/)/, ''), | ||
packages, | ||
path | ||
); | ||
}); | ||
}); | ||
|
||
// Create the <link> map | ||
const linkMap = {}; | ||
this.forEach(links, l => { | ||
|
||
const name = l.getAttribute('name'); | ||
linkMap[name] = this._processLink(l, packages, path, loadMeshCb); | ||
linkMap[name] = this._processLink(l, materialMap, packages, path, loadMeshCb); | ||
|
||
}); | ||
|
||
|
@@ -403,23 +416,41 @@ class URDFLoader { | |
} | ||
|
||
// Process the <link> nodes | ||
_processLink(link, packages, path, loadMeshCb) { | ||
_processLink(link, materialMap, packages, path, loadMeshCb) { | ||
|
||
const visualNodes = this.filter(link.children, n => n.nodeName.toLowerCase() === 'visual'); | ||
const obj = new THREE.Object3D(); | ||
obj.name = link.getAttribute('name'); | ||
obj.isURDFLink = true; | ||
obj.type = 'URDFLink'; | ||
|
||
this.forEach(visualNodes, vn => this._processVisualNode(vn, obj, packages, path, loadMeshCb)); | ||
this.forEach(visualNodes, vn => this._processVisualNode(vn, obj, materialMap, packages, path, loadMeshCb)); | ||
|
||
return obj; | ||
|
||
} | ||
|
||
// Process the visual nodes into meshes | ||
_processVisualNode(vn, linkObj, packages, path, loadMeshCb) { | ||
_processMaterial(material, type, value, packages, path) { | ||
if (type === 'color') { | ||
const rgba = value.split(/\s/g) | ||
.map(v => parseFloat(v)); | ||
|
||
material.color.r = rgba[0]; | ||
material.color.g = rgba[1]; | ||
material.color.b = rgba[2]; | ||
material.opacity = rgba[3]; | ||
|
||
if (material.opacity < 1) material.transparent = true; | ||
} else if (type === 'texture') { | ||
const filename = value.replace(/^(package:\/\/)/, ''); | ||
const filePath = this._resolvePackagePath(packages, filename, path); | ||
material.map = this.TextureLoader.load(filePath); | ||
} | ||
return material; | ||
} | ||
|
||
// Process the visual nodes into meshes | ||
_processVisualNode(vn, linkObj, materialMap, packages, path, loadMeshCb) { | ||
let xyz = [0, 0, 0]; | ||
let rpy = [0, 0, 0]; | ||
let scale = [1, 1, 1]; | ||
|
@@ -515,35 +546,27 @@ class URDFLoader { | |
rpy = this._processTuple(n.getAttribute('rpy')); | ||
|
||
} else if (type === 'material') { | ||
const materialName = n.getAttribute('name'); | ||
if (n.children.length) { | ||
this.forEach(n.children, c => { | ||
switch (c.nodeName.toLowerCase()) { | ||
|
||
case 'color': | ||
this._processMaterial(material, 'color', c.getAttribute('rgba')); | ||
break; | ||
case 'texture': | ||
if (materialName in materialMap) { | ||
material.copy(materialMap[materialName]); | ||
} else { | ||
this._processMaterial(material, 'texture', c.getAttribute('filename'), packages, path); | ||
} | ||
|
||
this.forEach(n.children, c => { | ||
|
||
if (c.nodeName.toLowerCase() === 'color') { | ||
|
||
const rgba = c.getAttribute('rgba') | ||
.split(/\s/g) | ||
.map(v => parseFloat(v)); | ||
|
||
material.color.r = rgba[0]; | ||
material.color.g = rgba[1]; | ||
material.color.b = rgba[2]; | ||
material.opacity = rgba[3]; | ||
|
||
if (material.opacity < 1) material.transparent = true; | ||
|
||
} else if (c.nodeName.toLowerCase() === 'texture') { | ||
|
||
const filename = c.getAttribute('filename').replace(/^(package:\/\/)/, ''); | ||
const filePath = this._resolvePackagePath(packages, filename, path); | ||
|
||
material.map = this._textureloader.load(filePath); | ||
|
||
} | ||
|
||
}); | ||
|
||
} | ||
}); | ||
} else { | ||
material.copy(materialMap[materialName]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using How do you feel about copying just those specific values: const sharedMatData = materialMap[materialName];
if (sharedMatData.color) material.color.copy(sharedMatData.color);
if (sharedMatData.map) material.map = sharedMatData.map; And then the material map could store just those preprocessed values in an object. The color and texture node parsing could be pulled out into separate functions that return the texture and color objects. |
||
} | ||
} | ||
|
||
}); | ||
|
||
// apply the position and rotation to the primitive geometry after | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using
||
like this means that once the first object is created the returnthis._processMaterial
function will never get called and the parameters defined by the second node will never get used. I'd suggest passing an object in to the_processMaterial
function. Maybe something like:That way
_processMaterial
can modify the existing object and add any fields it needs to.