Ways to expand the constructor function of the THREE.Mesh class

Exploring Three.js, I'm working on creating a basic model of the solar system. My current task involves building constructor functions for planets and moons. However, I keep encountering an error message:

The function setShadow() is not recognized.

var celestialBody = function(size, color) {
  this.sphere = new THREE.Mesh(new THREE.SphereGeometry(size, 32, 32), 
                               new THREE.MeshLambertMaterial({color:color}))
  return this.sphere
}

celestialBody.prototype = Object.create(THREE.Mesh.prototype);
celestialBody.prototype.constructor = celestialBody;

celestialBody.prototype.setShadow = function() {
  this.sphere.castShadow = true
  this.sphere.receiveShadow = true
}

I also attempted using

THREE.MESH.call(this, geometry, material)
, defining THREE.SphereGeometry = geometry and
THREE.MeshLambertMaterial = material
outside the constructor function. Is there anything specific I should be cautious about when working with Three.js, or is my approach flawed?

Edit: Another approach attempted -

var celestialBody = function() {
      THREE.Mesh.call(this)
      return this
    }

    celestialBody.prototype.setShadow = function() {
      this.castShadow = true
      this.receiveShadow = true
      return this
    }
    celestialBody.prototype = Object.create(THREE.Mesh.prototype);
    celestialBody.prototype.constructor = celestialBody;

    var samplePlanet = new celestialBody(new THREE.SphereGeometry(70, 32, 32), new THREE.MeshLambertMaterial({color:this.getRandColor()}))

It appears that everything is inheriting correctly, but I am puzzled by the malfunctioning setShadow function.

EDIT 2: Upon trying .call(this), the following error was encountered:

this.updateMorphTargets is not a function

Answer №1

You have encountered an error in your constructor when extending the THREE.Mesh class.

Here is a corrected version:

var Body = function(size, color) {
    THREE.Mesh.call(
        this, 
        new THREE.SphereGeometry(size, 32, 32), 
        new THREE.MeshLambertMaterial({color:color})
    );
}

Body.prototype = Object.create(THREE.Mesh.prototype);
Body.prototype.constructor = Body;

In the constructor, there is no need to include a return statement as the object created will be automatically returned.

When modifying your setShadow method, make sure to refer to this, since the properties castShadow and receiveShadow are direct properties of the newly created Body class (inherited from THREE.Object3D through THREE.Mesh).

Body.prototype.setShadow = function() {
    this.castShadow = true;
    this.receiveShadow = true;
}

It is recommended to use capital letters for the first character of your constructor's name. In the provided code, I changed body to Body. Ensure all other references are updated accordingly.

Check out a demonstration in a fiddle here

Answer №2

When utilizing the "function" method, you may encounter this error:

Uncaught TypeError: Class constructor Mesh cannot be invoked without 'new'

The most effective approach is to implement it using classes. Here's an example:

class Body extends THREE.Mesh {
  constructor(size, color) {
    super(
      new THREE.SphereGeometry(size, 32, 32),
      new THREE.MeshLambertMaterial({
        color: color
      })
    )
  }

  setShadow() {
    this.castShadow = true
    this.receiveShadow = true
  }
}

const body = new Body(20, 0x000000)
console.log({castShadow: body.castShadow, receiveShadow: body.receiveShadow})
body.setShadow()
console.log({castShadow: body.castShadow, receiveShadow: body.receiveShadow})
<script src="https://threejs.org/build/three.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

Angular Pause until the variable is ready

I am in the process of developing a new web application service. The first step involves obtaining a token through the rest API. Once this token is obtained, it needs to be sent as a header to retrieve additional information. The issue I'm facing is ...

What could be causing the issue with the array.push method not functioning

