Import 3D models and textures from a multipart file into three.js using Collada format

I am facing a challenge with loading Collada and image data stored in a multipart file outputted from an application. My goal is to display the Collada object and its associated images using three.js on the Web. However, I'm unsure if three.js can interpret the multipart file directly or if the data within the file needs to be parsed into separate files. The Collada loader example references a .dae file (e.g., loader.load('models/monster.dae')) rather than the actual data. How can I achieve this task of loading and viewing the "box" represented by the multipart data?

Below is the structure of the multipart file received from the application:

MIME-Version:1.0
Content-Type:multipart/mixed; 
boundary="----=_Part_4_153315749.1440434094461"

------=_Part_4_153315749.1440434094461
Content-Type: application/octet-stream; name=Texture_1.png
Content-ID: response-1
Content-Disposition: attachment; filename=Texture_1.png

‰PNG
"blob data here"
...

UPDATE:

After having the vendor split up the files, I was able to load the collada file directly into the viewer. However, I'm still unsure how to load the images along with it. Here is my current loading code snippet:

// instantiate a loader
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load('http://applicationvendorapi.com/dae', function (collada) {
    // processing logic
});

The XML of the Collada file contains references to images in the same directory as the Collada file. Can these images be referenced via URLs like /endpoint/texture_0 and /endpoint/texture_1?

UPDATE 2:

Incorporating advice to first load the texture using ImageUtils, I have updated the code as follows:

// Load texture before loading and initializing 3D object
var texture0 = THREE.ImageUtils.loadTexture('http://vendorwebservice/texture_0', {}, function loaded() {
    // Instantiate a Collada loader
    var loader = new THREE.ColladaLoader();
    loader.options.convertUpAxis = true;
    loader.load('http://vendorwebservice/dae', function (collada) {
        // processing logic
    });
});

However, there seem to be issues with fetching the texture using URL endpoints specified in the DAE file. Any ideas on resolving this issue?

Answer №1

For a web-service application without static URI's, it is necessary to download the data returned by the service locally. If texture files referenced in the Collada file are in a relative path to the .dae file, the THREE.ColladaLoader() function will successfully locate, load, and display them.

Answer №2

Although it may be past the deadline, I am sharing my insights in the hopes of assisting future readers.

I found myself facing a similar predicament where the files were not linked by static URIs. To avoid downloading the files due to concerns about data inefficiency and server resource usage, I opted to handle them manually in the browser using the following method:

  1. Determine the name of the image file referenced by the collada's texture
  2. Locate the image file corresponding to the name identified in step 1
  3. Create a Threejs texture utilizing the file discovered in step 2
  4. Attach the texture produced in step 3 to the texture slot in the collada material

Below is an example code snippet. In this scenario, the URLs within the code are data URLs.

const loadCollada = async (dae, img) => {
  const collada = new ColladaLoader().load(dae.url);

  // Extract all materials from the loaded collada
  const materials = new Set();
  collada.traverse((object) => {
    const mat = object.material
    if (mat) {
      if (mat.constructor.name === "Array") {
        mat.forEach((e) => {
          materials.add(e);  
        })
      } else {
        materials.add(mat);
      }
    }
  });

  // Parse the collada file
  const daeText = await fetch(dae.url).then((r) => r.text())
  const daeXml = new DOMParser().parseFromString(daeText,"text/xml")
  const materialLibrary = daeXml.getElementsByTagName("material")

  // Retrieve material names and texture names (image file names)
  Array.from(materialLibrary).forEach((e) => {
    const materialName = e.getAttribute("name")
    const effect = e.getElementsByTagName("instance_effect")[0]
    const textureUrl = effect.attributes.url.value.slice(1)
    const textureTag = daeXml.getElementById(textureUrl)
    const textureName = textureTag.getElementsByTagName("init_from")[0]?.innerHTML

    // Match the material with the name
    if (textureName) {
      Array.from(materials).forEach((mat) => {
        if (mat.name === materialName) {
          // Create a texture and assign it to the matched material
          const texture = new THREE.TextureLoader().load(img[textureName].url)
          texture.wrapS = THREE.RepeatWrapping
          texture.wrapT = THREE.RepeatWrapping
          mat.map = texture
        }
      });
    }
  })
}

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

How can I bind an event for changing innerHTML in Angular 2?

Is there a way to implement something similar to this: <div [innerHTML]="content" (innerHTMLchange)="contentInit()"></div> Currently, I have a variable content that is updated by a service fetching a string from my express server. The content ...

Creating HTML using JavaScript

This particular issue has been a challenge for me despite its apparent simplicity. I have a Javascript code that is responsible for constructing elements in the DOM by utilizing JSON data from a server script. Within this code, some of the elements include ...

