├── minirt_converter ├── __init__.py ├── helpers.py ├── main.py └── convert.py ├── requirements_dev.txt ├── docs ├── assets │ ├── cat.png │ ├── deer.png │ ├── wolf.png │ ├── dragon.png │ └── wolf3d.png ├── index.html ├── minirt_converter.html └── minirt_converter │ ├── helpers.html │ └── main.html ├── pyproject.toml ├── .pre-commit-config.yaml ├── .gitignore ├── README.md └── LICENSE /minirt_converter/__init__.py: -------------------------------------------------------------------------------- 1 | """.. include:: ../README.md""" 2 | -------------------------------------------------------------------------------- /requirements_dev.txt: -------------------------------------------------------------------------------- 1 | bandit 2 | pdoc3 3 | pre-commit 4 | pycodestyle 5 | -------------------------------------------------------------------------------- /docs/assets/cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matboivin/minirt_mesh_converter/HEAD/docs/assets/cat.png -------------------------------------------------------------------------------- /docs/assets/deer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matboivin/minirt_mesh_converter/HEAD/docs/assets/deer.png -------------------------------------------------------------------------------- /docs/assets/wolf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matboivin/minirt_mesh_converter/HEAD/docs/assets/wolf.png -------------------------------------------------------------------------------- /docs/assets/dragon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matboivin/minirt_mesh_converter/HEAD/docs/assets/dragon.png -------------------------------------------------------------------------------- /docs/assets/wolf3d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matboivin/minirt_mesh_converter/HEAD/docs/assets/wolf3d.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /minirt_converter/helpers.py: -------------------------------------------------------------------------------- 1 | """Command line helper functions.""" 2 | 3 | from argparse import ArgumentParser, Namespace 4 | 5 | 6 | def parse_args() -> Namespace: 7 | """Parse the program's arguments. 8 | 9 | Returns 10 | ------- 11 | argparse.Namespace 12 | The program's arguments. 13 | 14 | """ 15 | parser: ArgumentParser = ArgumentParser( 16 | prog="minirt_converter", 17 | description="Convert .obj files to .rt files to render a triangle mesh " 18 | "effect for miniRT project of School 42.", 19 | ) 20 | 21 | parser.add_argument("filename", type=str, help="obj file to convert.") 22 | parser.add_argument( 23 | "color", type=str, help="the color in RGB format (e.g., 255,255,255)." 24 | ) 25 | 26 | parser.add_argument_group( 27 | "example usage", "minirt_converter file.obj 255,204,0" 28 | ) 29 | 30 | return parser.parse_args() 31 | -------------------------------------------------------------------------------- /minirt_converter/main.py: -------------------------------------------------------------------------------- 1 | """Program's entrypoint.""" 2 | 3 | from argparse import Namespace 4 | from pathlib import Path 5 | 6 | import coloredlogs 7 | from verboselogs import VerboseLogger 8 | 9 | from .convert import convert_obj_to_rt 10 | from .helpers import parse_args 11 | 12 | 13 | def main(logger: VerboseLogger, filename: Path, color: str) -> None: 14 | """Run program. 15 | 16 | Parameters 17 | ---------- 18 | logger : VerboseLogger 19 | The program's logger. 20 | filename : Path 21 | The file to convert. 22 | color : str 23 | The color of the object in RGB format. 24 | 25 | """ 26 | convert_obj_to_rt(logger, filename, color) 27 | 28 | 29 | def entrypoint() -> None: 30 | """Program's entrypoint.""" 31 | args: Namespace = parse_args() 32 | filename: Path = Path(args.filename) 33 | logger: VerboseLogger = VerboseLogger("minirt_converter") 34 | 35 | coloredlogs.install( 36 | logger=logger, 37 | level="DEBUG", 38 | fmt="[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s", 39 | ) 40 | 41 | try: 42 | main(logger, filename, args.color) 43 | except (OSError, FileNotFoundError) as err: 44 | logger.error(err) 45 | 46 | 47 | if __name__ == "__main__": 48 | entrypoint() 49 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "minirt_converter" 3 | version = "1.0.0" 4 | description = "Convert .obj files to .rt files to render a triangle mesh effect for miniRT project at 42." 5 | authors = ["mboivin "] 6 | license = "CC BY-NC 4.0" 7 | readme = "README.md" 8 | repository = "https://github.com/matboivin/minirt_mesh_converter" 9 | documentation = "https://matboivin.github.io/minirt_mesh_converter/" 10 | classifiers = [ 11 | "Intended Audience :: Developers", 12 | "Operating System :: OS Independent", 13 | "Programming Language :: Python :: 3.9" 14 | ] 15 | 16 | [tool.poetry.dependencies] 17 | python = "^3.9" 18 | coloredlogs = "^15.0.1" 19 | verboselogs = "^1.7" 20 | 21 | [tool.poetry.dev-dependencies] 22 | bandit = "^1.7.4" 23 | black = "^22.6.0" 24 | isort = "^5.10.1" 25 | pdoc = "^13.1.0" 26 | pre-commit = "^2.20.0" 27 | pycodestyle = "^2.9.1" 28 | pylint = "^2.14.5" 29 | 30 | [tool.black] 31 | line-length = 79 32 | include = '\.pyi?$' 33 | exclude = ''' 34 | /( 35 | \.git 36 | | \.hg 37 | | \.mypy_cache 38 | | \.tox 39 | | \.venv 40 | | _build 41 | | buck-out 42 | | build 43 | | dist 44 | )/ 45 | ''' 46 | 47 | [tool.mypy] 48 | pretty = true 49 | show_traceback = true 50 | color_output = true 51 | strict = true 52 | ignore_missing_imports = true 53 | allow_untyped_decorators = true 54 | allow_subclassing_any = true 55 | 56 | [tool.poetry.scripts] 57 | minirt_converter = 'minirt_converter.main:entrypoint' 58 | 59 | [build-system] 60 | requires = ["poetry-core>=1.0.0"] 61 | build-backend = "poetry.core.masonry.api" 62 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | default_language_version: 2 | python: python3.9 3 | 4 | repos: 5 | 6 | - repo: https://github.com/pycqa/isort 7 | rev: 5.10.1 8 | hooks: 9 | - id: isort 10 | args: ["--profile", "black"] 11 | 12 | - repo: https://github.com/myint/autoflake 13 | rev: v1.4 14 | hooks: 15 | - id: autoflake 16 | args: [ 17 | --in-place, 18 | --remove-unused-variables, 19 | --remove-all-unused-imports, 20 | ] 21 | 22 | - repo: https://github.com/psf/black 23 | rev: 22.6.0 24 | hooks: 25 | - id: black 26 | language_version: python3.9 27 | 28 | - repo: https://github.com/pre-commit/mirrors-mypy 29 | rev: v0.942 30 | hooks: 31 | - id: mypy 32 | 33 | - repo: https://github.com/pycqa/pydocstyle 34 | rev: 4.0.0 35 | hooks: 36 | - id: pydocstyle 37 | args: ['--ignore=D213,D203,D204,D416'] 38 | exclude: "minirt_converter/__init__.py" 39 | 40 | - repo: local 41 | hooks: 42 | - id: pycodestyle 43 | name: pycodestyle 44 | entry: pycodestyle 45 | language: system 46 | args: [ 47 | '--ignore=E722,E126', 48 | '--max-line-length=80', 49 | '--exclude=*init*' 50 | ] 51 | files: \.py$ 52 | 53 | - repo: https://github.com/PyCQA/bandit 54 | rev: 1.7.4 55 | hooks: 56 | - id: bandit 57 | 58 | - repo: https://github.com/pre-commit/pre-commit-hooks 59 | rev: v3.2.0 60 | hooks: 61 | - id: trailing-whitespace 62 | - id: end-of-file-fixer 63 | - id: requirements-txt-fixer 64 | - id: check-docstring-first 65 | - id: check-added-large-files 66 | - id: check-yaml 67 | args: [--allow-multiple-documents] 68 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | obj_files/ 132 | *.obj 133 | *.rt 134 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Convert .obj files for 42's miniRT 2 | 3 | [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit) [![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit) 4 | 5 | Convert `.obj` files to `.rt` files to render a triangle mesh effect for [miniRT](https://github.com/matboivin/raytracer) project at 42. 6 | 7 |

