Moving points from a .obj model that was brought in

Being new to three.js, I've been stuck on a rookie mistake for hours. After finding some useful examples of mesh editing and managing an imported model on the forum (link), I tried adapting my code based on this example but now I'm facing a problem.

The issue arises when trying to drag the vertices of the model; clicking on them results in an error:

<a class='gotoLine' href='#140:42'>140:42</a> Uncaught ReferenceError: points is not defined""

I can't seem to access the var points outside of the function object without encountering a black screen.

My next hurdle would be exporting this to GLTF format and possibly to a 3D printer.

EDIT: I've managed to change the vertices, but the model doesn't transform correctly with the mesh. Testing revealed many overlapping vertices despite having:

geometry.mergeVertices(); geometry.computeFaceNormals(); geometry.computeVertexNormals();

enabled.


Here's my current code: https://jsfiddle.net/felipefsalazar/j9c1L6yr/6/

//SCREEN SETUP
var points, geometry;
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 5, 10);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x404040);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

//MOUSE CONTROLS
var controls = new THREE.OrbitControls(camera, renderer.domElement);

//LIGHTING
var light = new THREE.DirectionalLight(0xffffff, 0.5);
light.position.setScalar(100);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.5));

//GRAY GRID ON SCREEN
scene.add(new THREE.GridHelper(100, 100));

//LOAD OBJECT
var objLoader = new THREE.OBJLoader();

objLoader.load('https://raw.githubusercontent.com/felipefsalazar/venus/master/venuspeq.obj',

  function(object) {

    child = object.children[0];
    geometry = new THREE.Geometry().fromBufferGeometry(child.geometry);
    geometry.computeFaceNormals();
    geometry.mergeVertices(geometry);
    geometry.computeVertexNormals();
    geometry = new THREE.BufferGeometry().fromGeometry(geometry);

    scene.add(object);

    //STATUE MESH
    var plane = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({
      wireframe: true,
      color: "blue"
    }));
    scene.add(plane);

    //DRAGGABLE POINTS ON STATUE
    points = new THREE.Points(geometry, new THREE.PointsMaterial({
      size: 0.25,
      color: "yellow"
    }));
    scene.add(points);

    //STATUE MESH (wireframe)
    venuspeq = new THREE.Mesh(geometry, mesh);

  });


var raycaster = new THREE.Raycaster();
raycaster.params.Points.threshold = 0.25;
var mouse = new THREE.Vector2();
var intersects = null;
var plane = new THREE.Plane();
var planeNormal = new THREE.Vector3();
var currentIndex = null;
var planePoint = new THREE.Vector3();
var dragging = false;

window.addEventListener("mousedown", mouseDown, false);
window.addEventListener("mousemove", mouseMove, false);
window.addEventListener("mouseup", mouseUp, false);


function mouseDown(event) {
  setRaycaster(event);
  getIndex();
  dragging = true;
    if (currentIndex != null){
        controls.enabled = false;
        }
}

function mouseMove(event) {
  if (dragging && currentIndex !== null) {
    setRaycaster(event);
    raycaster.ray.intersectPlane(plane, planePoint);
    geometry.attributes.position.setXYZ(currentIndex, planePoint.x, planePoint.y, planePoint.z);
    geometry.attributes.position.needsUpdate = true;
  }
}

function mouseUp(event) {
  dragging = false;
  currentIndex = null;
    controls.enabled = true;
}

function getIndex() {
  intersects = raycaster.intersectObject(points);
  if (intersects.length === 0) {
    currentIndex = null;
    return;
  }
  currentIndex = intersects[0].index;
  setPlane(intersects[0].point);
}

function setPlane(point) {
  planeNormal.subVectors(camera.position, point).normalize();
  plane.setFromNormalAndCoplanarPoint(planeNormal, point);
}

function setRaycaster(event) {
  getMouse(event);
  raycaster.setFromCamera(mouse, camera);
}

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


//RENDER
function render() {
  requestAnimationFrame(render);
  renderer.render(scene, camera);
}
render();
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/loaders/OBJLoader.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Answer №1

It seems like you're facing an issue with JavaScript scope here. The key is to ensure that the variable points is accessible throughout your code, not restricted to just one function. Here's an example to illustrate:

function init() {
   var points = 1;
}

// In this case, points will not be accessible
// outside the init function
init();
console.log(points);

To resolve this problem, declare your variable outside the function to broaden its scope by one level:

var points;
function init() {
    points = 1;
}

// Now you'll successfully log the output as 1
init();
console.log(points);

Here's a corrected version for your reference. Please note that both variables points and geometry had to be declared at the start of your code to make them available across all functions:

//SCREEN SETUP
var points, geometry;
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 5, 10);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x404040);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

//MOUSE CONTROLS
var controls = new THREE.OrbitControls(camera, renderer.domElement);

//LIGHT SETTINGS
var light = new THREE.DirectionalLight(0xffffff, 0.5);
light.position.setScalar(100);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.5));

//GRAY GRID ON SCREEN
scene.add(new THREE.GridHelper(100, 100));

//OBJECT LOADING
var objLoader = new THREE.OBJLoader();

objLoader.load('https://raw.githubusercontent.com/felipefsalazar/venus/master/venuspeq.obj',


  function(object) {

    child = object.children[0];
    geometry = new THREE.Geometry().fromBufferGeometry(child.geometry);
    geometry.computeFaceNormals();
    //geometry.mergeVertices();
    geometry.computeVertexNormals();
    geometry = new THREE.BufferGeometry().fromGeometry(geometry);

    scene.add(object);

    //STATUE MESH
    var plane = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({
      wireframe: true,
      color: "blue"
    }));
    scene.add(plane);

    //POINTS ON STATUE FOR INTERACTION
    points = new THREE.Points(geometry, new THREE.PointsMaterial({
      size: 0.15,
      color: "red"
    }));
    scene.add(points);


    //STATUE MESH (wireframe)
    //venuspeq = new THREE.Mesh(geometry, mesh);

    //OBJECT ROTATION
    //object.rotation.x = -Math.PI * 0.5;

    //OBJECT BOUNDING BOX
    //var box = new THREE.Box3().setFromObject(object);
    //var box3Helper = new THREE.Box3Helper(box);
    //scene.add(box3Helper);



  });


var raycaster = new THREE.Raycaster();
raycaster.params.Points.threshold = 0.15;
var mouse = new THREE.Vector2();
var intersects = null;
var plane = new THREE.Plane();
var planeNormal = new THREE.Vector3();
var currentIndex = null;
var planePoint = new THREE.Vector3();
var dragging = false;

window.addEventListener("mousedown", mouseDown, false);
window.addEventListener("mousemove", mouseMove, false);
window.addEventListener("mouseup", mouseUp, false);



function mouseDown(event) {
  setRaycaster(event);
  getIndex();
  dragging = true;
}

function mouseMove(event) {
  if (dragging && currentIndex !== null) {
    setRaycaster(event);
    raycaster.ray.intersectPlane(plane, planePoint);
    geometry.attributes.position.setXYZ(currentIndex, planePoint.x, planePoint.y, planePoint.z);
    geometry.attributes.position.needsUpdate = true;
  }
}

function mouseUp(event) {
  dragging = false;
  currentIndex = null;
}

function getIndex() {
  intersects = raycaster.intersectObject(points);
  if (intersects.length === 0) {
    currentIndex = null;
    return;
  }
  currentIndex = intersects[0].index;
  setPlane(intersects[0].point);
}

function setPlane(point) {
  planeNormal.subVectors(camera.position, point).normalize();
  plane.setFromNormalAndCoplanarPoint(planeNormal, point);
}

function setRaycaster(event) {
  getMouse(event);
  raycaster.setFromCamera(mouse, camera);
}

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



//RENDER FUNCTION
function render() {
  requestAnimationFrame(render);
  renderer.render(scene, camera);
}
render();
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/loaders/OBJLoader.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

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

sudden swivel when shifting camera while following an object on a flat surface/pathway

I'm relatively new to three.js and I'm eager to create a scenario where a cube or object moves on a flat surface or road. I have managed to move the object in the z direction, but now I want to move the camera as well, giving the impression of a ...

The issue with ThreeJS where the camera movement stops working after clicking

Seeking assistance with implementing camera movement in ThreeJS. Despite having no errors, clicking the button does not trigger the camera movement as expected. The function aimed at moving the camera by 200 units in all directions seems to have no effec ...

Challenges with npm and Node.js compatibility in a Vite project

I've run into a problem while attempting to launch my Vite project using npm. After updating Node.js to version 18.16.0, I'm now receiving the following error message: The specified module could not be found. \?\C:\Users\Riaj& ...

What is the most effective method for filtering a table using both column-specific and global filters?

