<commit_before>

Tutorials
=========

Example 1: Displaying a 3D Object
+++++++++++++++++++++++++++++++++

This tutorial will show the process of displaying a 3D object onscreen. This will be done in four steps:
  - We'll open a file containing 3D objects--a Wavefront .obj file containing basic 3D primitives that comes with ratCAVE (although you can use any .obj file outputted by 3D modeling software), 
  - We then retrieve a Mesh object from the file. Mesh objects contain all information about the object, including its position (inside its Local and World attributes), color (inside its Material attribute), and even the vertex data itself (inside its Data attribute).
  - We'll put the Mesh inside a Scene object, which is a container class that holds all meshes visible at one time, a Camera object, and a Light source object. Multiple Scenes can be created, even ones that contain the same Meshes, and rendering one vs another one is as simple as changing which Scene is the active one inside the Window.
  - Finally, we'll put the Scene inside a Window object, and render it by calling its draw() and flip() methods.



Reading a Wavefront .obj file
-----------------------------

Wavefront files can be exported from Blender, and they usually come in pairs-- a .obj file contianing the spatial vertex data for each mesh, and a .mtl file containing the coloring data for each mesh.  In ratCAVE, .obj files are summarized in the MeshData class and .mtl files are summarized in the Material class.  Mesh classes wrap both of these, plus containing a bit of extra functionality for dealing with these meshes as a whole (like moving the whole thing around, rotating it, or giving it certain image textures, things like that.).  Custom MeshData and Material objects can be created, but often it is just easier to import them together in Wavefront files as Meshes.  This is the purpose of the **WavefrontReader** class.  We've included some files with primitive shapes with ratCAVE, whose paths you can find in the **graphics.resources** module, to get you started::

  from ratcave import graphics

  # Insert filename into WavefrontReader.
  obj_filename = graphics.resources.obj_primitives
  obj_reader = graphics.WavefrontReader(obj_filename)

  # Check which meshes can be found inside the Wavefront file, and extract it into a Mesh object for rendering.
  print(obj_reader.mesh_names)
  >>> ['Torus', 'Sphere', 'Monkey', 'Cube']


Creating a Mesh from the WavefrontReader and Positioning it
-----------------------------------------------------------

The same keywords used for instantiating a Mesh can be used inside the WavefrontReader.get_mesh() method.  An important keyword is **centered**--if you leave it False (it is False by default), then the Mesh will appear wherever it was in the original file, which cana be found in its local.position attribute.  This is useful when you've pre-arranged the locations of everything in a 3D modelling program, but if you'd like to explicitly set its postiion, it can be a bit confusing.  So, we set its starting position to 0,0,0 by calling centered=True.  Then, we set local.position to a locatio in front of the camera::

  monkey = obj_reader.get_mesh("Monkey")
  monkey.local.position = 0, 0, -2 


Creating a Scene<commit_msg>added links inside some tutorial<commit_after>

Tutorials
=========

Example 1: Displaying a 3D Object
+++++++++++++++++++++++++++++++++

This tutorial will show the process of displaying a 3D object onscreen. This will be done in four steps:
  - We'll open a file containing 3D objects--a Wavefront .obj file containing basic 3D primitives that comes with ratCAVE (although you can use any .obj file outputted by 3D modeling software), using the :py:class:`ratcave.graphics.WavefrontReader` class.
  - We then retrieve a :py:class:`ratcave.graphics.Mesh` object from the file. Mesh objects contain all information about the object, including its position (inside its Local and World attributes, which are :py:class:`ratcave.graphics.mixins.Physical` objects), color (inside its Material attribute, which are of the :py:class:`ratcave.graphics.Material` class), and even the vertex data itself (inside its Data attribute, which is a :py:class:`ratcave.graphics.MeshData` object).
  - We'll put the Mesh inside a :py:class:`ratcave.graphics.Scene` object, which is a container class that holds :py:class:`ratcave.graphics.Mesh` objects, a :py:class:`ratcave.graphics.Camera` object, and a :py:class:`ratcave.graphics.Light` object, along with an RGB background color. Multiple Scenes can be created, even ones that contain the same Meshes, and rendering one vs another one is as simple as changing which Scene is the active one inside the :py:class:`ratcave.graphics.Window`.
  - Finally, we'll put the Scene inside a :py:class:`ratcave.graphics.Window` object, and render it by calling its :py:meth:`ratcave.graphics.Window.draw` and :py:meth:`ratcave.graphics.Window.flip`  methods.



Reading a Wavefront .obj file
-----------------------------

Wavefront files can be exported from Blender, and they usually come in pairs-- a .obj file contianing the spatial vertex data for each mesh, and a .mtl file containing the coloring data for each mesh.  In ratCAVE, .obj files are summarized in the MeshData class and .mtl files are summarized in the Material class.  Mesh classes wrap both of these, plus containing a bit of extra functionality for dealing with these meshes as a whole (like moving the whole thing around, rotating it, or giving it certain image textures, things like that.).  Custom MeshData and Material objects can be created, but often it is just easier to import them together in Wavefront files as Meshes.  This is the purpose of the **WavefrontReader** class.  We've included some files with primitive shapes with ratCAVE, whose paths you can find in the **graphics.resources** module, to get you started::

  from ratcave import graphics

  # Insert filename into WavefrontReader.
  obj_filename = graphics.resources.obj_primitives
  obj_reader = graphics.WavefrontReader(obj_filename)

  # Check which meshes can be found inside the Wavefront file, and extract it into a Mesh object for rendering.
  print(obj_reader.mesh_names)
  >>> ['Torus', 'Sphere', 'Monkey', 'Cube']


Creating a Mesh from the WavefrontReader and Positioning it
-----------------------------------------------------------

The same keywords used for instantiating a Mesh can be used inside the WavefrontReader.get_mesh() method.  An important keyword is **centered**--if you leave it False (it is False by default), then the Mesh will appear wherever it was in the original file, which cana be found in its local.position attribute.  This is useful when you've pre-arranged the locations of everything in a 3D modelling program, but if you'd like to explicitly set its postiion, it can be a bit confusing.  So, we set its starting position to 0,0,0 by calling centered=True.  Then, we set local.position to a locatio in front of the camera::

  monkey = obj_reader.get_mesh("Monkey")
  monkey.local.position = 0, 0, -2 


Creating a Scene
{'fraction_non_alphanumeric': 0.09362717574396406, 'fraction_numerical': 0.0036496350364963502, 'mean_word_length': 3.986004198740378, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4006313', 'n_tokens_mistral': 1902, 'n_tokens_neox': 1765, 'n_words': 991}