8 | deer 9 |

10 | 11 | ## Requirements 12 | 13 | * Python 3.9 or greater 14 | * [`poetry`](https://python-poetry.org/) 15 | * Learn more about `.obj` files formatting [here](https://en.wikipedia.org/wiki/Wavefront_.obj_file). 16 | 17 | ## Installation 18 | 19 | 1. Clone the repository and change it to your working directory. 20 | 21 | 2. Install the project: 22 | 23 | ```console 24 | $ poetry install 25 | ``` 26 | 27 | ## Usage 28 | 29 | ```console 30 | minirt_converter [-h] filename color 31 | 32 | Convert .obj files to .rt files to render a triangle mesh effect for miniRT project at 42. 33 | 34 | positional arguments: 35 | filename obj file to convert. 36 | color the color in RGB format (e.g., 255,255,255). 37 | 38 | optional arguments: 39 | -h, --help show this help message and exit 40 | 41 | example usage: 42 | minirt_converter file.obj 255,255,255 43 | ``` 44 | 45 | 1. Activate the virtual environment: 46 | 47 | ```console 48 | $ source `poetry env info --path`/bin/activate 49 | ``` 50 | 51 | 2. Run the project: 52 | 53 | ```console 54 | $ minirt_converter file.obj 255,255,255 55 | ``` 56 | 57 | 3. Then, **add Resolution, Ambient Light, cameras and light points** to your [scene](https://github.com/matboivin/raytracer/blob/main/doc/scene_file.md). 58 | 59 | ### Examples 60 | 61 | The `deer.rt`, `dragon.rt` and `wolf3d.rt` scenes can be found [here](https://github.com/matboivin/raytracer/tree/main/scenes). 62 | 63 |

64 | dragon 65 | wolf 66 |

67 | 68 | ## Acknowledgements 69 | 70 | Many thanks to [MrMoustach](https://github.com/MrMoustach) for contributing by adding a polygon support! 71 | 72 | ## License 73 | 74 | Creative Commons License 75 | 76 | This work is licensed under a 77 | [Creative Commons Attribution-NonCommercial 4.0 International License](http://creativecommons.org/licenses/by-nc/4.0/). 78 | -------------------------------------------------------------------------------- /minirt_converter/convert.py: -------------------------------------------------------------------------------- 1 | """Convert .obj file to .rt file.""" 2 | 3 | from pathlib import Path 4 | from typing import Dict, List 5 | 6 | from verboselogs import VerboseLogger 7 | 8 | 9 | def get_triangles_from_face( 10 | face: str, 11 | vertices_coords: Dict[str, Dict[str, str]], 12 | color: str, 13 | triangles: List[str], 14 | ) -> None: 15 | """Get triangles from face element coordinates. 16 | 17 | Parameters 18 | ---------- 19 | face : str 20 | A Polygonal face element line. 21 | vertices_coords : dict of dict 22 | Vertices coordinates parsed from .obj file. 23 | color : str 24 | The color of the object in RGB format. 25 | triangles : list of str 26 | The list to which append new triangles. 27 | 28 | """ 29 | tmp: List[str] = face.split(" ") 30 | matching_coords: List[str] = [ 31 | tmp[i].split("/")[0] for i in range(1, len(tmp)) 32 | ] 33 | 34 | vertex1: str = ",".join( 35 | ( 36 | vertices_coords[matching_coords[0]]["x"], 37 | vertices_coords[matching_coords[0]]["y"], 38 | vertices_coords[matching_coords[0]]["z"], 39 | ) 40 | ) 41 | 42 | vertex2: str = ",".join( 43 | ( 44 | vertices_coords[matching_coords[1]]["x"], 45 | vertices_coords[matching_coords[1]]["y"], 46 | vertices_coords[matching_coords[1]]["z"], 47 | ) 48 | ) 49 | 50 | vertex3: str = ",".join( 51 | ( 52 | vertices_coords[matching_coords[2]]["x"], 53 | vertices_coords[matching_coords[2]]["y"], 54 | vertices_coords[matching_coords[2]]["z"], 55 | ) 56 | ) 57 | 58 | triangles.append(f"tr {vertex1} {vertex2} {vertex3} {color}") 59 | 60 | # if a face line has more than 5 params then its a quad not a tris therefore 61 | # we transform the quad into a tris.. still have to implement other polyons. 62 | # 4-------3 63 | # | /| 64 | # | / | 65 | # | / | 66 | # |/ | 67 | # 1-------2 68 | # 1 2 3 4 into 1 2 3 and 1 3 4 69 | if len(tmp) > 5: 70 | vertex4: str = ",".join( 71 | ( 72 | vertices_coords[matching_coords[3]]["x"], 73 | vertices_coords[matching_coords[3]]["y"], 74 | vertices_coords[matching_coords[3]]["z"], 75 | ) 76 | ) 77 | triangles.append(f"tr {vertex1} {vertex3} {vertex4} {color}") 78 | 79 | 80 | def parse_vertices_coords(obj_data: List[str]) -> Dict[str, Dict[str, str]]: 81 | """Parse vertices coordinates (x, y, z). 82 | 83 | Parameters 84 | ---------- 85 | obj_data : list of str 86 | List obj elements. 87 | 88 | Returns 89 | ------- 90 | dict of dict 91 | All vertices coordinates. 92 | 93 | """ 94 | vertices_coords: Dict[str, Dict[str, str]] = {} 95 | vertices_count: int = 1 96 | 97 | for element in obj_data: 98 | if element[:2] == "v ": # Geometric vertex (v x y z [w]) 99 | vertex_coords: List[str] = element.split(" ") 100 | 101 | vertices_coords[str(vertices_count)] = { 102 | "x": vertex_coords[1], 103 | "y": vertex_coords[2], 104 | "z": vertex_coords[3][:-1], 105 | } 106 | vertices_count += 1 107 | 108 | return vertices_coords 109 | 110 | 111 | def save_polygons_to_file( 112 | filename: Path, obj_data: List[str], color: str 113 | ) -> None: 114 | """Parse vertices coordinates (x, y, z). 115 | 116 | Parameters 117 | ---------- 118 | filename : Path 119 | The output filename. 120 | obj_data : list of str 121 | List obj elements. 122 | color : str 123 | The color of the object in RGB format. 124 | 125 | """ 126 | vertices_coords: Dict[str, Dict[str, str]] = parse_vertices_coords( 127 | obj_data 128 | ) 129 | 130 | triangles: List[str] = [] 131 | 132 | for element in obj_data: 133 | if element[:2] == "f ": # Polygonal face element (f 1 2 3) 134 | get_triangles_from_face(element, vertices_coords, color, triangles) 135 | 136 | filename.write_text("\n".join(triangles) + "\n") 137 | 138 | 139 | def convert_obj_to_rt( 140 | logger: VerboseLogger, filename: Path, color: str 141 | ) -> None: 142 | """Convert .obj file to .rt format. 143 | 144 | Parameters 145 | ---------- 146 | logger : VerboseLogger 147 | The program's logger. 148 | filename : Path 149 | The file to convert. 150 | color : str 151 | The color of the object in RGB format. 152 | 153 | """ 154 | outfile: Path = filename.with_suffix(".rt") 155 | 156 | with filename.open(mode="r", encoding="utf-8") as file_handle: 157 | obj_data: List[str] = file_handle.readlines() 158 | 159 | logger.info("Start conversion.") 160 | 161 | save_polygons_to_file(outfile, obj_data, color) 162 | 163 | logger.info(f"Result saved in: '{str(outfile)}'.") 164 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Attribution-NonCommercial 4.0 International 2 | 3 | ======================================================================= 4 | 5 | Creative Commons Corporation ("Creative Commons") is not a law firm and 6 | does not provide legal services or legal advice. Distribution of 7 | Creative Commons public licenses does not create a lawyer-client or 8 | other relationship. Creative Commons makes its licenses and related 9 | information available on an "as-is" basis. Creative Commons gives no 10 | warranties regarding its licenses, any material licensed under their 11 | terms and conditions, or any related information. Creative Commons 12 | disclaims all liability for damages resulting from their use to the 13 | fullest extent possible. 14 | 15 | Using Creative Commons Public Licenses 16 | 17 | Creative Commons public licenses provide a standard set of terms and 18 | conditions that creators and other rights holders may use to share 19 | original works of authorship and other material subject to copyright 20 | and certain other rights specified in the public license below. The 21 | following considerations are for informational purposes only, are not 22 | exhaustive, and do not form part of our licenses. 23 | 24 | Considerations for licensors: Our public licenses are 25 | intended for use by those authorized to give the public 26 | permission to use material in ways otherwise restricted by 27 | copyright and certain other rights. Our licenses are 28 | irrevocable. Licensors should read and understand the terms 29 | and conditions of the license they choose before applying it. 30 | Licensors should also secure all rights necessary before 31 | applying our licenses so that the public can reuse the 32 | material as expected. Licensors should clearly mark any 33 | material not subject to the license. This includes other CC- 34 | licensed material, or material used under an exception or 35 | limitation to copyright. More considerations for licensors: 36 | wiki.creativecommons.org/Considerations_for_licensors 37 | 38 | Considerations for the public: By using one of our public 39 | licenses, a licensor grants the public permission to use the 40 | licensed material under specified terms and conditions. If 41 | the licensor's permission is not necessary for any reason--for 42 | example, because of any applicable exception or limitation to 43 | copyright--then that use is not regulated by the license. Our 44 | licenses grant only permissions under copyright and certain 45 | other rights that a licensor has authority to grant. Use of 46 | the licensed material may still be restricted for other 47 | reasons, including because others have copyright or other 48 | rights in the material. A licensor may make special requests, 49 | such as asking that all changes be marked or described. 50 | Although not required by our licenses, you are encouraged to 51 | respect those requests where reasonable. More considerations 52 | for the public: 53 | wiki.creativecommons.org/Considerations_for_licensees 54 | 55 | ======================================================================= 56 | 57 | Creative Commons Attribution-NonCommercial 4.0 International Public 58 | License 59 | 60 | By exercising the Licensed Rights (defined below), You accept and agree 61 | to be bound by the terms and conditions of this Creative Commons 62 | Attribution-NonCommercial 4.0 International Public License ("Public 63 | License"). To the extent this Public License may be interpreted as a 64 | contract, You are granted the Licensed Rights in consideration of Your 65 | acceptance of these terms and conditions, and the Licensor grants You 66 | such rights in consideration of benefits the Licensor receives from 67 | making the Licensed Material available under these terms and 68 | conditions. 69 | 70 | 71 | Section 1 -- Definitions. 72 | 73 | a. Adapted Material means material subject to Copyright and Similar 74 | Rights that is derived from or based upon the Licensed Material 75 | and in which the Licensed Material is translated, altered, 76 | arranged, transformed, or otherwise modified in a manner requiring 77 | permission under the Copyright and Similar Rights held by the 78 | Licensor. For purposes of this Public License, where the Licensed 79 | Material is a musical work, performance, or sound recording, 80 | Adapted Material is always produced where the Licensed Material is 81 | synched in timed relation with a moving image. 82 | 83 | b. Adapter's License means the license You apply to Your Copyright 84 | and Similar Rights in Your contributions to Adapted Material in 85 | accordance with the terms and conditions of this Public License. 86 | 87 | c. Copyright and Similar Rights means copyright and/or similar rights 88 | closely related to copyright including, without limitation, 89 | performance, broadcast, sound recording, and Sui Generis Database 90 | Rights, without regard to how the rights are labeled or 91 | categorized. For purposes of this Public License, the rights 92 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 93 | Rights. 94 | d. Effective Technological Measures means those measures that, in the 95 | absence of proper authority, may not be circumvented under laws 96 | fulfilling obligations under Article 11 of the WIPO Copyright 97 | Treaty adopted on December 20, 1996, and/or similar international 98 | agreements. 99 | 100 | e. Exceptions and Limitations means fair use, fair dealing, and/or 101 | any other exception or limitation to Copyright and Similar Rights 102 | that applies to Your use of the Licensed Material. 103 | 104 | f. Licensed Material means the artistic or literary work, database, 105 | or other material to which the Licensor applied this Public 106 | License. 107 | 108 | g. Licensed Rights means the rights granted to You subject to the 109 | terms and conditions of this Public License, which are limited to 110 | all Copyright and Similar Rights that apply to Your use of the 111 | Licensed Material and that the Licensor has authority to license. 112 | 113 | h. Licensor means the individual(s) or entity(ies) granting rights 114 | under this Public License. 115 | 116 | i. NonCommercial means not primarily intended for or directed towards 117 | commercial advantage or monetary compensation. For purposes of 118 | this Public License, the exchange of the Licensed Material for 119 | other material subject to Copyright and Similar Rights by digital 120 | file-sharing or similar means is NonCommercial provided there is 121 | no payment of monetary compensation in connection with the 122 | exchange. 123 | 124 | j. Share means to provide material to the public by any means or 125 | process that requires permission under the Licensed Rights, such 126 | as reproduction, public display, public performance, distribution, 127 | dissemination, communication, or importation, and to make material 128 | available to the public including in ways that members of the 129 | public may access the material from a place and at a time 130 | individually chosen by them. 131 | 132 | k. Sui Generis Database Rights means rights other than copyright 133 | resulting from Directive 96/9/EC of the European Parliament and of 134 | the Council of 11 March 1996 on the legal protection of databases, 135 | as amended and/or succeeded, as well as other essentially 136 | equivalent rights anywhere in the world. 137 | 138 | l. You means the individual or entity exercising the Licensed Rights 139 | under this Public License. Your has a corresponding meaning. 140 | 141 | 142 | Section 2 -- Scope. 143 | 144 | a. License grant. 145 | 146 | 1. Subject to the terms and conditions of this Public License, 147 | the Licensor hereby grants You a worldwide, royalty-free, 148 | non-sublicensable, non-exclusive, irrevocable license to 149 | exercise the Licensed Rights in the Licensed Material to: 150 | 151 | a. reproduce and Share the Licensed Material, in whole or 152 | in part, for NonCommercial purposes only; and 153 | 154 | b. produce, reproduce, and Share Adapted Material for 155 | NonCommercial purposes only. 156 | 157 | 2. Exceptions and Limitations. For the avoidance of doubt, where 158 | Exceptions and Limitations apply to Your use, this Public 159 | License does not apply, and You do not need to comply with 160 | its terms and conditions. 161 | 162 | 3. Term. The term of this Public License is specified in Section 163 | 6(a). 164 | 165 | 4. Media and formats; technical modifications allowed. The 166 | Licensor authorizes You to exercise the Licensed Rights in 167 | all media and formats whether now known or hereafter created, 168 | and to make technical modifications necessary to do so. The 169 | Licensor waives and/or agrees not to assert any right or 170 | authority to forbid You from making technical modifications 171 | necessary to exercise the Licensed Rights, including 172 | technical modifications necessary to circumvent Effective 173 | Technological Measures. For purposes of this Public License, 174 | simply making modifications authorized by this Section 2(a) 175 | (4) never produces Adapted Material. 176 | 177 | 5. Downstream recipients. 178 | 179 | a. Offer from the Licensor -- Licensed Material. Every 180 | recipient of the Licensed Material automatically 181 | receives an offer from the Licensor to exercise the 182 | Licensed Rights under the terms and conditions of this 183 | Public License. 184 | 185 | b. No downstream restrictions. You may not offer or impose 186 | any additional or different terms or conditions on, or 187 | apply any Effective Technological Measures to, the 188 | Licensed Material if doing so restricts exercise of the 189 | Licensed Rights by any recipient of the Licensed 190 | Material. 191 | 192 | 6. No endorsement. Nothing in this Public License constitutes or 193 | may be construed as permission to assert or imply that You 194 | are, or that Your use of the Licensed Material is, connected 195 | with, or sponsored, endorsed, or granted official status by, 196 | the Licensor or others designated to receive attribution as 197 | provided in Section 3(a)(1)(A)(i). 198 | 199 | b. Other rights. 200 | 201 | 1. Moral rights, such as the right of integrity, are not 202 | licensed under this Public License, nor are publicity, 203 | privacy, and/or other similar personality rights; however, to 204 | the extent possible, the Licensor waives and/or agrees not to 205 | assert any such rights held by the Licensor to the limited 206 | extent necessary to allow You to exercise the Licensed 207 | Rights, but not otherwise. 208 | 209 | 2. Patent and trademark rights are not licensed under this 210 | Public License. 211 | 212 | 3. To the extent possible, the Licensor waives any right to 213 | collect royalties from You for the exercise of the Licensed 214 | Rights, whether directly or through a collecting society 215 | under any voluntary or waivable statutory or compulsory 216 | licensing scheme. In all other cases the Licensor expressly 217 | reserves any right to collect such royalties, including when 218 | the Licensed Material is used other than for NonCommercial 219 | purposes. 220 | 221 | 222 | Section 3 -- License Conditions. 223 | 224 | Your exercise of the Licensed Rights is expressly made subject to the 225 | following conditions. 226 | 227 | a. Attribution. 228 | 229 | 1. If You Share the Licensed Material (including in modified 230 | form), You must: 231 | 232 | a. retain the following if it is supplied by the Licensor 233 | with the Licensed Material: 234 | 235 | i. identification of the creator(s) of the Licensed 236 | Material and any others designated to receive 237 | attribution, in any reasonable manner requested by 238 | the Licensor (including by pseudonym if 239 | designated); 240 | 241 | ii. a copyright notice; 242 | 243 | iii. a notice that refers to this Public License; 244 | 245 | iv. a notice that refers to the disclaimer of 246 | warranties; 247 | 248 | v. a URI or hyperlink to the Licensed Material to the 249 | extent reasonably practicable; 250 | 251 | b. indicate if You modified the Licensed Material and 252 | retain an indication of any previous modifications; and 253 | 254 | c. indicate the Licensed Material is licensed under this 255 | Public License, and include the text of, or the URI or 256 | hyperlink to, this Public License. 257 | 258 | 2. You may satisfy the conditions in Section 3(a)(1) in any 259 | reasonable manner based on the medium, means, and context in 260 | which You Share the Licensed Material. For example, it may be 261 | reasonable to satisfy the conditions by providing a URI or 262 | hyperlink to a resource that includes the required 263 | information. 264 | 265 | 3. If requested by the Licensor, You must remove any of the 266 | information required by Section 3(a)(1)(A) to the extent 267 | reasonably practicable. 268 | 269 | 4. If You Share Adapted Material You produce, the Adapter's 270 | License You apply must not prevent recipients of the Adapted 271 | Material from complying with this Public License. 272 | 273 | 274 | Section 4 -- Sui Generis Database Rights. 275 | 276 | Where the Licensed Rights include Sui Generis Database Rights that 277 | apply to Your use of the Licensed Material: 278 | 279 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 280 | to extract, reuse, reproduce, and Share all or a substantial 281 | portion of the contents of the database for NonCommercial purposes 282 | only; 283 | 284 | b. if You include all or a substantial portion of the database 285 | contents in a database in which You have Sui Generis Database 286 | Rights, then the database in which You have Sui Generis Database 287 | Rights (but not its individual contents) is Adapted Material; and 288 | 289 | c. You must comply with the conditions in Section 3(a) if You Share 290 | all or a substantial portion of the contents of the database. 291 | 292 | For the avoidance of doubt, this Section 4 supplements and does not 293 | replace Your obligations under this Public License where the Licensed 294 | Rights include other Copyright and Similar Rights. 295 | 296 | 297 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 298 | 299 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 300 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 301 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 302 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 303 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 304 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 305 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 306 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 307 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 308 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 309 | 310 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 311 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 312 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 313 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 314 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 315 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 316 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 317 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 318 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 319 | 320 | c. The disclaimer of warranties and limitation of liability provided 321 | above shall be interpreted in a manner that, to the extent 322 | possible, most closely approximates an absolute disclaimer and 323 | waiver of all liability. 324 | 325 | 326 | Section 6 -- Term and Termination. 327 | 328 | a. This Public License applies for the term of the Copyright and 329 | Similar Rights licensed here. However, if You fail to comply with 330 | this Public License, then Your rights under this Public License 331 | terminate automatically. 332 | 333 | b. Where Your right to use the Licensed Material has terminated under 334 | Section 6(a), it reinstates: 335 | 336 | 1. automatically as of the date the violation is cured, provided 337 | it is cured within 30 days of Your discovery of the 338 | violation; or 339 | 340 | 2. upon express reinstatement by the Licensor. 341 | 342 | For the avoidance of doubt, this Section 6(b) does not affect any 343 | right the Licensor may have to seek remedies for Your violations 344 | of this Public License. 345 | 346 | c. For the avoidance of doubt, the Licensor may also offer the 347 | Licensed Material under separate terms or conditions or stop 348 | distributing the Licensed Material at any time; however, doing so 349 | will not terminate this Public License. 350 | 351 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 352 | License. 353 | 354 | 355 | Section 7 -- Other Terms and Conditions. 356 | 357 | a. The Licensor shall not be bound by any additional or different 358 | terms or conditions communicated by You unless expressly agreed. 359 | 360 | b. Any arrangements, understandings, or agreements regarding the 361 | Licensed Material not stated herein are separate from and 362 | independent of the terms and conditions of this Public License. 363 | 364 | 365 | Section 8 -- Interpretation. 366 | 367 | a. For the avoidance of doubt, this Public License does not, and 368 | shall not be interpreted to, reduce, limit, restrict, or impose 369 | conditions on any use of the Licensed Material that could lawfully 370 | be made without permission under this Public License. 371 | 372 | b. To the extent possible, if any provision of this Public License is 373 | deemed unenforceable, it shall be automatically reformed to the 374 | minimum extent necessary to make it enforceable. If the provision 375 | cannot be reformed, it shall be severed from this Public License 376 | without affecting the enforceability of the remaining terms and 377 | conditions. 378 | 379 | c. No term or condition of this Public License will be waived and no 380 | failure to comply consented to unless expressly agreed to by the 381 | Licensor. 382 | 383 | d. Nothing in this Public License constitutes or may be interpreted 384 | as a limitation upon, or waiver of, any privileges and immunities 385 | that apply to the Licensor or You, including from the legal 386 | processes of any jurisdiction or authority. 387 | 388 | ======================================================================= 389 | 390 | Creative Commons is not a party to its public 391 | licenses. Notwithstanding, Creative Commons may elect to apply one of 392 | its public licenses to material it publishes and in those instances 393 | will be considered the “Licensor.” The text of the Creative Commons 394 | public licenses is dedicated to the public domain under the CC0 Public 395 | Domain Dedication. Except for the limited purpose of indicating that 396 | material is shared under a Creative Commons public license or as 397 | otherwise permitted by the Creative Commons policies published at 398 | creativecommons.org/policies, Creative Commons does not authorize the 399 | use of the trademark "Creative Commons" or any other trademark or logo 400 | of Creative Commons without its prior written consent including, 401 | without limitation, in connection with any unauthorized modifications 402 | to any of its public licenses or any other arrangements, 403 | understandings, or agreements concerning use of licensed material. For 404 | the avoidance of doubt, this paragraph does not form part of the 405 | public licenses. 406 | 407 | Creative Commons may be contacted at creativecommons.org. 408 | -------------------------------------------------------------------------------- /docs/minirt_converter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | minirt_converter API documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 53 |
54 |
55 |

