frenchtoast747 / webgl-obj-loader Goto Github PK
View Code? Open in Web Editor NEWA simple OBJ model loader to help facilitate the learning of WebGL.
Home Page: http://frenchtoast747.github.io/webgl-obj-loader/
License: MIT License
A simple OBJ model loader to help facilitate the learning of WebGL.
Home Page: http://frenchtoast747.github.io/webgl-obj-loader/
License: MIT License
The OBJ.Mesh class should be moved into its own module.
The OBJ.Material class should be moved into its own module
With the existing support for .mtl files it would make sense for the library to calculate the tangents and bitangents as an option. These are later needed for calculating the TBN matrix when dealing with normal maps.
The tangents and bitangents are derived from the vertices positions and (most commonly) the direction of the texture coordinates.
Hi there, I just spotted that (webgl-obj-loader.js; line 866):
_case layout.Layout.UV.key:
dataView.setFloat32(offset, this.textures[i * 2], true);
dataView.setFloat32(offset + 4, this.vertices[i * 2 + 1], true);
probably should look like
_case layout.Layout.UV.key:
dataView.setFloat32(offset, this.textures[i * 2], true);
dataView.setFloat32(offset + 4, this.textures[i * 2 + 1], true);
which seems to solve a small problem that I had with correct gBuffer mappings ; D
Hello
I've been trying this method:
Create a one global array buffer for each type of data (position, uv, normal, etc).
Then create one element buffer array (index) for each material index data.
Create one VAO for each material index array. Every VAO is going to be bound to all the global array buffer and one respective element buffer.
Lastly I draw every VAO.
I tried this approach with Drovaric sponza from https://casual-effects.com/data/ and it works fine, but it does not have normal data, so I used blender to generate the normals and I get a bad result when drawing the mesh, like the the vertices are out of order.
in the case of using OBJ.initMeshBuffers, how would i go about it?
Thanks.
The current documentation around the indicesPerMaterial
attribute is very confusing as many different terms are used interchangeably.
The Readme states that the indices can be used to index into the attribute component arrays such like
submeshIndices = indicesPerMaterial[0];
attributeIndex = submeshIndices[0];
vertices[attributeIndex];
normals[attributeIndex];
textures[attributeIndex];
However the attribute arrays themselves are flattened so that each element stores an attribute component rather than a vertex full attribute. Therefore to store information for a full vertex one must index the attribute arrays once for each component of the vertex attribute (so 3 times for a position and 2 times for a texture coordinate).
But it isn't clear which is the correct method of doing this either:
attributeIndex0 = submeshIndices[0];
attributeIndex1 = submeshIndices[1];
attributeIndex2 = submeshIndices[2];
Vector3 actualVertexPosition;
actualVertexPosition.x = vertices[attributeIndex0];
actualVertexPosition.y = vertices[attributeIndex1];
actualVertexPosition.z = vertices[attributeIndex2];
or
attributeIndex = submeshIndices[0];
Vector3 actualVertexPosition;
actualVertexPosition.x = vertices[attributeIndex];
actualVertexPosition.y = vertices[attributeIndex + 1];
actualVertexPosition.z = vertices[attributeIndex + 2];
I'm guessing the latter otherwise it wouldn't work with attributes of different sizes, but that's just my guess. The documentation should be clearer to specify which is correct.
What also doesn't help is the naming of the vertices
attribute which is in fact vertex positions and so should be named positions
, but maybe I should make a separate issue for that?
Usually, when an .obj file is exported, a .mtl file is exported as well.
The .mtl contains information such as texture maps and colors. An .obj file will reference a lib name from which to load material names. The name of the lib is the name of the corresponding .mtl file to load. A material is then prefixed before one or more faces that use that material.
For example:
# at the top of SomeModel.obj file
mtllib SomeModel.mtl
# ...vertex, vertex normal, and texture coord definitions here...
usemtl my_material
f 2/1/1 4/2/2 3/3/3
f 5/4/4 7/5/5 6/6/6
...
While parsing, the material information should be associated with the specific faces. Several simple models that I have seen usually only have a single material that applies to all faces, although, this may not always be the case.
I'm not entirely sure how to handle application of MTL information to the OBJ model at the moment.
This addition could greatly help in getting models with simple textures loaded quickly in an organized manner.
Helpful reading materials:
http://nendowingsmirai.yuku.com/forum/viewtopic/id/1723#.VEf6cPnF9wB
http://people.cs.clemson.edu/~dhouse/courses/405/docs/brief-mtl-file-format.html
https://en.wikipedia.org/wiki/Wavefront_.obj_file#Material_template_library
Hi everyone, I'm a noob in 3D graphics. I tried to load the model I attach
bb8.obj.zip
but it doesn't show up. I downloaded the model from http://tf3dm.com, and it seems to work in http://www.meshlabjs.net/
I cloned webgl-obj-loader and checked out in the gh-pages branch. Then I added my model in the models/ directory and makes the window.onload function in webgl.js load "bb8.obj" instead of "suzanne,obj" and the result is... that nothing appear on the pedestal
I looked at the javascript console, and this is what I got:
non well-formed tunnel_ceiling.obj:1:2
non well-formed tunnel_walls.obj:1:2
non well-formed room_walls.obj:1:2
non well-formed room_ceiling.obj:1:2
non well-formed room_floor.obj:1:2
non well-formed room_tunnel_ceiling.obj:1:2
non well-formed room_tunnel_walls.obj:1:2
non well-formed room_wall_broken.obj:1:2
non well-formed room_wall_unbroken.obj:1:2
non well-formed bb8.obj:1:2
non well-formed pedestal.obj:1:2
non well-formed boulder.obj:1:2
A "non well formed" for each .obj files I tried to load (also for those that I didn't changed such as "boulder.obj"). I get the same errors on http://frenchtoast747.github.io/webgl-obj-loader/, but of course I can see suzanne on the pedestal.
I watched into the .obj files, and I saw that there were some missing lines in bb8.obj, that I added:
o bb8.obj
g default
but nothing changed.
I also noticed that the lines are in different order from the other files: in "suzanne.obj", there are a lot of lines that starts with "v", then a lot of lines that starts with "vn", then a lot of lines that starts with "f"
in "bb8.obj", there are a lot of lines that starts with "v", then a lot of lines that starts with "vn", then a lot of lines that starts with "vt", then a line that begins with "s" and finally lot of lines that begins with "f" and "s", mixed.
As I said before, I know nothing about the obj format, I can just guess that each line defines a vertex, and in the two files the lines order is different.
I wonder why webgl-obj-loader cannot load my .obj file, or as an alternative, can you please tell me how to reorder the lines in my file to get it loaded?
Thank you in advance,
Lucio
Hey, awesome job on loader!
I'm working on a project that is using webpack. I couldn't find any webpack loaders for obj files, so i made my own which just calls this library new Mesh(source)
. Just want to leave this here for people that are using webpack.
The parser currently only supports separating submeshes via 'usemtl' statements. However a large part of the OBJ format (and meshes in general) is the ability to split meshes into submeshes or 'groups' via the 'g' option.
Without this support the parser will currently provide single arrays of vertex attributes as opposed to separate arrays of attributes per group, for meshes without 'usemtl' statements.
The image/texture/reflection map files have options that can be passed along with the filename. A new option parser class should be created to be able to handle these options.
Note, according to the Wikipedia page, the format specifies that the filename always comes after the options, however, there is at least one vendor that allows for the filename to come before. This should be considered.
The most difficult part of parsing the options (and why we most likely have to write a custom parser) is due to the -o, -s, and -t options allowing 0, 1, or 2 args.
Enable or disable materials via the MATERIAL_WEIGHT
attribute.
@qtip feel free to expand your thoughts on this issue.
I've caught myself pushing without running a few tests already. It would be nice to set up the continuous integration in order to automatically run. This will make accepting pull requests that much easier.
If you export a model with quads and texture coordinates, you will see artifacts.
But if all the quads are converted to triangles when exporting in advance, there are no problems.
You can check it in the sandbox
https://codesandbox.io/s/apple-webgl-u4pg7
You can also check model in obj viewer.
The current triangulation algorithm is very simple and can potentially produce interesting (and unexpected) shading effects.
Depends on #12 . Once the interface has been changed to work async with 1 worker, we should try to spawn multiple workers, since an obj file should be able to be parsed in parallel, and recombined in order.
Hello ,
Is it possible to load multiple objects or multiple instances of same obj into the scene? how do i do it?
thanks
Veni
Hello,
I cannot compile my simple example using "model": "AMD".
Thank you for any help in advance.
Thanks for the obj loader, very helpful library.
Is it possible to use the Mesh in other libraries like ThreeJS?
Sometimes it's not desirable to pass all the material information to a single shader, but rather switch shaders between materials.
One solution would be to have the materials hold separate index buffers to accomplish this.
How do I handle a model with multiple textures? Is there a way to know what texture-coordinates a specific texture should have on the model?
For example, a horse, where the tail is a seperate texture, or a man with a hat
looks like the arrays are a bunch of strings in node.js.
vertices, vertexNormals, textures are strings, while indices are numbers.
As the tile describles
Thanks for making this library! I'm looking forward to playing with it :)
One thing at a glance - I downloaded some basic sphere model from turbosquid and it comes with some material. When I load it via webl-obj-loader
and console.log
the mesh returned from downloadMeshes
I see there's some materials.
Looking the source of material.js- I see lots of great comments on what a material is - e.g. diffuse, specular, etc.
However, I don't see any documentation of how to use this in a shader. I understand that there is no 1:1 correspondence since lighting is implementation specific, and using this library as opposed to Three.JS is all about getting down and dirty to DIY.
Still, any documentation or leads on how to get from materials to shader/js implementation is helpful. Sortof like nice how to you did with initMeshBuffers
... e.g. maybe provide a helper util, but show code samples of the reasoning behind it so it's easier to build from scratch?
Right now I'm just learning WebGL and sortof at a place of basically understanding how to apply a directional light by formula (e.g. this article) - to give some context :)
Any thoughts on this are appreciated.
Thanks!
Right now the lib seems to convert quads to triangles and thus assumes 3 or 4 vertices per face. The .obj format has however no limit on how many vertices there should be per face and some models break because of this.
An example of an .obj which sometimes has more than 4 vertices per face rendered in my engine using gl.drawElements
:
(Model taken from https://casual-effects.com/g3d/data10/research/model/breakfast_room/breakfast_room.zip)
downloadMeshes() still uses Ajax()
. Switch it over to using the new fetch()
API.
This module is currently missing and index.d.ts
file which means that it is not compatible with TypeScript without type casting to any
type, which removes the benefit of the static typing.
If any maintainer of this repo is interested, I would be happy to open a PR to add one?
I get empty string ("") in filename on the sponza 3d model material downloaded from this site https://casual-effects.com/data/.
Maybe I dont understand the source code yet, can somebody tell me where can I get the texture image path/filename from each material.
my code is more or less this:
var sponzaMeshObjText = getString('Assets/sponza/sponza.obj');
var sponzaMeshObj = new OBJ.Mesh(sponzaMeshObjText);
var material = new OBJ.Material(sponzaMeshObj.materialNames[0]);
console.log(material);
I could load it manually but the sponza model have a lot of meshes and textures.
Currently, if a model has more than 4 vertices in a face, the model will not load correctly and will have gaps. To prevent this from happening, the model first needs to be pre-processed and triangulated to make it WebGL happy.
This is somewhat of a pain for people wanting to learn WebGL, but not care about how model files are laid out (or how to use some third party program to pre-process the file).
Instead, the model should be converted to triangles on the fly.
in webgl-obj-loader.js I had to change the line
Layout.DISSOLVE = new Attribute("dissolve", 3, TYPES.FLOAT);
to
Layout.DISSOLVE = new Attribute("dissolve", 1, TYPES.FLOAT);
for my materials to parse correctly
Though this would change the interface, parsing should really be done in a separate thread so as not to block the main thread of execution. Meshes like the Stanford Dragon (~9MB) will trigger a slow script warning.
Right now Mesh.makeBufferdata doesn't handle Attributes that it's unaware of. We should make it easy to allow custom Attribute objects that perhaps have a user callback to stuff data into the buffer.
The existing helper function can remain, but it should be updated to use the new Layout()
class.
Since mtl format is not supported I want to set a fixed color to my mesh. Would it work to create a new program with color shaders enable the attribute?
even with 78d9d17 I still see strings in the browser. Usually, this isn't an issue, but if you try and transform them you'll run into funky bugs. I need to sit and run a bisection to see where I broke this, figure out why it's different in node.js, then write a unit test to catch this.
Currently, the loader expects the user to bind a grand total of four different buffers before drawing the mesh. There should be an option that allows the Mesh instance to interleave all of the data into a single list.
Thanks for your good works,I have cloned this project and attempted to run the deveplement examples,but it warns with 'mesh.js:534 Material "Gold" not found in mesh. Did you forget to call addMaterialLibrary(...)?'.
I have no idea whether I have overlooked something.
Hi,
thank you for your nice script.
i now encountered obj files exported from cinema 4d which have 3 numbers per texturecoordinate, which does not make sense for 2d textures.
all the indices for texture coordinates are wrong when loading this .obj file.
i fixed it by checking the number of elements and reducing it to 2 if >2
do you want me to create a pull request for this ?
I'm not sure if this is a best practice or not. It's frustrating when meshes' vertices are values greater than +/- 1. A friend described to me a trick where you fit a model to clip space by iterating over each vertex, keeping track of max & min x, y, & z values, then pass over them again multiplying them to fit within exactly the 2x2x2 clipping cube. This would make meshes that appear too small be a more reasonable size, and meshes that are too large fit within the standard clipping cube. You could always transform the vertices later with a model matrix. One issue is non uniform scaling. We wouldn't want to non-uniformly scale each axis, or that would mess up the dimensions of the model. Instead, we'd want to find out which axis was closest (or farthest, I guess) to -1:1 and just uniformly scale each axis. It might be a better idea to do this offline once for the obj, rather than every time at runtime. Either a command line tool, or an optional argument at runtime would be helpful.
line 169 of mesh.js
should be
coords = elements.slice(0, 2);
instead of
coords = elements.slice(0, 1);
This is a placeholder issue for the tests needed for the work done by #66.
I'm using .mjs
in my node.js project and I import the loader with:
import OBJ from "webgl-obj-loader";
But when importing I get the error that window
is undefined in webgl-obj-loader.min.js
. I fixed it by replacing window
with: typeof window !== "undefined" ? window : global
.
I'm not sure if that is the right fix to use this project in node, I can create a PR if it's fine
I'm trying to use the downloadModels() function like this:
OBJ.downloadModels([{
obj: 'model/test.obj',
mtl: true
}]).then(function(result){console.log("success")}, function(err){console.log("error")});
The files are actually successfully requested to the server but nothing is ever printed to the console.
What am I doing wrong?
There are a few utility functions, like Ajax, etc that need to be extracted into its own module. The each() function can probably be removed in favor of ES6's iterators and builtin forEach().
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.