Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The Support for colored STL and OBJ files is not present. #6670

Closed
1 of 17 tasks
diyaayay opened this issue Dec 28, 2023 · 9 comments · Fixed by #6710
Closed
1 of 17 tasks

The Support for colored STL and OBJ files is not present. #6670

diyaayay opened this issue Dec 28, 2023 · 9 comments · Fixed by #6710

Comments

@diyaayay
Copy link
Contributor

diyaayay commented Dec 28, 2023

Increasing Access

image
image

Went through the learn pages and found out that p5.js currently does not support colored STL files while creating custom geometry.
Found the relevant code here:

/**
 * This function parses the Binary STL files.
 * https://en.wikipedia.org/wiki/STL_%28file_format%29#Binary_STL
 *
 * Currently there is no support for the colors provided in STL files.
 */
function parseBinarySTL(model, buffer) {
  const reader = new DataView(buffer);

  // Number of faces is present following the header
  const faces = reader.getUint32(80, true);
  let r,
    g,
    b,
    hasColors = false,
    colors;
  let defaultR, defaultG, defaultB;

  // Binary files contain 80-byte header, which is generally ignored.
  

Link to the code:
https://github.com/processing/p5.js/blob/8f2b47c2957fda064992ddffbceb62983a26103c/src/webgl/loading.js#L357C1-L375C1

Most appropriate sub-area of p5.js?

  • Accessibility
  • Color
  • Core/Environment/Rendering
  • Data
  • DOM
  • Events
  • Image
  • IO
  • Math
  • Typography
  • Utilities
  • WebGL
  • Build Process
  • Unit Testing
  • Internalization
  • Friendly Errors
  • Other (specify if possible)

Feature request details

STL files can have color information in the form of per-face or per-vertex color attributes. We would need to modify the parser to extract and interpret this color data and then use it appropriately in the application.

Here's a high-level overview of the steps:

Parse Color Information:

For binary STL files, understand the format's structure to locate color information.
For ASCII STL files, adapt the parser to recognize and process color data in the file.
Integrate Color in Rendering:

Modify the rendering code to consider color information while rendering the 3D model.
Adjust shaders or rendering logic to incorporate color attributes.
Update File Upload and Display:

When handling file uploads, ensure that the code correctly interprets and processes color data from STL files.
Update the UI to display the 3D model with color.
Testing:

Test the implementation with STL files containing color information to verify that both geometry and color are rendered correctly.

I think this is where the functionality should be implemented:
}
if (hasColors) {
// add support for colors here.
}
return model;
}

p5.js/src/webgl/loading.js

Lines 439 to 445 in 8f2b47c

}
if (hasColors) {
// add support for colors here.
}
return model;
}

@diyaayay
Copy link
Contributor Author

I would love to have a discussion over this and see if the current functionality of p5.js allows implementing the feature, I would like to implement it.
@davepagurek What do you think?

@diyaayay diyaayay changed the title STL files do not support colors while buinding Custom Geometry STL files do not support colors while building Custom Geometry Dec 28, 2023
@diyaayay diyaayay changed the title STL files do not support colors while building Custom Geometry The Support for colored STL files is not present. Dec 28, 2023
@davepagurek
Copy link
Contributor

I'm less familiar with the stl format, does it include colors all in one file? .obj files also don't currently support color imports, but I gather the blocker there is also the fact that typically they come in two parts: a .obj file that specifies shape and material names, and a .mtl file with the material definitions. Adding color support for objs would need an update to the APIs to include loading that second file too, would STL be the same?

Another complication is that p5.Geometry supports per-vertex colors, but not necessarily per-vertex materials. .obj materials not only include color, but also things like specular color, diffuse color, etc. To support that, I think we'd need to make a new class that can contain multiple p5.Geometry objects with a transformation matrix and material settings for each, allowing one to store multiple shapes + settings in one object. If STL materials also work the same way, they'd also need that. If they really only have colors, then they could potentially be imported just as p5.Geoemtry vertex colors.

@davepagurek
Copy link
Contributor

I think adding just colors could be a good way to start regardless, and we definitely have the ability to do that in p5.Geometry.

I'm going to tag the other WebGL stewards too: @aferriss, @aceslowman, @ShenpaiSharma, @ChihYungChang, @teragramgius, @JazerUCSB, @richardegil, @itsjoopark, @Gaurav-1306, @jeanetteandrews, does that seem light the right approach to you, both for right now and for how it might need to be extended in the future?

@diyaayay
Copy link
Contributor Author