Looking for the most efficient way to filter a large chunk of JSON data client-side using a table? Each header has an input filter where users can enter a string to filter that specific property. There is also a global filter for free text search. If you ...

``Troubleshooting Problem with Tailwind's Flex Box Responsive Grid and Card Elements

Starting point: Preview https://i.sstatic.net/zfzBU.jpg Code : <div class="container my-12 mx-auto"> <div className="flex flex-wrap "> {error ? <p>{error.message}</p> : null} {!isLoading ...

Using Nested Arrays to Create Search Filters with Query Parameters

Here is the data structure I am working with: [ { id: // the field to be search { eq: '1234' // eq is the operand; 1234 is the keyword } }, { description: { ...

Custom AngularJS directive that permits only alphabetic characters, including uppercase letters and the ability to input spaces

I'm currently working on an AngularJS directive that is meant to only allow alphabetical characters, however, I've encountered an issue where it disables caps lock and space functionality. While the main goal is to prevent special characters and ...

Launching Links in Browser Using Cordova in Android Platform

I am facing an issue with the inAppBrowser on Android. Despite setting it up correctly, using _blank or _system still results in the webpage loading within the app instead of opening in an external browser. Here is the relevant code: <a href="#" rel=" ...

Determine the global upward direction of an object along any given axis in ThreeJS

I'm struggling to determine the exact rotation of my object around any given axis. Thus far, I've managed to find the relative rotation of my object using a specific method. To achieve this, I positioned a plane behind the object aligned with th ...

The mismatch between JSON schema validation for patternProperties and properties causes confusion

Here is the JSON schema I am working with: { "title": "JSON Schema for magazine subscription", "type": "object", "properties": { "lab": { "type": "string" } }, "patternProperties": { "[A-Za-z][A-Za-z_]*[A-Za-z]": { "type" ...

Puppeteer - Issue with Opening Calendar Widget

Problem: Unable to interact with the calendar widget on a hotel website (). Error Message: Node is either not clickable or not an Element Steps Taken (code snippet below): const puppeteer = require('puppeteer') const fs = require('fs/promi ...

Retrieving the initial item from a Response.Json() object

i have a this code: fetch("https://rickandmortyapi.com/api/character/?name=Rick") .then((response) => { response.json().then((data) => { console.log(JSON.stringify(data)) }).catch( (error) => { console.log(`Error: $ ...

Issue with material-ui-dropzone, the DropzoneAreaBase component not displaying the preview of the uploaded files

Has anyone encountered issues with the DropzoneAreaBase component from the material-ui-dropzone library? I am having trouble getting it to display added file previews. Any insights into why this might be happening? <DropzoneAreaBase onAdd={(fileObjs) ...

Combine the elements of an array to form a cohesive string

As a newcomer to Javascript, I am feeling a bit puzzled about this conversion. var string = ['a','b','c']; into 'a','b','c' ...

Discover the method to adjust the position of elements, such as images, using radio buttons

I have an image positioned in a container along with 3 radio buttons. I want to make additional images appear over the main image when specific radio buttons are selected. Each button will trigger different positions for the additional images. So far, thi ...

"Enable real-time editing with inline save/submit feature in

I'm struggling to figure out how to extract the modified content from a CKEditor instance and send it to a URL. I've been referencing something like this: but I can't seem to determine how to save the changes. Is there a way to post the up ...

How to retrieve attributes of a model from a related model in Sails.js

Currently, I am utilizing the beta version(v0.10.0-rc3) of Sails.js and have updated the database adapter to PostgreSQL in order to enable associations via the Waterline ORM. My main focus is on creating a role-based user model for authorization based on d ...

Having trouble with Next.js environment variables not being recognized in an axios patch request

Struggling with passing environment variables in Axios patch request const axios = require("axios"); export const handleSubmit = async (formValue, uniquePageName) => { await axios .patch(process.env.INTERNAL_RETAILER_CONFIG_UPDATE, formVal ...

There seems to be an issue with the functionality of the JavaScript Quiz as it is

While working on my JS quiz, I encountered an issue where some answers were not displaying due to quotes and the need to escape HTML characters. Additionally, I am facing difficulty in accurately awarding points or deductions based on user responses. Curre ...

Using jQuery, selectively reveal and conceal multiple tbody groups by first concealing them, then revealing them based on

My goal is to initially display only the first tbody on page load, followed by showing the remaining tbody sections based on a selection in a dropdown using jQuery. Please see below for a snippet of the code. //custom JS to add $("#choice").change(func ...