Last active
April 27, 2024 02:58
-
-
Save andreasplesch/1ee775f917593af42d0bb42a2c7f01ff to your computer and use it in GitHub Desktop.
InstancedShapeProto test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<X3D ondownloadsfinished='init()'> | |
<!--head> | |
<meta content='Prototype_DiffuseApp.x3d' name='title'/> | |
<meta content='X3D encodings example: defining a Prototype, demonstration of IS/connect definitions.' name='description'/> | |
<meta content='Andreas Plesch' name='creator'/> | |
<meta content='21 July 2020' name='created'/> | |
<meta content='BSD' name='license'/> | |
</head--> | |
<Scene> | |
<ProtoDeclare name="InstancedShape"> | |
<ProtoInterface> | |
<field accessType="initializeOnly" type="MFNode" name="shapes" value="NULL" /> | |
<field accessType="inputOutput" type="MFVec3f" name="translations" value="" /> | |
<field accessType="inputOutput" type="MFVec3f" name="scales" value="" /> | |
<field accessType="inputOutput" type="MFRotation" name="rotations" value="" /> | |
</ProtoInterface> | |
<ProtoBody> | |
<Group> | |
<IS> | |
<connect nodeField="children" protoField="shapes" /> | |
</IS> | |
</Group> | |
</ProtoBody> | |
</ProtoDeclare> | |
<ExternProtoDeclare name="Teapot" url='"https://raw.githubusercontent.com/x3dom/x3dom/master/test/functional/protos/castle/teapot_fallback_implementation.x3d#Teapot"'> | |
<field accessType="inputOutput" type="SFNode" name="metadata" /> | |
<field accessType="initializeOnly" type="SFVec3f" name="size" /> | |
<field accessType="initializeOnly" type="SFBool" name="solid" /> | |
<field accessType="initializeOnly" type="SFBool" name="manifold" /> | |
<field accessType="inputOutput" type="SFNode" name="texCoord" /> | |
</ExternProtoDeclare> | |
<InstancedShape | |
translations='1 0 0, 0 1 0'> | |
<Shape> | |
<Appearance> | |
<Material diffuseColor='0.34 0 0.26' specularColor='1 1 1' shininess='1.6' /> | |
</Appearance> | |
<Teapot /> | |
</Shape> | |
</InstancedShape> | |
<!-- script for gpu instances --> | |
<script type="text/javascript"> | |
var makeInstances = function() { | |
var instanceGroup = document.querySelector('InstancedShape')._x3domNode; | |
var shape = instanceGroup._cf.shapes.nodes[0]; | |
var translations = instanceGroup._vf.translations; | |
var scales = instanceGroup._vf.scales; | |
var rotations = instanceGroup._vf.rotations; | |
var trafos = translations.map(function(t, i) { | |
return x3dom.fields.SFMatrix4f.fromRotationTranslationScale(rotations[i], translations[i], scales[i]); | |
}); | |
//positions | |
var instances = translations.length; | |
var positions = shape._webgl.positions[0]; | |
var posVec3f = x3dom.fields.MFVec3f.parse(positions.join()); | |
var transformedPositions = trafos.map(function(trafo) { | |
return new x3dom.fields.MFVec3f(posVec3f.map(function(v, i) { | |
return trafo.multMatrixPnt(v); | |
})).toGL() | |
}); | |
//var positions2 = positions.map( function (v) { return v + 1; } ); | |
//shape._webgl.positions[0] = [].concat(...translatedPositions); | |
//shape._webgl.positions[0] = flatten(translatedPositions); | |
shape._webgl.positions[0] = flatten(transformedPositions); | |
//indices | |
var indices = shape._webgl.indexes[0]; | |
var indices2 = translations.map(function(t, i) { | |
return indices.map(function(v) { | |
return v + i * positions.length / 3; | |
}) | |
}); | |
//shape._webgl.indexes[0] = [].concat(...indices2); | |
//shape._webgl.indexes[0] = flatten(indices2); | |
let ind32 = new Uint32Array( indices.length * instances ); | |
indices2.forEach( function (ind, i) { | |
ind32.set(ind, i * indices.length ); | |
}); | |
shape._webgl.indexes[0] = ind32; | |
//normals | |
//use transpose of inverse | |
var normals = shape._webgl.normals[0]; | |
var normalsVec3f = x3dom.fields.MFVec3f.parse(normals.join()); | |
//var zeroVec3f = new x3dom.fields.SFVec3f(); | |
var xNormals = trafos.map(function(trafo) { | |
//trafo.setTranslate( zeroVec3f ); | |
var normalTrafo = trafo.inverse().transpose(); | |
return new x3dom.fields.MFVec3f(normalsVec3f.map(function(n) { | |
return normalTrafo.multMatrixVec(n); | |
})).toGL() | |
}); | |
//shape._webgl.normals[0] = [].concat(...normals2); | |
shape._webgl.normals[0] = flatten(xNormals); | |
//texcoords | |
var texcoords = shape._webgl.texcoords[0]; | |
let tex32 = new Uint32Array( texcoords.length * instances ); | |
//var texcoords2 = translations.map(function(v, i) { | |
// return texcoords; | |
//}); | |
//shape._webgl.texcoords[0] = [].concat(...texcoords2); | |
//shape._webgl.texcoords[0] = flatten(texcoords2); | |
translations.forEach( function (v, i) { | |
tex32.set(texcoords, i * texcoords.length ); | |
}); | |
shape._webgl.texcoords[0] = tex32; | |
shape.setAllDirty(); | |
shape.invalidateVolume(); | |
shape._cf.geometry.node.invalidateVolume(); | |
//debugger; | |
function flatten(a) { | |
var out = []; | |
a.forEach(function(s) { | |
out.push(...s) | |
}); | |
return out; | |
} | |
}; | |
var init = function() { | |
makeInstances(); | |
fitscene(); | |
// defined in Viewer | |
}; | |
//generate translations | |
var num_instances = 5000 | |
, size = 3; | |
var dim = size * Math.sqrt(num_instances); | |
var instanceGroup = document.querySelector('InstancedShape'); | |
var translations = new Array(num_instances).fill(0).map(function(v) { | |
return [(Math.random() * dim).toFixed(5), 0, (Math.random() * dim).toFixed(5)].join() | |
}); | |
//instanceGroup.setFieldValue('translations', x3dom.fields.MFVec3f.parse(translations.join())); | |
instanceGroup.setAttribute('translations', translations.join()); | |
var scales = translations.map(function(v) { | |
return "1 " + (0.5 + Math.random()).toFixed(3) + " 1" | |
}); | |
//instanceGroup.setFieldValue('scales', x3dom.fields.MFVec3f.parse(scales.join())); | |
instanceGroup.setAttribute('scales', scales.join()); | |
var rotations = translations.map(function(v) { | |
return "0 1 0 " + (Math.random() * 6.283).toFixed(5) | |
}); | |
//instanceGroup.setFieldValue('rotations', x3dom.fields.MFRotation.parse(rotations.join())); | |
instanceGroup.setAttribute('rotations', rotations.join()); | |
//makeInstances(); | |
</script> | |
</Scene> | |
</X3D> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment