creating a boundary around a three-dimensional shape using Three.js

I have a number of objects in my scene affecting the outcome of the .mesh in Three.js, but I am unsure how to separate them properly.

To clearly delineate the shapes, I aim to create a boundary. Check out the link for reference:

extrude_geometry[i] = new THREE.ExtrudeGeometry(shape_form[i], extrusion_data);
front_material[i] = new THREE.MeshBasicMaterial({ color: "#FF0000" });

municipalities[i] = new THREE.Mesh(extrude_geometry[i], front_material[i]);

Answer №1

To successfully implement the outlined pass feature, both Composer and Outline Pass are essential components. Below is a simplified version of the official example that can be found at

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Implementing three.js webgl - post processing with Outline Pass</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
</head>
<body>
<script src="three.js"></script>

<script src="CopyShader.js"></script>
<script src="FXAAShader.js"></script>
<script src="EffectComposer.js"></script>
<script src="RenderPass.js"></script>
<script src="ShaderPass.js"></script>
<script src="OutlinePass.js"></script>


<div id="info">
    <a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - Detailed information on Outline Pass by <a href="http://eduperiment.com" target="_blank" rel="noopener">Prashant Sharma</a> and <a href="https://clara.io" target="_blank" rel="noopener">Ben Houston</a><br/><br/>
</div>

<script>

    var container, camera, scene, renderer, composer, effectFXAA, outlinePass;

    var raycaster = new THREE.Raycaster();
    var mouse = new THREE.Vector2();

    initSetup();
    initiateAnimation();

    function initSetup() {
        container = document.createElement('div');
        document.body.appendChild(container);

        var width = window.innerWidth || 1;
        var height = window.innerHeight || 1;

        renderer = new THREE.WebGLRenderer({antialias: false});
        renderer.setSize(width, height);
        document.body.appendChild(renderer.domElement);

        camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 100);
        camera.position.z = 8;
        camera.position.x = 0;

        scene = new THREE.Scene();


        var light = new THREE.DirectionalLight(0xddffdd, 0.4);
        light.position.z = 1;
        light.position.y = 1;
        light.position.x = 1;
        scene.add(light);

        var floorMaterial = new THREE.MeshLambertMaterial();
        floorMaterial.side = THREE.DoubleSide;
        var floorGeometry = new THREE.PlaneBufferGeometry(12, 12);
        var floorMesh = new THREE.Mesh(floorGeometry, floorMaterial);
        floorMesh.rotation.x -= Math.PI * 0.5;
        floorMesh.position.y -= 1.5;
        scene.add(floorMesh);




        // Setting up post processing
        composer = new THREE.EffectComposer(renderer);

        var renderPass = new THREE.RenderPass(scene, camera);
        composer.addPass(renderPass);

        outlinePass = new THREE.OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera);
        composer.addPass(outlinePass);

        effectFXAA = new THREE.ShaderPass(THREE.FXAAShader);
        effectFXAA.uniforms['resolution'].value.set(1 / window.innerWidth, 1 / window.innerHeight);
        effectFXAA.renderToScreen = true;
        composer.addPass(effectFXAA);

        window.addEventListener('mousemove', handleMouseMove);
        window.addEventListener('touchmove', handleMouseMove);

        function handleMouseMove(event) {
            mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
            mouse.y = -( event.clientY / window.innerHeight ) * 2 + 1;

            raycaster.setFromCamera(mouse, camera);

            var intersections = raycaster.intersectObjects([scene], true);

            if (intersections.length > 0) {
                var selectedObject = intersections[0].object;
                outlinePass.selectedObjects = [selectedObject];
            }
        }
    }

    function initiateAnimation() {
        requestAnimationFrame(initiateAnimation);
        composer.render();
    }

</script>
</body>
</html>

Answer №2

If you're looking for a solution, I recommend trying out EdgesGeometry. It worked perfectly in my situation. Just add this code snippet after inserting the mesh:

const geometry = new THREE.PlaneBufferGeometry(200, 200) // use any geometry you prefer
const line = new THREE.LineSegments(new THREE.EdgesGeometry(geometry), new THREE.LineBasicMaterial({color: 0x00000}))
scene.add(line)

Check out more about EdgesGeometry here!

Answer №3

Check out the convenient WireframeHelper and edgesHelper features available in THREE.js - they provide exactly what you're looking for.

Answer №4

If you're looking to display the bounding box of an object in Three.js, you can use the THREE.BoundingBoxHelper(). This function will visually show the bounding box around the specified object. Here's an example:

# Define a hexadecimal value for color
var hex  = 0xff0000;
var bbox = new THREE.BoundingBoxHelper( your_mesh, hex );
bbox.update();
scene.add( bbox );

In order to render only the outline of a mesh, you can render the mesh twice with a flat color while utilizing frontface culling and a custom shader that offsets each vertex along its normal. Here's a snippet of what this might look like:

var vertexShader = 
"void main(){"+
    "float offset = 2.0;"+
    "vec4 pos = modelViewMatrix * vec4( position + normal * offset, 1.0 );"+
    "gl_Position = projectionMatrix * pos;"+
"}\n";

var fragmentShader =
"void main(){"+
    "gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );"+
"}\n";

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to transfer a querystring received in Node.js to a page being shown through res.render?

I have a nodejs file where I am rendering a page named foo.html. Within foo.html, I am using ajax to retrieve variables from a querystring and load an appropriate xml document based on those variables. The issue arises when I run my nodejs server, which is ...

Tips for removing a row from a table in Angular4, where there is a delete button located in every row

Component <tr *ngFor="let item of items; let i = index"> <th>{{ i + 1 }}</th> <th>{{ item.id }}</th> <td>{{ item.title }}</td> <th><button (click)="deleteItem()">Edit</button>< ...

When using AJAX POST requests, HTML links may become unresponsive

Scenario: Currently, I am developing a small-scale web application. The AJAX functionality is successfully sending data to create.php which then executes the necessary MySQL query. Upon completion of the AJAX request, a success message is appended to the d ...

The Google Maps listener event behaves as if it were clicked even though it is triggered by a mouseover

Two google.maps.event.addListener events are being added here google.maps.event.addListener(markerAcademicCenter, "mouseover", function (e) { markerIconAcademicCenter.url = 'MapIcons/Circle32.png' }); google.maps.event.addListener(markerAcade ...

Data vanished from the input field values

Having an issue with displaying an HTML table inside a .cshtml file. When I hardcode values, the table appears as expected. However, when I attempt to populate it using a foreach loop, the table disappears. <script> var nTable = ""; $(docu ...

Tips for swapping out textures imported from Collada with ShaderMaterial textures in Three.js

Is it possible to update the textures of a basic 3D model loaded using the Collada loader in the Three.js library? My goal is to incorporate color, specular, and normal maps onto the model using ShaderMaterial by referencing new files with the model' ...

Encountered an issue with npm install showing error message 'Failed: connection closed unexpectedly.'

Encountered an issue while running the command npm install module-name --save. The installation fails regardless of the module I try to install. Even specifying it in the package.json and then running npm install for the entire project results in failure ...

Automatically switch to dark mode at specified times: A simple guide

Here is the current method for toggling themes: let themeToggler = document.getElementById('theme-toggler'); themeToggler.onclick = () => { themeToggler.classList.toggle('fa-sun'); if (themeToggler.classList.contains('f ...

Executing NestJS code after applying a pipe but before reaching the method handler

Is it possible to insert additional code after all the pipes have transformed but before the method handler is called? https://i.sstatic.net/IjQvv.png ...

Mandatory press for a function known as a click

After dealing with a previous question on this matter, I have encountered yet another issue. My goal is to rotate an element clockwise by 22 degrees and then back to its initial state of 0 degrees on click. The first function executes correctly, but the ...

Using Django ajax doesn't function properly when it's in a separate file

My Django site utilizes AJAX to handle requests. Initially, I had the JavaScript code embedded within the HTML document using <script>...</script>, which worked perfectly fine. However, when I decided to move the JavaScript to a separate file, ...

"Efficiently transferring a large file using AJAX and sending it via POST to a

I am facing a challenge with a small script that I am developing. The script is designed to download relatively large files (around 15Mb each) from one domain using AJAX, and then upload/post them to another domain also through AJAX. Downloading the files ...

Simulate a keyboard key being pressed and held for 5 seconds upon loading the page

Is it possible to create a script that automatically triggers an event to press and hold down the Space key for 5 seconds upon page load, without any user interaction? After the 5 seconds, the key should be released. It is important to emphasize that abso ...

Using THREEJS to implement IfcAxis2Placement3D and IfcObjectPlacement

I am currently developing a web-based viewer for IFC files using WebGL. While most IfcRepresentation objects are straightforward, I am struggling with coordination transformation. Is there a more effective way to translate and rotate an Object3D in THREEJS ...

What approach does JavaScript take when encountering a value that is undefined?

Having recently delved into JavaScript and exploring a book, I came across an interesting example in the recursive chapter: function findSolution(target) { function find(current, history) { if (current == target) return history; else if (c ...

Navigating through a JSON dictionary in Svelte: A step-by-step guide

When working with Svelte, the #each construct allows for easy iteration over array-like objects. But what if you have a JSON dictionary object instead? Is there a way in Svelte to iterate over this type of object in order to populate a dropdown menu? The ...

Running AngularJS on a personal server

I recently embarked on creating a basic web application using AngularJS. You can find the files for this project here. To get it up and running, I installed node.js and ran the command "npm install -g http-server" on Windows 10 command prompt. After naviga ...

The elements in my code are not displaying as expected

This is my jQuery script: $("#options").popup(null, Settings.DialogOptions) .on("onOk", function(){ Settings.SaveSettings( ); Settings.CloseSettings( ); switch(Settings.GetSetting("displayId")){ case "true": $("#nextId").s ...

Is there a way for me to locate a forum using a JWT Token?

I am searching for a way to retrieve forums using JWT Token. If a user has created 3 forums, I want to display them in a list. My Request is structured like this : ### http://localhost:8080/forum/getByOwnerID Authorization: Bearer {{adminToken}} Alternat ...

Take two inputs, divide them, and then multiply the result by 100

I am currently troubleshooting the total project match function, as it is not working properly. I aim to have this function divide the first function by the second function and then multiply the result by 100. Here is a snippet of my code: matchContribu ...