56 | minirt_converter

57 | 58 |

Convert .obj files for 42's miniRT

59 | 60 |

Code style: black pre-commit security: bandit

61 | 62 |

Convert .obj files to .rt files to render a triangle mesh effect for miniRT project at 42.

63 | 64 |

65 | deer 66 |

67 | 68 |

Requirements

69 | 70 |
    71 |
  • Python 3.9 or greater
  • 72 |
  • poetry
  • 73 |
  • Learn more about .obj files formatting here.
  • 74 |
75 | 76 |

Installation

77 | 78 |
    79 |
  1. Clone the repository and change it to your working directory.

  2. 80 |
  3. Install the project:

    81 | 82 |
    83 |
    $ poetry install
     84 | 
    85 |
  4. 86 |
87 | 88 |

Usage

89 | 90 |
91 |
minirt_converter [-h] filename color
 92 | 
 93 | Convert .obj files to .rt files to render a triangle mesh effect for miniRT project at 42.
 94 | 
 95 | positional arguments:
 96 |   filename    obj file to convert.
 97 |   color       the color in RGB format (e.g., 255,255,255).
 98 | 
 99 | optional arguments:
100 |   -h, --help  show this help message and exit
101 | 
102 | example usage:
103 |   minirt_converter file.obj 255,255,255
104 | 
105 |
106 | 107 |
    108 |
  1. Activate the virtual environment:

    109 | 110 |
    111 |
    $ source `poetry env info --path`/bin/activate
    112 | 
    113 |
  2. 114 |
  3. Run the project:

    115 | 116 |
    117 |
    $ minirt_converter file.obj 255,255,255
    118 | 
    119 |
  4. 120 |
  5. Then, add Resolution, Ambient Light, cameras and light points to your scene.

  6. 121 |
122 | 123 |

Examples

124 | 125 |

The deer.rt, dragon.rt and wolf3d.rt scenes can be found here.

126 | 127 |

128 | dragon 129 | wolf 130 |

131 | 132 |

Acknowledgements

133 | 134 |

Many thanks to MrMoustach for contributing by adding a polygon support!

135 | 136 |

License

137 | 138 |

Creative Commons License

139 | 140 |

This work is licensed under a 141 | Creative Commons Attribution-NonCommercial 4.0 International License.

142 |
143 | 144 | 145 | 146 | 147 | 148 |
1""".. include:: ../README.md"""
149 | 
150 | 151 | 152 |
153 |
154 | 336 | -------------------------------------------------------------------------------- /docs/minirt_converter/helpers.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | minirt_converter.helpers API documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 47 |
48 |
49 |

50 | minirt_converter.helpers

51 | 52 |

Command line helper functions.

53 |
54 | 55 | 56 | 57 | 58 | 59 |
 1"""Command line helper functions."""
 60 |  2
 61 |  3from argparse import ArgumentParser, Namespace
 62 |  4
 63 |  5
 64 |  6def parse_args() -> Namespace:
 65 |  7    """Parse the program's arguments.
 66 |  8
 67 |  9    Returns
 68 | 10    -------
 69 | 11    argparse.Namespace
 70 | 12        The program's arguments.
 71 | 13
 72 | 14    """
 73 | 15    parser: ArgumentParser = ArgumentParser(
 74 | 16        prog="minirt_converter",
 75 | 17        description="Convert .obj files to .rt files to render a triangle mesh "
 76 | 18        "effect for miniRT project of School 42.",
 77 | 19    )
 78 | 20
 79 | 21    parser.add_argument("filename", type=str, help="obj file to convert.")
 80 | 22    parser.add_argument(
 81 | 23        "color", type=str, help="the color in RGB format (e.g., 255,255,255)."
 82 | 24    )
 83 | 25
 84 | 26    parser.add_argument_group(
 85 | 27        "example usage", "minirt_converter file.obj 255,204,0"
 86 | 28    )
 87 | 29
 88 | 30    return parser.parse_args()
 89 | 
90 | 91 | 92 |
93 |
94 | 95 |
96 | 97 | def 98 | parse_args() -> argparse.Namespace: 99 | 100 | 101 | 102 |
103 | 104 |
 7def parse_args() -> Namespace:
105 |  8    """Parse the program's arguments.
106 |  9
107 | 10    Returns
108 | 11    -------
109 | 12    argparse.Namespace
110 | 13        The program's arguments.
111 | 14
112 | 15    """
113 | 16    parser: ArgumentParser = ArgumentParser(
114 | 17        prog="minirt_converter",
115 | 18        description="Convert .obj files to .rt files to render a triangle mesh "
116 | 19        "effect for miniRT project of School 42.",
117 | 20    )
118 | 21
119 | 22    parser.add_argument("filename", type=str, help="obj file to convert.")
120 | 23    parser.add_argument(
121 | 24        "color", type=str, help="the color in RGB format (e.g., 255,255,255)."
122 | 25    )
123 | 26
124 | 27    parser.add_argument_group(
125 | 28        "example usage", "minirt_converter file.obj 255,204,0"
126 | 29    )
127 | 30
128 | 31    return parser.parse_args()
129 | 
130 | 131 | 132 |

Parse the program's arguments.

133 | 134 |

Returns

135 | 136 |

argparse.Namespace 137 | The program's arguments.