@davepagurek Thanks a lot for tagging other stewards. The approach seems fair enough to take this forward.
Since You mentioned that .obj files also don't support color imports currently.
.obj files include .mtl files which provide the color and material information.
The STL file format also does not inherently support color information. STL files are primarily used for representing the geometry of 3D models by describing the surface using triangular facets.
However, the coloring of STL files is complex and not common.
Can we implement the color functionality of .obj files then?

@diyaayay diyaayay changed the title The Support for colored STL files is not present. The Support for colored STL and OBJ files is not present. Dec 28, 2023
@davepagurek
Copy link
Contributor

That sounds good to me!

Looking at the .mtl spec on wikipedia, it looks like they set a bunch of comopnents of the material: ambient color, diffuse color, and specular color, among other things. We can translate diffuse colors to the vertexColors array in p5.Geometry and ignore the other properties for now until we do something like the group-of-p5.Geometry (p5.GeometryGroup?) thing I was describing to allow multiple material settings within one object.

@diyaayay
Copy link
Contributor Author

diyaayay commented Dec 28, 2023

Seems like a plan! I'll start looking into the translation of diffuse colors to vertexColors array for now.
P5.GeometryGroup looks good to me. Lets dive into that soon once we're done implementing the part above.

@diyaayay
Copy link
Contributor Author

@davepagurek
Started with writing a parser for the mtl files in p5/src/webgl/loading.js and then translate the diffuse colors to vertexColors.
-p5.js has parseObj and parseStl. So it would require a parseMtl?
if the parser looks something like this:

function parseMtl(model, lines) {
  const materials = {}; //stores parsed material data

  for (let line = 0; line < lines.length; ++line) {
    const tokens = lines[line].trim().split(/\s+/);

    if (tokens.length > 0) {
      if (tokens[0] === 'newmtl') {
        // Create a new material
        materials[tokens[1]] = {};
      } else if (tokens[0] === 'Kd') {
        // Diffuse color
        materials[materials.current].diffuse = [
          parseFloat(tokens[1]),
          parseFloat(tokens[2]),
          parseFloat(tokens[3])
        ];
      } else if (tokens[0] === 'Ka') {
        // Ambient color
        materials[materials.current].ambient = [
          parseFloat(tokens[1]),
          parseFloat(tokens[2]),
          parseFloat(tokens[3])
        ];
      } else if (tokens[0] === 'Ks') {
        // Specular color
        materials[materials.current].specular = [
          parseFloat(tokens[1]),
          parseFloat(tokens[2]),
          parseFloat(tokens[3])
        ];
      } else if (tokens[0] === 'Ns') {
        // Specular exponent
        materials[materials.current].shininess = parseFloat(tokens[1]);
      } else if (tokens[0] === 'map_Kd') {
        // Diffuse texture map
        materials[materials.current].diffuseMap = tokens[1];
      }
    }
  }

  model.materials = materials;
  return model;
}

and taking an example mtl file ,after parsing would look something like this:
MTL file:

newmtl Material1
Kd 0.8 0.2 0.2  # Diffuse color (red)
Ka 0.2 0.2 0.2  # Ambient color (gray)
Ks 0.5 0.5 0.5  # Specular color (white)
Ns 50.0          # Shininess
map_Kd texture1.png  # Diffuse texture map

newmtl Material2
Kd 0.2 0.8 0.2  # Diffuse color (green)

model.materials from the returned model:

{
  "Material1": {
    "diffuse": [0.8, 0.2, 0.2],
    "ambient": [0.2, 0.2, 0.2],
    "specular": [0.5, 0.5, 0.5],
    "shininess": 50.0,
    "diffuseMap": "texture1.png"
  },
  "Material2": {
    "diffuse": [0.2, 0.8, 0.2],
    // Other properties (ambient, specular, etc.) would be undefined if not specified in the MTL file
  }
}

Then extract diffuse colors from it and translate them into vertexColors array in p5.Geometry as We are going to ignore other properties for now and only use diffuse colors.
Is this the right way to approach this?

@davepagurek
Copy link
Contributor

That looks like a great start!

  • Next step would probably be to change the diffuse colors in the model based on those materials. That would likely mean loading the materials before loading the vertex data, and adapting the .obj importer to recognize the materials
  • Also it would be great to add some unit tests for the parser too

@diyaayay
Copy link
Contributor Author

@davepagurek thanks for the heads up on what to do next.
I'll start with coding these functions and add some unit tests too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants