Discussion on adding a 3D Model class to pyglet

639 views
Skip to first unread message

Benjamin Moran

unread,
May 29, 2017, 11:38:12 PM5/29/17
to pyglet-users
Hi all,

This is one thing that was often talked about in the past, but noone ever got around to implementing. It would be great to implement for some future release.
I've done some tinkering around with this, and after some thought I think I have a decent idea on how it might fit in. (I'm going with the working name "model" for the module, but name suggestions are welcome!).

Creating a 3D models would be different from Sprites, since it involves loading one or more files from disk. For this reason, it seems to me that it makes the most sense to shape this this after the current "image" module.  Just as there are different codecs for handling different image formats, we would have different parsers for a few different 3D model formats. You would do something like:
my_model = pyglet.model.load("thing.obj")
The file extension would be used to determine which parser to use, just as the image module does. (There is already some example code in /contrib for loading obj files, so a parser would be easy to create). Extending pyglet.resource to use this loader would be trivial.

The main thing to do is to figure out internal classes for the abstract representation of the data. For example, instead of ImageData that's returned from the image codecs, we would have VertexData, MaterialData, etc. The 3D model class would constructed from this, in the same way the Sprite class is constructed from an image and positional data.

I'd love to hear feedback on this.
-Ben

Richard Jones

unread,
May 29, 2017, 11:43:20 PM5/29/17
to pyglet-users
+1 to make life easier, since OBJ is something I carry around between projects. As long as the implementation has batch support :-)

Benjamin Moran

unread,
May 30, 2017, 12:10:28 AM5/30/17
to pyglet-users
Thanks Richard,

Batch support is definite. I actually hacked up a Sprite-module-like class based off of the /contrib code, which included both batch support as well as a direct Model.draw() method for people who like slow code :)

Since you're here, what are your thoughts on projection? For my personal projects I have 2D and 3D fixed resolution viewport classes, which maintain aspect ratio on resizing. These are similar to the examples/fixed_resolution.py file. I gather from reading old discussions that something like this may have been planned for inclusion at some point.

-Ben

Richard Jones

unread,
May 30, 2017, 1:07:17 AM5/30/17
to pyglet-users
Hi Ben,

That's great to hear.

Projection (or rather, getting my model positioned and view configured to display the model on screen ;-) is something that frequently stumps me when I go back into OBJ modelling each time. It'd be awesome if there was a reasonable default 3D projection (with an extended one that had some view controls would be super). Having that code be highly modular and easy to read would be a boon for newcomers.


     Richard

--
You received this message because you are subscribed to the Google Groups "pyglet-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyglet-users+unsubscribe@googlegroups.com.
To post to this group, send email to pyglet...@googlegroups.com.
Visit this group at https://groups.google.com/group/pyglet-users.
For more options, visit https://groups.google.com/d/optout.

Benjamin Moran

unread,
May 30, 2017, 2:08:56 AM5/30/17
to pyglet-users
I use these clases here for my personal 2D and 2.5D (3D, but only ever viewed from straight on) projects:
https://bitbucket.org/snippets/HigashiNoKaze/7ndxM

It might work to have a Projection class with set and unset methods, which could be passed to the Window. This could be called automatically before and after draw. One issue is that sometimes you might want to reset this stuff during a draw call, such as for doing a 2D hud over a 3D background... I'm not sure of the best way to handle it, but I'll probably start by adding more extensive "camera" controls to my existing class, to use standalone.

As for the actual 3D model transformations, I suppose it makes the most sense to put the transform calls inside a ModelGroup (based on how the Sprite class does it with SpriteGroup). This would allow setting any transform variables (x, y, z) on the model, and having it handled when the Group sets the state.
It would be foolish to try to recalculate all of the Model's vertex lists to move it, but it might be useful to have a base offset parameter for when the image is loaded. This would allow loading in multiple models that are all based around 0, 0, 0, but you want to situate at different positions within the scene.




On Tuesday, May 30, 2017 at 2:07:17 PM UTC+9, Richard Jones wrote:
Hi Ben,

That's great to hear.

Projection (or rather, getting my model positioned and view configured to display the model on screen ;-) is something that frequently stumps me when I go back into OBJ modelling each time. It'd be awesome if there was a reasonable default 3D projection (with an extended one that had some view controls would be super). Having that code be highly modular and easy to read would be a boon for newcomers.


     Richard
On 30 May 2017 at 14:10, Benjamin Moran <benmo...@gmail.com> wrote:
Thanks Richard,

Batch support is definite. I actually hacked up a Sprite-module-like class based off of the /contrib code, which included both batch support as well as a direct Model.draw() method for people who like slow code :)

Since you're here, what are your thoughts on projection? For my personal projects I have 2D and 3D fixed resolution viewport classes, which maintain aspect ratio on resizing. These are similar to the examples/fixed_resolution.py file. I gather from reading old discussions that something like this may have been planned for inclusion at some point.