138 |
139 | 140 | 141 |
142 |
143 | 325 | -------------------------------------------------------------------------------- /docs/minirt_converter/main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | minirt_converter.main API documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 50 |
51 |
52 |

53 | minirt_converter.main

54 | 55 |

Program's entrypoint.

56 |
57 | 58 | 59 | 60 | 61 | 62 |
 1"""Program's entrypoint."""
 63 |  2
 64 |  3from argparse import Namespace
 65 |  4from pathlib import Path
 66 |  5
 67 |  6import coloredlogs
 68 |  7from verboselogs import VerboseLogger
 69 |  8
 70 |  9from .convert import convert_obj_to_rt
 71 | 10from .helpers import parse_args
 72 | 11
 73 | 12
 74 | 13def main(logger: VerboseLogger, filename: Path, color: str) -> None:
 75 | 14    """Run program.
 76 | 15
 77 | 16    Parameters
 78 | 17    ----------
 79 | 18    logger : VerboseLogger
 80 | 19        The program's logger.
 81 | 20    filename : Path
 82 | 21        The file to convert.
 83 | 22    color : str
 84 | 23        The color of the object in RGB format.
 85 | 24
 86 | 25    """
 87 | 26    convert_obj_to_rt(logger, filename, color)
 88 | 27
 89 | 28
 90 | 29def entrypoint() -> None:
 91 | 30    """Program's entrypoint."""
 92 | 31    args: Namespace = parse_args()
 93 | 32    filename: Path = Path(args.filename)
 94 | 33    logger: VerboseLogger = VerboseLogger("minirt_converter")
 95 | 34
 96 | 35    coloredlogs.install(
 97 | 36        logger=logger,
 98 | 37        level="DEBUG",
 99 | 38        fmt="[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s",
100 | 39    )
101 | 40
102 | 41    try:
103 | 42        main(logger, filename, args.color)
104 | 43    except (OSError, FileNotFoundError) as err:
105 | 44        logger.error(err)
106 | 45
107 | 46
108 | 47if __name__ == "__main__":
109 | 48    entrypoint()
110 | 
111 | 112 | 113 |
114 |
115 | 116 |
117 | 118 | def 119 | main( logger: verboselogs.VerboseLogger, filename: pathlib.Path, color: str) -> None: 120 | 121 | 122 | 123 |
124 | 125 |
14def main(logger: VerboseLogger, filename: Path, color: str) -> None:
126 | 15    """Run program.
127 | 16
128 | 17    Parameters
129 | 18    ----------
130 | 19    logger : VerboseLogger
131 | 20        The program's logger.
132 | 21    filename : Path
133 | 22        The file to convert.
134 | 23    color : str
135 | 24        The color of the object in RGB format.
136 | 25
137 | 26    """
138 | 27    convert_obj_to_rt(logger, filename, color)
139 | 
140 | 141 | 142 |

Run program.

143 | 144 |

Parameters

145 | 146 |

logger : VerboseLogger 147 | The program's logger. 148 | filename : Path 149 | The file to convert. 150 | color : str 151 | The color of the object in RGB format.

152 |
153 | 154 | 155 |
156 |
157 | 158 |
159 | 160 | def 161 | entrypoint() -> None: 162 | 163 | 164 | 165 |
166 | 167 |
30def entrypoint() -> None:
168 | 31    """Program's entrypoint."""
169 | 32    args: Namespace = parse_args()
170 | 33    filename: Path = Path(args.filename)
171 | 34    logger: VerboseLogger = VerboseLogger("minirt_converter")
172 | 35
173 | 36    coloredlogs.install(
174 | 37        logger=logger,
175 | 38        level="DEBUG",
176 | 39        fmt="[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s",
177 | 40    )
178 | 41
179 | 42    try:
180 | 43        main(logger, filename, args.color)
181 | 44    except (OSError, FileNotFoundError) as err:
182 | 45        logger.error(err)
183 | 
184 | 185 | 186 |

Program's entrypoint.

187 |
188 | 189 | 190 |
191 |
192 | 374 | --------------------------------------------------------------------------------