i have come across this piece of code function fetchImagesList(errU,errorsList) { if(errU) throw errU; var directories=new Array(); var sourceDir=''; var destinationDir=''; if(errorsList==&a ...

The method $event.stopPropogation doesn't seem to be functioning properly

I am facing an issue where the functionality of a div is affected when clicking on an input box inside it. When the div is selected and colored red, clicking on the input box within the selected div causes the div to become unselected (grey in color). I ...

Performing an AngularJS $http POST request with a combination of JSON parameter and query string

I'm currently trying to write an AJAX call using Angular's $http object in order to send a post request with JSON in the body and a query string appended to the URL. Despite going through the documentation for $http, looking for solutions on SO, ...

The property 'licenses' has incompatible types. The type 'License[]' cannot be assigned to type 'undefined' in the getServerSideProps function while using iron-session

I am encountering an issue with red squiggly lines appearing on the async keyword in my code: Argument of type '({ req, res }: GetServerSidePropsContext<ParsedUrlQuery, PreviewData>) => Promise<{ props: { admin: Admin; licenses?: undefined ...

"Using Node.js Express 4.4 to efficiently upload files and store them in a dynamically

Looking for recommendations on the most efficient method to upload a file in node.js using express 4.4.1 and save it to a dynamically created directory? For example, like this: /uploads/john/image.png, uploads/mike/2.png ...

The damping effect in three.js OrbitControls only activates when the mouse is pressed, however there is no damping effect once the

I find it difficult to articulate: Currently, I am utilizing OrbitControls in three.js and have activated damping for a smoother rotation with the mouse. It is somewhat effective but not entirely seamless. When I click and drag, the damping feature works ...

What could explain why the event listener functions properly on the initial call but fails on subsequent calls?

Currently, I am working on a bootstrap carousel where the "Previous" button is hidden on the first slide and the "Next" button is hidden on the last slide. Now, I want to disable the next button on the second slide (and eventually all slides with iframe vi ...

Loading images asynchronously in Next.js before the user arrives at the component displaying them

Currently, I am developing a Next.js application with only one page where users have the option to click on certain buttons to reveal an image. I would like to make it mandatory for clients to download the image before revealing it through a click event. S ...

Getting the correct JSON field value from a JavaScript Promise object in the right way

Trying to fetch data in JSON format from a URL, I encountered an issue where the value of responseData.title differed between two calls made within the second .then() function below: var getTitleForId = async function(id) { if (!id) return fal ...

Issue specifically with Android 6 WebView - jQuery 1.9.1 where a RangeError is thrown due to the call stack size being exceeded

An error message "Uncaught RangeError Maximum call stack size exceeded" is causing a web application to fail in the jQuery-1.9.1 extend() function, but strangely it only occurs on Android 6. The application runs smoothly on all other platforms such as Des ...

The callback function for ajax completion fails to execute

My current framework of choice is Django. I find myself faced with the following code snippet: var done_cancel_order = function(res, status) { alert("xpto"); }; var cancel_order = function() { data = {}; var args = { type:"GET", url:"/exch ...

Change Observable<String[]> into Observable<DataType[]>

I'm currently working with an API that provides me with an Array<string> of IDs when given an original ID (one to many relationship). My goal is to make individual HTTP requests for each of these IDs in order to retrieve the associated data from ...

PHP-generated HTML onclick attribute malfunctioning

Here is the PHP code I am currently working with: $listing .= "<button onclick='updateValue(".$id.", ".$key.")'>change value</button>"; The variable $id is an integer and functions correctly. However, $key is a reference from a for ...

Tips for modifying date format in Angular 8

My datepicker for a date column is displaying the incorrect date format after submission. I am looking to change this format to the correct one. I am working with bsConfig bootstrap in Angular 8, but I am unsure of how to modify the date format. The back ...

Tips for implementing conditional app.use() in nestJS backend strategies?

Trying to incorporate helmet into my nestJS application. I also require the inclusion of graphqlUploadExpress. How can I properly utilize the usesUpload condition to implement either helmet alone or along with upload? import { NestFactory } from '@nes ...

Adjust size of item within grid component in VueJS

I have a grid container with cells and a draggable item in a Vue project. I am trying to figure out how to resize the box inside the grid component (refer to images). https://i.stack.imgur.com/q4MKZ.png This is my current grid setup, and I would like the ...

Having trouble simulating a custom Axios Class in JavaScript/TypeScript

Here are the function snippets that I need to test using jest, but they require mocking axios. My attempt at doing this is shown below: // TODO - mock axios class instance for skipped Test suites describe("dateFilters()", () => { beforeEac ...

How can I utilize the JQuery GetJSON function to retrieve HTML content from an external webpage?

Imagine you're attempting a jQuery ajax request like this: $.ajax({ ... url: http://other-website.com ... }) You probably know that due to the same-origin policy, this request will fail because the URL is for an external domain. But the ...

Class for Eliminating the Background Image Using Bootstrap

Is there a Bootstrap class that can be used to remove a background image from a div? Currently, I have this style defined in my CSS: background-image: linear-gradient(to bottom, rgba(0,0,0,0.1), rgba(0,0,0,0)); I would like to remove it using: bg-img-non ...