-Ben



On Tuesday, May 30, 2017 at 12:43:20 PM UTC+9, Richard Jones wrote:
+1 to make life easier, since OBJ is something I carry around between projects. As long as the implementation has batch support :-)

--
You received this message because you are subscribed to the Google Groups "pyglet-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyglet-users...@googlegroups.com.

Richard Jones

unread,
May 30, 2017, 2:39:12 AM5/30/17
to pyglet-users
On 30 May 2017 at 16:08, Benjamin Moran <benmo...@gmail.com> wrote:
I use these clases here for my personal 2D and 2.5D (3D, but only ever viewed from straight on) projects:
https://bitbucket.org/snippets/HigashiNoKaze/7ndxM

It might work to have a Projection class with set and unset methods, which could be passed to the Window. This could be called automatically before and after draw. One issue is that sometimes you might want to reset this stuff during a draw call, such as for doing a 2D hud over a 3D background...

Modern Python techniques suggest a context manager (or set of related context managers that could be used individually or combined) that pushes/pops state :-)

 
As for the actual 3D model transformations, I suppose it makes the most sense to put the transform calls inside a ModelGroup (based on how the Sprite class does it with SpriteGroup). This would allow setting any transform variables (x, y, z) on the model, and having it handled when the Group sets the state.
It would be foolish to try to recalculate all of the Model's vertex lists to move it, but it might be useful to have a base offset parameter for when the image is loaded. This would allow loading in multiple models that are all based around 0, 0, 0, but you want to situate at different positions within the scene.

Perhaps attach some GLSL to the model to handle transformation? ModelGroup etc. then just loads the vertices etc. and manages the GLSL variables.


     Richard

Benjamin Moran

unread,
May 30, 2017, 3:27:07 AM5/30/17
to pyglet-users
Modern Python techniques suggest a context manager (or set of related context managers that could be used individually or combined) that pushes/pops state :-)

Indeed, I currently use them as a context manager myself, which you've probably seen from the __enter__/__exit__ methods in the classes. In any case, I think this is something that can get sorted out after the model stuff is in.

Perhaps attach some GLSL to the model to handle transformation? ModelGroup etc. then just loads the vertices etc. and manages the GLSL variables.

I was thinking of just using legacy OpenGL transforms for the time being on the Model class, since I'm not familar with 2.X era GLSL. That said, I do have another branch in which I've been experimenting with re-writing pyglet's core to be based on OpenGL 3.3+. So far I have the image and graphics modules ported, and simple Shader/ShaderProgram classes.  It would be easy enough to update the ModelGroup at a later date when we decide to tackle that update... That's an entirely different discussion!

Benjamin Moran

unread,
May 31, 2017, 4:03:02 AM5/31/17
to pyglet-users
I quickly mocked something up that's based on the image module. One thing I'm not sure about is how to handle the API for passing in batches.

The image module is:
image = pyglet.image.load("image.png")
# and:
image
= pyglet.resource.image("image.png")

I currently doing this for the new model module:
teapot = pyglet.model.load("teapot.obj", batch=batch)
# and:
teapot
= pyglet.resource.model("teapot.obj", batch=batch)

Instead of an Image, you'll get a Model instance back. This instance will have similar methods to the Sprite class, as much is appropriate.
Does that look reasonable?

-Ben

Richard Jones

unread,
May 31, 2017, 7:23:57 PM5/31/17
to pyglet-users
LGTM

--
You received this message because you are subscribed to the Google Groups "pyglet-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyglet-users+unsubscribe@googlegroups.com.

Benjamin Moran

unread,
Jun 4, 2017, 11:16:23 AM6/4/17
to pyglet-users
I hacked on this a bit more, and basically have a working implementation now. It's structured pretty much like the image module, which I think makes the most sense after all. There is a single codec, which is  wavefront (obj) decoder based on the pyglet/contrib/model code. It works, but needs major cleanup.

