I want to obtain vertixes for any given text. Text is created via TextGeometry and then PointCloud is instantiated:
var textGeo = new THREE.TextGeometry( "three.js", {...});
var textMaterial = new THREE.MeshBasicMaterial({
color:0x8080FF,
side:THREE.DoubleSide,
});
textObject = new THREE.PointCloud( textGeo, textMaterial)
The effect is following:
As you can see, the issue is that, points are not uniformely distributed, especially they are missing on straight lines.
Do you guys have any suggestions how to achieve a nicer effect?
I met the same problem. And I change the .JSON in THREE.FontLoader.load(),then I can see most of the points.
fontLoader.load('build/optimer_bold.typeface.json',
function (font) {
let fontOptions = {
font:font,
size:10
......
}
.....
}
);
Try the optimer_bold.typeface.json.
Related
I'm trying to assign a new material to an object, but when I assign a new (color) map, the object renders as white, and the AO and shadows no longer show up. It's as if the emissive attribute is 100%. I can change the color attribute (e.g. 'red' or 'blue'), ao, normal, etc. without issues. The glb loaded in already has a working material with a color map and ao, but I want to be able to replace it.
I'm using 8th Wall with A-Frame, but I've registered the following as a custom Three.js component.
const customMat = {
schema: {}, // will pass textures via aframe later
init() {
this.el.addEventListener('model-loaded', (e) => {
const material = new THREE.MeshStandardMaterial()
const texLoader = new THREE.TextureLoader()
texLoader.crossOrigin = ''
const mapColor = texLoader.load('assets/cover_color.jpg')
const mapAO = texLoader.load('assets/cover_ao.jpg')
material.map = mapColor // makes everything 100% white likes it's emissive
// material.color = new THREE.Color('red') // works fine no problem
material.aoMap = mapAO
material.aoMapIntensity = 1
e.detail.model.traverse((mesh) => {
if (mesh.isMesh) {
mesh.material = material
mesh.material.needsUpdate = true // not sure if needed
}
})
})
},
}
export {customMat}
Any suggestions would be much appreciated. I've tried this with primitive geometry too, but the same issue occurs. I don't seem to be able to modify the existing material's attributes either, so maybe my approach is fundamentally wrong.
I'm working on some screen space shaders using THREE.JS and GLSL. I'd like to both render a "diffuse" buffer with per object materials/textures AND render an "ID" buffer where each object has a unique color for object edge detection. This would also be really useful for object picking as some of the THREE.JS examples show.
I am already using Scene.overrideMaterial to render normal buffers (and some other cool stuff) but haven't figured out a way to do something similar for an ID buffer. Is there something like this that exists? Seems useful enough that it would be likely. Have other people developed solutions to this problem? Maybe by mapping an objects UUID to a color value?
-----> EDIT
Here is my attempt using this example:
https://threejs.org/examples/webgl_interactive_instances_gpu.html
I'm not concerned with selection at this point, regardless this isn't working. I think I may be setting up onBeforeRender() incorrectly. Any help on this?
Thanks!
initPieces = function(geometry){
...
//set id Color to unique color
//for picking will use setHex(i) method
m.userData.idColor = material.color;
...
m.onBeforeRender = function (){
if(Viewer._scene.overrideMaterial){
if(Viewer._scene.overrideMaterial._name == "id"){
var updateList = [];
var u = scene.overrideMaterial.uniforms;
//picking color in user data
var d = this.userData;
//Is this just equivalent to checking whether this is the picking material?
if(u.idColor){
u.idColor.value = (d.idColor);
// u.needsUpdate = true;
updateList.push("idColor");
}
//Don't understand what this is doing
//Throws "WebGL INVALID_OPERATION: uniformMatrix4fv: location is not from current program"
if (updateList.length){
var materialProperties = renderer.properties.get(material);
if( materialProperties.program){
var gl = renderer.getContext();
var p = materialProperties.program;
gl.useProgram( p.program );
var pu = p.getUniforms();
updateList.forEach(function(name){
pu.setValue( gl, name, u[name].value);
});
}
}
}
}
}
// Doesn't show onBeforeRender set as I expected?
console.log(m);
...
}
...
}
...
function render(scene, camera){
...
scene.overrideMaterial = getMaterial("id");
renderer.render(scene, camera, getTarget("id"));
scene.overrideMaterial = null;
...
}
I'm trying to use line like this
myObject3D.children.forEach(
function(pChild){
return pChild.position.multiplyScalar(myMultiplier)
}
);
and this
myObject3D.children.forEach(
function(pChild){
pChild.position.copy(myVector3)
}
);
But for some reasons, functions in child elements of 'myObject3D' seems to be inexistent. ("Uncaught TypeError: pChild.position.multiplyScalar is not a function")
However, elements in 'myObject3D' are 'Mesh' objects.
Can anybody suggest what can I do?
Thanks
First, your forEach callback shouldn't return anything.
There doesn't appear to be anything wrong with your second code segment.
The code below runs without errors.
var group = new THREE.Object3D();
var geo = new THREE.BoxBufferGeometry(10, 10, 10);
var mat = new THREE.MeshBasicMaterial({
color: "red"
});
var mesh = new THREE.Mesh(geo, mat);
group.add(mesh);
group.add(mesh.clone());
group.add(mesh.clone());
group.add(mesh.clone());
group.add(mesh.clone());
var myVector3 = new THREE.Vector3();
group.children.forEach(function(pChild) {
pChild.position.multiplyScalar(5);
pChild.position.copy(myVector3)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.js"></script>
Please verify that you're populating your group with the correct kinds of objects. Also, you can always test if a function is available before using it:
if(obj.someFunction){
obj.someFunction();
}
Having problem understanding the class system in Three.js
I have a code in player.js :
function Player() {
var mesh = new THREE.Object3D();
this.player = null;
this.loader = new THREE.JSONLoader();
this.name = 'player';
this.loader.load(
'obj/models/minecraft_sole.json',
function ( geometry, materials ) {
var material = new THREE.MultiMaterial( materials );
this.player = new THREE.Mesh( geometry, material );
this.player.position.set(0, 0, 0);
this.player.scale.set(.5,.5,.5);
this.player.castShadow = true;
this.player.receiveShadow = false;
mesh.add( this.player );
}
);
Player.prototype.constructor = Player;
Player.prototype = Object.create(THREE.Object3D.prototype);
}
Player.prototype.updatePosition = function(){
this.mesh.position.y += 0.05;
}
And basically what I'm trying to achieve:
In main.js after all standard setup for init()/render()/animate() and all...
I create variable called johny:
var johny = new Player();
Now everything loads great and all, but in player.js i want to be able to define some prototype ? method, and in that method I want to listen for a click event. After that event is called I want my player mesh to animate to certain position or start rotating/scaling.
My pseudo code for better understanding is:
var Player = function(){
// define mesh and all
}
player.add.eventListener( 'click' ){
//code to animate player
}
Remember that all this; I want to be a part of player.js so that after calling:
var johny = new Player();
I don't have to add event listening functions to the main.js and all that.
And second of all I want my code to be modular, as You may already noticed :)
So I did managed to understand it.
So, I already have the circle in my screen and showed it up, but I wanted to change the graphic from the "default circle", which is created by using the code like so:
circle.graphic.BeginFill();
circle.graphic.DrawCircle(10,10,10);
circle.graphic.EndFill();
addChild(circle);
I wanted to change that to my desired image like so:
How do I do that?
Use BitmapData and beginBitmapFill with circle like so:
var myBitmap:BitmapData;
var imgLoader:Loader = new Loader();
imgLoader.load(new URLRequest("myImage.png"));
imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, drawImage);
function drawImage(e:Event):void
{
myBitmap = new BitmapData(imgLoader.width, imgLoader.height, false);
myBitmap.draw(imgLoader);
var circle:Sprite = new Sprite();
circle.graphics.beginBitmapFill(myBitmap, null, true);
circle.graphics.drawCircle(50,50,100);
circle.graphics.endFill();
addChild(circle);
}
For more info see beginBitmapFill()