Retrieve the total number of users in a Node.js application by querying the MongoDB database

Within my node application, I have the ability to register users and showcase their profiles. My aim is to exhibit the total number of users in the database on the homepage exclusively for the logged-in user. The pivotal route in my route.js file reads as ...

What is the significance of using curly braces within the function setFormData to update the formData object with the key-value pair [e.target.name]: e

The onChange function I have set up is used for submitting a form with multiple input values, and it takes in whatever the name attribute of the input field is. While I understand the basic functionality of this code, I am curious about what exactly happen ...

React callbacks involve the interaction between three different components

Currently, I am working with 3 distinct components: -The friendsPage component contains a list of friends and invitations to friends -The friendComponent displays detailed information about a friend along with possible actions (which are handled in the t ...

Is there a way to show a 'Refresh' icon in HTML without the need to download an image through HTTP?

In my HTML/JavaScript app project, I am looking to incorporate a 'refresh' symbol without having to load an image through HTTP requests. Are there reliable methods that can achieve this across all major browsers? I came across the Unicode value: ...

trouble displaying Google AdSense ads

I'm having trouble getting the ad to display on my website despite trying many different solutions. Any advice you can offer would be greatly appreciated. Thanks in advance! <!doctype html> <html lang="en"> <head> < ...

Select the five previous siblings in reverse order using jQuery's slice method

I have a unique approach to displaying a series of divs where only 5 are shown at a time using the slice() method. To navigate through the items, I include an ellipsis (...) link after every 4th item, which allows users to easily move on to the next set of ...

If the div element undergoes a change, use an if-else condition to populate the data fields accordingly

I'm looking to create a basic if/else statement in JavaScript that checks if a div element has changed before populating JSON data fields/variables that pull from dynamically updated HTML. I want to avoid using the deprecated DOMSubtreeModified metho ...

Access the second DIV using JavaScript's getElementById method

What could be preventing me from displaying a Google map in the second DIV ID? I attempted changing my Map_canvas to Class with the same results. I am aiming to showcase a Google map in the second Div, map_canvas. The map functions within my jQueryMobile s ...

Using cookies in JavaScript for saving and fetching data

Currently, I am delving into the world of Javascript and attempting to work with cookies. Although my code appears to be correct, there seems to be an issue that I can't quite pinpoint. function init() { var panel = document.getElementById("panel ...

Passing the IDs of other elements as arguments when invoking a JavaScript function

Greetings, as I work on a jQuery mobile app, a particular scenario has arisen that requires attention. <script> function showPanel(info) { alert(info.id); } </script> <div data-role=" ...

Difficulty in displaying additional search outcomes

I decided to take on the challenge of learning coding by working on a website project that involves creating a simple search site. One feature I implemented is when users search for keywords like "Restaurant" or "Restaurants," they are presented with refi ...

Having trouble updating state in React after making a fetch request

I am encountering an issue with setting the current user after a successful login. Even though the login process is successful and the data is accurate, I am unable to set the state as the user data appears to be empty. UserContext.js import React, { useC ...

Need to monitor a Firebase table for any updates

How can I ensure my Angular 2 app listens to changes in a Firebase table? I am using Angular2, Firebase, and TypeScript, but the listener is not firing when the database table is updated. I want the listener to always trigger whenever there are updates or ...

Resolving Jest error in React JS unit tests

While working on a unit test for React code, I encountered an issue with a particular action. For example, suppose I have the following line in testing.js: const images = require.context('../../../media/promotions', true); Here is the unit tes ...

Tips for retrieving only the changes or updates from DynamoDB streams

Currently, I am faced with a scenario where I must comprehend the distinction between NEW_IMAGE and OLD_IMAGE on dynamoDB streams. As per the information available at: https://aws.amazon.com/blogs/database/dynamodb-streams-use-cases-and-design-patterns/ ...

react-swiper does not trigger a re-render

function WorkSpace() { const dispatch = useDispatch(); const edit = useSelector((state)=>(state.workSpace.edit)); const currentMode = useSelector((state)=>(state.workSpace.currentMode)); useEffect(()=>{ const swiper = docu ...

No response observed upon clicking on the li element within the personalized context menu

I created a custom context menu that pops up when you click on an li element within an unordered list. I'm trying to trigger an alert when clicking on an li item inside the context menu, but it's not working as expected. To handle this dynamic c ...

I'm completely baffled as to why the client console is unable to locate my JS file

I have a question that may seem basic, so please bear with me! I'm having trouble adding a js file to an html page and it seems to be related to the file path. In my HTML page, I have this code to link the file: <script src="../src/utils/mapbo ...