Richard, what would you say are vital method to have on the Model class? So far, I have a draw method (which people shouldn't use anyway), and an update method which allows shifting the model on one of the x, y, z axis (requiring lots of list slicing). Any thoughts on what methods would be most important to add?  My personal use case is mainly for static background objects, so I'm not the best judge in this case!
LGTM

To unsubscribe from this group and stop receiving emails from it, send an email to pyglet-users...@googlegroups.com.

magu...@gmail.com

unread,
Jun 4, 2017, 5:24:46 PM6/4/17
to pyglet-users
How easy is it to edit the loaded vertex data and attributes, and can you create an empty model instance in memory to fill with data (or by passing an existing array/attributes in memory) as opposed to loading an existing model file?

Benjamin Moran

unread,
Jun 4, 2017, 11:21:26 PM6/4/17
to pyglet-users
Good questions. Currently, the constructor/initializer takes a list of meshes, which contain one or more lists of vertex data and their associated group. After initialization, the model instance is left with a vertex_lists attribute, which contains a list of pyglet vertex lists. Passing a list of meshes is perhaps too specific to the .obj format, so maybe there should be a generic intermediate format. Or, perhaps the initilizer should just take pyglet vertex lists.

As for editing the Model:
The Model class itself is just a container for one or more related pyglet vertex lists, which you can add/remove if you like. The class should have methods that work on these lists as a group, which is what I need feedback on.

You can find my branch here:  https://bitbucket.org/HigashiNoKaze/pyglet/src/cd6151730e5611f022ef590129820b2abab01a05/?at=3dmodel
It's just a crude mockup, but it does work.

Richard Jones

unread,
Jun 5, 2017, 7:53:11 PM6/5/17
to pyglet-users
On 5 June 2017 at 01:16, Benjamin Moran <benmo...@gmail.com> wrote:
I hacked on this a bit more, and basically have a working implementation now. It's structured pretty much like the image module, which I think makes the most sense after all. There is a single codec, which is  wavefront (obj) decoder based on the pyglet/contrib/model code. It works, but needs major cleanup.

Richard, what would you say are vital method to have on the Model class? So far, I have a draw method (which people shouldn't use anyway), and an update method which allows shifting the model on one of the x, y, z axis (requiring lots of list slicing). Any thoughts on what methods would be most important to add?  My personal use case is mainly for static background objects, so I'm not the best judge in this case!

ISTM that gross operations on the model (transformations on all vertices like the translation - I think that's what you mean by "shifting the model") should be handled entirely by a shader, and no actual vertex data manipulation, since setting the shader variable will be infinitely faster.


     Richard

Benjamin Moran

unread,
Jun 6, 2017, 3:29:44 AM6/6/17
to pyglet-users
 
ISTM that gross operations on the model (transformations on all vertices like the translation - I think that's what you mean by "shifting the model") should be handled entirely by a shader, and no actual vertex data manipulation, since setting the shader variable will be infinitely faster.


     Richard

Yes, sorry, I do mean translation. And you're absolutely right that it's silly to do these types of transformations on the CPU in a realtime application.
I was mainly thinking that it's useful to have transform methods to reposition static objects in the scene when you first load them.
I think the only possibilities are passing arguments to the pyglet.model.load function, or doing it right after loading. If you do it after loading, the following three methods should cover most bases:
Model.update(x, y, z)     # Translate on a specific axis.
Model.scale(1.0)          #  Rescale the entire model.
Model.rotate(x, y, z)     #  Rotate along one or more axis.

This would come with a big fat warning about not doing this every frame, and of course using shaders is going to be necessary for most things.
Does that sound reasonable?

Tristam MacDonald

unread,
Jun 6, 2017, 10:45:13 AM6/6/17
to pyglet-users
I'm not sure it's worthwhile to include *at all*. What's the advantage of doing that, versus transforming the model on the GPU?

Matrix * vector operations in the vertex shader are really cheap, and most programs are limited by the fragment shader performance.

The only case where this might be a win is if you are assembling a level from singular geometries at runtime. Which seems a vanishingly unlikely case - generally you would assemble static elements in your editor, and then add multiple copies of props, etc at runtime.

Benjamin Moran

unread,
Jun 6, 2017, 9:12:12 PM6/6/17
to pyglet-users
Thanks for your feedback Tristam. I actually do agree with both of you guys that this is GPU/shader territory.

I am mainly looking at it from the viewpoint of a user thats using Pyglet 1.3, and has little or no OpenGL knowledge.
For example, I have a little side-scrolling shoot-em-up game I made to play around with projection and "2.5D" style side scrolling. Lets say I have a single asteroid model that I want to place in the background at various random positions and rotations. Having a few transform methods would let you randomly place them at runtime without needing to create a full scene in an editor.

That's basically it. Do you think it would harmful to include transform methods, in the sense that we would be giving users tools that they probably shouldn't really be using anyway?

Tristam MacDonald

unread,
Jun 6, 2017, 9:19:31 PM6/6/17
to pyglet-users
I think it's going to end up actively harmful.

We need to give them the tools to do GPU transforms anyway (a class for placing models in the scene, default uniforms for the transform matrices, and a default vertex shader), at which point having methods to also pre-transform models on the CPU are redundant and/or confusing.

Richard Jones

unread,
Jun 6, 2017, 9:34:31 PM6/6/17
to pyglet-users
There absolutely has to be a default vertex and fragment shader with this implementation, yep.

To unsubscribe from this group and stop receiving emails from it, send an email to pyglet-users+unsubscribe@googlegroups.com.

To post to this group, send email to pyglet...@googlegroups.com.
Visit this group at https://groups.google.com/group/pyglet-users.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "pyglet-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyglet-users+unsubscribe@googlegroups.com.

Benjamin Moran

unread,
Jun 6, 2017, 11:29:54 PM6/6/17
to pyglet-users
OK, loud and clear. I won't waste effort on transform methods.

Another question is what types of codecs we should try to include other than obj, and who wants to write them? :)

Greg Ewing

unread,
Jun 7, 2017, 2:00:57 AM6/7/17
to pyglet...@googlegroups.com
Benjamin Moran wrote:
> I am mainly looking at it from the viewpoint of a user thats using
> Pyglet 1.3, and has little or no OpenGL knowledge. ... Lets say I
> have a single asteroid model that I want to place in the background at
> various random positions and rotations. Having a few transform methods
> would let you randomly place them at runtime without needing to create a
> full scene in an editor.

It would be much better for Pyglet to provide a general mechanism
for applying transformations at rendering time, maybe something like
the matrix stack in OpenGL 2.

--
Greg

DR0ID

unread,
Jun 7, 2017, 11:08:19 AM6/7/17
to pyglet...@googlegroups.com

Hi there

Not sure if you would like an external dependency or not, but there is assimp, see

http://www.assimp.org/index.html

It loads various formats to the same structure so the code will only have to worry about one format internally (I haven't used it yet, but probably will try it out in future).

And I don't see the point to write your own codecs if some one else already has gone through the trouble making such a library.

But sure, pyglet could focus on just one or few formats and that would be probably enough (since there are other ways to convert a model to the supported format). I would like a format where one can define bones and animations too. But that is just my wish.

Keep up the good work.

~DR0ID


Tristam MacDonald

unread,
Jun 7, 2017, 11:29:11 AM6/7/17
to pyglet...@googlegroups.com
Gltf would be a natural choice, in many ways:

https://github.com/KhronosGroup/glTF

It's an open interchange format, with some degree of tool support (and very easy to write converters for).

Steve Johnson

unread,
Jun 7, 2017, 12:07:46 PM6/7/17
to pyglet-users
I question the idea of including any of this stuff in pyglet. It is already a large library.

Why not start by creating a third party module, letting it stabilize on its own, and rolling it into pyglet when it has proved its usefulness and quality?

Honestly, if I were designing pyglet from scratch, I would create four separate libraries. Dependency management and app packaging in the Python ecosystem are not as hard as they used to be.

Tristam MacDonald

unread,
Jun 7, 2017, 1:11:26 PM6/7/17
to pyglet-users
Yeah, that's fair. Maybe it's time that pyglet became a collection of libraries.

On the other hand, we do need to overhaul pyglet itself to provide all the modern OpenGL primitives. And those primitives aren't very useful to newcomers without a high-level abstraction over models/scenes...

Maybe go the other direction. Produce a pyglet-core with just the OpenGL primitives, and make pyglet itself a meta-package over pyglet-core, pyglet-scene, etc?

Steve Johnson

unread,
Jun 7, 2017, 1:36:43 PM6/7/17
to pyglet-users
YES! As I was typing my last email I was considering breaking it down explicitly like that, but decided to be vague instead.

pyglet_core (gl, window, canvas, no dependencies)
pyglet_utils (event, clock, no dependencies)
pyglet_media (media)
pyglet_graphics (graphics)
pyglet_drawing (sprite, text)
pyglet_assets (resource, image)
pyglet_input
pyglet_transforms??
pyglet_models??

And then tie it all together with the pyglet superpackage, which has pyglet.app.

You could also split the maintainer responsibility up across modules, version them separately, and have clear API touch points between them. They could remain in the same repo to keep things simple. The docs could be unified, or split up and linked using intersphinx, with the high level guides living in the main pyglet repo. (Reading back over this paragraph, though, that seems like too much overhead for the number of people on this project.)

The split would solve a problem I had recently: if you want to use pyglet just for audio (in this case I was doing my graphics with BearLibTerminal), you have to do some pyglet.options voodoo. I'd rather just import pyglet_audio. It's the nicest way to do audio in Python by far.

Richard Jones

unread,
Jun 7, 2017, 7:09:20 PM6/7/17
to pyglet-users
Careful, folks. Please don't kill off this actually very useful contribution to pyglet by sidetracking it into a massive (unnecessary, bordering on harmful in my opinion) refactoring.


     Richard

To unsubscribe from this group and stop receiving emails from it, send an email to pyglet-users+unsubscribe@googlegroups.com.

Steve Johnson

unread,
Jun 7, 2017, 7:10:53 PM6/7/17
to pyglet-users
Sure, but my point stands about needlessly adding new stuff to an already-big library when it would work 100% as well as a third party library.

Benjamin Moran

unread,
Jun 7, 2017, 11:47:38 PM6/7/17
to pyglet-users
I think as one of the "pyglet elders", Richard gets two votes here :) 
I believe that generic 3D model support, and a user-friendly way to set 2D and 3D projections are two of the last things missing from pyglet.

Splitting pyglet into seperate modules at this point is probably not a good idea due to the aforementioned number of contributors. It's a discussion best left for the future when we're migrated to GL3+/Python3, and possibly pick up a few active contributors. In the meantime, to Steve's point, I think we can definitely investigate tweaks to make pyglet's modules more usable by themselves. I've seen others with similar complaints.

Regarding avoiding bloat, I think the basic classes and loading mechanisms are important. The codecs themselves are a different story, and I agree that we shouldn't try to support too much. We have good mechanisms for adding codecs later, just like the image module:
pyglet.model.codecs.add_decoders(MyFormatDecoder())
model
= pyglet.model.load("mymodel.xyz")

One or two generic decoders are probably a good idea. Obj seems a no-brainer.
Greg, I like the glTF format. I forgot all about that one. It seems like there are plenty of tools to convert to it, and it's royalty free.

Tristam MacDonald

unread,
Jun 7, 2017, 11:54:36 PM6/7/17
to pyglet-users
If you need a hand with glTF, give me a shout. I've writting a couple of implementations in my day :)

Richard Jones

unread,
Jun 8, 2017, 1:09:17 AM6/8/17
to pyglet-users
On 8 June 2017 at 13:47, Benjamin Moran <benmo...@gmail.com> wrote:
I think as one of the "pyglet elders", Richard gets two votes here :) 
I believe that generic 3D model support, and a user-friendly way to set 2D and 3D projections are two of the last things missing from pyglet.

Splitting pyglet into seperate modules at this point is probably not a good idea due to the aforementioned number of contributors. It's a discussion best left for the future when we're migrated to GL3+/Python3, and possibly pick up a few active contributors.

I would caution against overloading the GL3+ migration (I regret mentioning Python 3, I shouldn't have confused the scope of the work like that).

 
Regarding avoiding bloat, I think the basic classes and loading mechanisms are important. The codecs themselves are a different story, and I agree that we shouldn't try to support too much. We have good mechanisms for adding codecs later, just like the image module:
pyglet.model.codecs.add_decoders(MyFormatDecoder())
model
= pyglet.model.load("mymodel.xyz")

One or two generic decoders are probably a good idea. Obj seems a no-brainer.

+1


    Richard

Benjamin Moran

unread,
Jun 8, 2017, 10:29:05 AM6/8/17
to pyglet-users
Tristam,

That would be fantastic. I'll get my work pushed to a branch on bitbucket once I have a chance to clean it up a little bit, so you can see how it's structured. If you want to start with a general parser, it'll be trivial to turn it into a codec.

So far, I have the following design points (which we can change as appropriate of course):
  • The Model class is not fleshed out, and is little more than a container for vertex lists. We can add approprite methods, reprs, etc. later.
  • The Models always uses a Batch. If none is passed in to model.load(), the codec will create it's own batch and use that when making it's vertex lists. (This is how the text module does it).
  • There are two possible Groups that the codecs use, depending on the mesh's material - TexturedModelGroup, and ModelGroup.

Benjamin Moran

unread,
Jun 8, 2017, 10:29:46 AM6/8/17
to pyglet-users
Caution noted, Richard!

Tristam MacDonald

unread,
Jun 8, 2017, 11:16:20 AM6/8/17
to pyglet...@googlegroups.com
What is the plan for handling files that contain multiple "sub-models" (for lack of a better term)? it's not unusual for 3D meshes to be segmented, and result in quite a few models at runtime

Benjamin Moran

unread,
Jun 8, 2017, 11:46:36 AM6/8/17
to pyglet-users
Other modules support loading resources from either a file object or just a filename, which the model one does as well.

The obj codec (so far) uses the os module to find the base path of the file object, and locates the other material and image files that way.

There might be some hiccups that will pop up once trying to use the resource module, but nothing we can't solve. Any suggestions welcome, as always.

Benjamin Moran

unread,
Jun 18, 2017, 10:29:42 PM6/18/17
to pyglet-users
I still plan on merging in the basic framework for Models, but first I'm going over Steve's work on the documentation.

Regarding loading the files, I realize we'll have to do something regarding binary versus ascii formats. My initial thinking is that we should default to loading as binary for everything, and just decode to ascii inside the ModelDecoders if necessary. This would prevent a bit of waste inside the load and resource methods.

Nick Del Grosso

unread,
Jun 28, 2017, 4:35:32 AM6/28/17
to pyglet...@googlegroups.com
Hi all,

The ratcave package I wrote (https://github.com/neuroneuro15/ratcave) and use in my virtual reality research is exactly this.  


Best wishes,

Nick

--
You received this message because you are subscribed to the Google Groups "pyglet-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyglet-users+unsubscribe@googlegroups.com.

Benjamin Moran

unread,
Jun 29, 2017, 3:06:23 AM6/29/17
to pyglet-users
Hi Nick,

I was browsing through your code, and it looks like a nice project.




On Wednesday, June 28, 2017 at 5:35:32 PM UTC+9, Nick Del Grosso wrote:
Hi all,

The ratcave package I wrote (https://github.com/neuroneuro15/ratcave) and use in my virtual reality research is exactly this.  


Best wishes,

Nick
On Mon, Jun 19, 2017 at 4:29 AM, Benjamin Moran <benmo...@gmail.com> wrote:
I still plan on merging in the basic framework for Models, but first I'm going over Steve's work on the documentation.

Regarding loading the files, I realize we'll have to do something regarding binary versus ascii formats. My initial thinking is that we should default to loading as binary for everything, and just decode to ascii inside the ModelDecoders if necessary. This would prevent a bit of waste inside the load and resource methods.



On Friday, June 9, 2017 at 12:46:36 AM UTC+9, Benjamin Moran wrote:
Other modules support loading resources from either a file object or just a filename, which the model one does as well.

The obj codec (so far) uses the os module to find the base path of the file object, and locates the other material and image files that way.

There might be some hiccups that will pop up once trying to use the resource module, but nothing we can't solve. Any suggestions welcome, as always.

--
You received this message because you are subscribed to the Google Groups "pyglet-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyglet-users...@googlegroups.com.

Nick Del Grosso

unread,
Jul 6, 2017, 10:36:19 AM7/6/17
to pyglet...@googlegroups.com
Hi Benjamin,

Thank you for the compliment!

Best wishes,
NIck

To unsubscribe from this group and stop receiving emails from it, send an email to pyglet-users+unsubscribe@googlegroups.com.

Benjamin Moran

unread,
Jul 11, 2017, 4:24:15 AM7/11/17
to pyglet-users
As a follow up Nick,

You've recreated a lot of things that will potentially end up in pyglet core at some point. This is more related to the other thread about an eventual move of the pyglet codebase to GL3+. It looks like we can leverage most of the existing pyglet.graphics module when we move forward with that, so it makes sense for the Model framework to use the existing API for a start.

I see that you've written a nice obj loader, which is a lot cleaner than the quick one I've hacked together :)

Nick Del Grosso

unread,
Jul 18, 2017, 3:08:42 AM7/18/17
to pyglet...@googlegroups.com
Hi Benjamin, 

That makes sense. Thank you for taking a look at ratcave! 

Best wishes, 

Nick 

To unsubscribe from this group and stop receiving emails from it, send an email to pyglet-users+unsubscribe@googlegroups.com.

Benjamin Moran

unread,
Feb 2, 2018, 10:01:02 AM2/2/18
to pyglet-users
Hi everyone,

I know this has been quiet for a while, but I figured it was a good time to think about merging in the basic framework for the model class. I think this work gets a lot more interesting with GL3+, but at least we can get some things worked out in the mean time. You can find my pull request here, and feedback would be greatly appreciated:
https://bitbucket.org/pyglet/pyglet/pull-requests/108/3dmodel/diff

This consists of a new pyglet.model module. The structure is very similar to pyglet.image. There is also a single codec for obj files, which was based on some older /contrib code. This codec is crude and unfinished, but works well enough for a placeholder.

The pyglet.model.__init__ file contains the new `Model` class, as well as two Groups (for textured, or non-textured meshes). The main thing we need to flesh out is the `Model` class. In particular, which attributes we need to consider. Currently there is a `vertex_list_map`, which contains a mapping of the vertex lists and which Groups they are using (as some models have multiple meshes with different properties).

I'm thinking at the least we should add an `add_to_texture_bin` method, similar to Animations. This would also be useful for the resource module, so models loaded through there could optionally be added to the interal resource module texture bins (as Animations can be).

I'm not an expert on these things, so any feedback is appreciated!

-Ben

Nick Del Grosso

unread,
Feb 3, 2018, 3:58:54 AM2/3/18
to pyglet...@googlegroups.com
Hi, 

In response to this addition,  I'd like to recommend my 3d model package Ratcave again as an extension package for Pyglet and Pygame users. It has been quite improved since I last suggested it on this mailing list, with a cleaner interface and more tests. It uses modern opengl and shaders to stay performant, and it works as a drop-in extension to any opengl context. Models are drawn with draw(), cameras, lights, shaders, etc. use context managers, which keep things cclean-lookin, and it also includes an OBJ file parser. Finally, deferred rendering is made simple with context manager FBOs and Textures, which has made it an effective teaching tool for shaders. 



For simple games and apps, it has been more than enough.  There's certainly still room for improvement, of course. Any contributions and suggestions are welcome! 

Best wishes, 

Nick 

To unsubscribe from this group and stop receiving emails from it, send an email to pyglet-users+unsubscribe@googlegroups.com.

Benjamin Moran

unread,
Feb 4, 2018, 9:31:00 PM2/4/18
to pyglet-users
Hi Nick,

Firstly, nice progress you've made. I would be happy to add your library to the projects section in the documentation:  https://pyglet.readthedocs.io/en/latest/index.html#projects-using-pyglet
Just let me know the description and preferred link, and I'll add it in. It's not much, but we don't have a proper website at the moment.

About this model module, it's mainly just about getting the abstractions right, such as what attributes make sense to expose. We should also ensure the codec system makes sense for adding additional model parsers. Similar to the Sprite class in scope.

As you might know we are planning to move pyglet's core to GL3+ in the future. I would be very interested in talking with you regarding this work. Some necessary internal classes for supporting everything are necessary, such as shader/shader program abstractions. These are duplicated in projects like yours, but in the future it would be nice to ensure the built-in classes are useful by other projects as well. The current rough implementation of the shader module for example, is here: https://bitbucket.org/HigashiNoKaze/pyglet/src/aec97ee54c670ce983041b39284b9794f78ceac0/pyglet/graphics/shader.py?at=shaders&fileviewer=file-view-default

Nick Del Grosso

unread,
Feb 5, 2018, 6:08:31 AM2/5/18
to pyglet...@googlegroups.com
Hi Benjamin,

No problem, I understand.  Any way I can contribute would be great!  I'll also look at using your Shader implementation in ratcave (no need to reinvent the wheel and all, and I think your implementation is very well done!); in either case, ratcave doesn't rely on a given shader implementation--it just catches the OpenGl error if a shader isn't bound when it tries to send uniforms--so any user that wants to mix and match packages won't have any problems.

And thank you for offering to add the project on the Pyglet page, that would be great!  

Title: Ratcave: A Simple Python 3D Graphics Engine extension for Pyglet, Psychopy, and PyGame.
Description: Ratcave provides a simple OOP interface for loading, positioning, and drawing 3D scenes in OpenGL windows.  It's a great fit for simple games and scientific behavioral experiments!

Best wishes,

Nick


To unsubscribe from this group and stop receiving emails from it, send an email to pyglet-users+unsubscribe@googlegroups.com.

Benjamin Moran

unread,
Feb 6, 2018, 9:56:46 AM2/6/18
to pyglet-users
Hi Nick,

I've added that description/link to the docs: https://pyglet.readthedocs.io/en/latest/index.html#third-party-libraries
If you could give the Shader classes a try, that would be great. They have only really been tested with simple things that pyglet needs internally, so not all types are covered yet.
Also, the code for setting/getting of Uniforms and UniformBufferObjects/UniformBlocks could definiltly use a review by someone who's better at this stuff than I am. Any feedback or suggestions would be most appreciated.

Benjamin Moran

unread,
Feb 6, 2018, 10:09:05 AM2/6/18
to pyglet-users
Back to the pyglet.model module, I've been playing with some things in order to find out a generic way to structure the base classes. I ended up with "Material" and "Mesh" classes. The Mesh class contains vertex points and one (on none) Material attributes. The Model class is passed a list of Meshes, which are then finally turned into pyglet vertex lists on instantiation. It's probably easiest to understand just by looking at the code in the pull request:   https://bitbucket.org/pyglet/pyglet/pull-requests/108/3dmodel/diff
We essentially end up with one Group per mesh in the Model class, but these groups will be consolidated if possible when adding to the Batch.

I'm not 100% sure if this is flexible enough to handle the needs of other formats besides obj, so hopefully someone can comment here.
Perhaps writing an additional decoder for another format will make this clear.

For the Model class, it will need a smooth mechanism for updating it's Groups. Models will tend to have multiple groups if they are complex, and in the future a Group can contain a Shader. Having an easy way to view and change these seems important.

Benjamin Moran

unread,
Mar 16, 2018, 9:37:02 AM3/16/18
to pyglet-users
I started hacking on a basic glTF codec, and it became apparent that the Model decoders themselves are probably better off forming the vertex lists internally, rather than the Model doing it in it's __init__ method.  The main reason is that with formats such as glTF, the data is already stored as byte arrays. It would be nice to be able to copy this data directly over into the GL buffers as intended, rather than unpacking them into lists first.

It seems to be now that the main thing to start with is that the Model class has dictionaries to map the Group/vlists/textures together. This will allow you to load a model, and then easily acces it to change any Groups or vlists you need to. This should be a good base, and leave things open for the future.

Neon22

unread,
May 14, 2018, 5:31:22 PM5/14/18
to pyglet-users
I'd like to suggest that the numbering of vertices is maintained through the importer. This enables morphing from one shape to another by simply transforming each vertex position from its original to a second position.

I.e. Two models with identical vertex numbering are created in external s/w and saved (as obj for now).
They both have same topology but the vertices are in different positions (e.g. two positions of a heart beating).
These two models are saved. One is loaded as the model.
The second is loaded as a morph target and only the verts are loaded. (more than one can be loaded for more complex morphs)
As long as vertex numbering (order) is maintained in the loader then morphing becomes possible.

Later:
If a normalised 3d vector is calculated, and stored on load, instead of just the new vertex positions then this describes the difference between the base(first loaded model) and a target shape.
This means the base can be transformed to a fraction of that shape (even a negative amount) and many shapes can be blended to make more complex and sophisticated effects.
E.g. A head with face shapes for smile, mouth open, pout can be mixed to make simple talking head animations.
But first we have to preserve vertex order on load.

Benjamin Moran

unread,
May 15, 2018, 3:27:39 AM5/15/18
to pyglet-users
Hi Neon22,

The obj importer creates the vertices in the order which they're defined in the obj file, so this should be fine.
 
I'm thinking we will want to have some type of Animation class at some point. glTF files in particular can include animation data as part of the format. A potential Animation class should be generic enough to be populated with this type of data, as well as allow someone to create their own.

Benjamin Moran

unread,
Jul 26, 2018, 8:21:01 AM7/26/18
to pyglet-users
Hi everyone,

I finally got back to working on the GLTF decoder, it's it's just about done. I have a few more things to finish up after that, and I can merge this in. Tests also need to be written as well. Writing the GLTF decoder has clarified a few things, so I'm feeling fairly happy about it. It will be a fairly simple implementation to start, but things can be expanded in the future as we move to GL3+ (which I've also been working on :)  ).


On Tuesday, May 30, 2017 at 12:38:12 PM UTC+9, Benjamin Moran wrote:
Hi all,

This is one thing that was often talked about in the past, but noone ever got around to implementing. It would be great to implement for some future release.
I've done some tinkering around with this, and after some thought I think I have a decent idea on how it might fit in. (I'm going with the working name "model" for the module, but name suggestions are welcome!).

Creating a 3D models would be different from Sprites, since it involves loading one or more files from disk. For this reason, it seems to me that it makes the most sense to shape this this after the current "image" module.  Just as there are different codecs for handling different image formats, we would have different parsers for a few different 3D model formats. You would do something like:
my_model = pyglet.model.load("thing.obj")
The file extension would be used to determine which parser to use, just as the image module does. (There is already some example code in /contrib for loading obj files, so a parser would be easy to create). Extending pyglet.resource to use this loader would be trivial.

The main thing to do is to figure out internal classes for the abstract representation of the data. For example, instead of ImageData that's returned from the image codecs, we would have VertexData, MaterialData, etc. The 3D model class would constructed from this, in the same way the Sprite class is constructed from an image and positional data.

I'd love to hear feedback on this.
-Ben

Benjamin Moran

unread,
Jul 26, 2018, 8:26:27 AM7/26/18
to pyglet-users
Just to add, the final design of the `pyglet.model` module is very similar to `pyglet.image`, in that you can do `pyglet.model.load('file.gltf', batch=optional_batch)`. The pyglet.resource module also has `pyglet.resource.model(file, batch)`.  In additional, the `model` module uses the same `codec` design that the image and media modules do. This means anyone can write a decoder for specific format, and add it at runtime with `pyglet.model.add_decoders(module)`.

Benjamin Moran

unread,
Aug 15, 2018, 8:41:51 PM8/15/18
to pyglet-users
I merged in an initial version of thid work. Feedback would be great, if you see something really wrong!

The classes are all pretty limited, with the idea that it can be expanded for the upcoming GL3 release where appropriate.

A transform matrix can be set after loading. Matrix Multiplication currently takes place in the Groups, and will be done in a Shader in the pyglet 2/3 release.

Richard Jones

unread,
Aug 19, 2018, 8:35:12 PM8/19/18
to pyglet-users
\o/ (not that I'm in a position to really kick the tyres on this one at the moment, but it's great to see this land)

--
You received this message because you are subscribed to the Google Groups "pyglet-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyglet-users+unsubscribe@googlegroups.com.

Benjamin Moran

unread,
Aug 19, 2018, 9:45:41 PM8/19/18
to pyglet-users
Thanks Richard.

I decided to merge this without enabline the glTF decoder, but the obj decoder should be complete.

For glTF, I ran into some issues with how to fit some of the file specifications into the current GL2 capabilities. In particular, how to deal with materials (since glTF files are based around PBR). The decoder is there and just about usable otherwise, but I did not include it in the default_codecs list yet.  If anyone is knowledgable about glTF and would like to help get it in order, let me know!




On Monday, August 20, 2018 at 9:35:12 AM UTC+9, Richard Jones wrote:
\o/ (not that I'm in a position to really kick the tyres on this one at the moment, but it's great to see this land)
On 16 August 2018 at 10:41, Benjamin Moran <benmo...@gmail.com> wrote:
I merged in  an initial version of thid work. Feedback would be great, if  you see something really wrong!

The classes are all pretty limited, with the idea that it can be expanded for the upcoming GL3 release where appropriate.

A transform matrix can be set after loading. Matrix Multiplication currently takes place in the Groups, and will be done in a Shader in the pyglet 2/3 release.

--
You received this message because you are subscribed to the Google Groups "pyglet-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyglet-users...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages