From 9c4d38e8d04724b9e5eeb17648095ffd079ddcd7 Mon Sep 17 00:00:00 2001 From: Ilya Razmanov Date: Thu, 4 Apr 2024 22:09:23 +0300 Subject: [PATCH] major restructure --- README.RU.md | 12 +- README.md | 18 +- img2mesh.py | 252 ++++++++++++++++++ old_versions/README.RU.md | 31 +++ old_versions/README.md | 31 +++ .../img2mesh.01.004.py | 0 .../img2mesh.02.004.py | 0 .../img2mesh.02.005.py | 0 .../img2mesh.02.007.py | 60 +++-- 9 files changed, 362 insertions(+), 42 deletions(-) create mode 100644 img2mesh.py create mode 100644 old_versions/README.RU.md create mode 100644 old_versions/README.md rename img2mesh.01.004.py => old_versions/img2mesh.01.004.py (100%) rename img2mesh.02.004.py => old_versions/img2mesh.02.004.py (100%) rename img2mesh.02.005.py => old_versions/img2mesh.02.005.py (100%) rename img2mesh.02.007.py => old_versions/img2mesh.02.007.py (75%) diff --git a/README.RU.md b/README.RU.md index 992701c..0bf0e5c 100644 --- a/README.RU.md +++ b/README.RU.md @@ -6,17 +6,9 @@ ![Example of img2mesh output rendering](https://dnyarri.github.io/imgmesh/640/img2mesh.png) -*Версии* +В данной директории находится наиболее свежая версия программы; несколько более старых закопаны в *"old_versions"* для археологов будущего. -- **img2mesh.01.xxx** - конвертирует квадрат 2x2 пикселя в 2 треугольника с общей гипотенузой. Версия 01.003 - выбор диагонали квадрата для гипотенуз ("перегиба" квадрата) в соответствии с локальным градиентом. **Разработка прекращена на версии 01.004 в пользу версии 02**, обеспечивающей улучшенный рендеринг. - -- **img2mesh.02.xxx** - конвертирует 1 пиксель в пирамиду из 4 треугольников. Узлы сетки автоматически связываются, что обеспечивает возможность использования сетки в [CSG](https://www.povray.org/documentation/3.7.0/r3_4.html#r3_4_5_4)-операциях (начиная с версии 02.002 к сцене добавлена операция intersection с кубом, что придаёт сетке боковые поверхности и дно. Редактируя размеры куба (или заменяя его на цилиндр и т.п.), можно аккуратно обрезать бока сетки, а также менять "уровень воды", прорезая отверстия на месте минимумов). - -- **img2mesh.02.005** - существенное внутреннее изменение. Модуль чтения исходных PNG изменен с Pillow на [PyPNG](https://gitlab.com/drj11/pypng), что уменьшает объем внешних зависимостей программы, а главное - обеспечивает трассировку исходных PNG с цветовой глубиной 16 бит на канал, что резко увеличивает разрешение сигнала по оси z. - -- **img2mesh.02.007** - внутренние изменения, улучшения читаемости вывода; к релизу 2.6.1 добавлен **img2mesh.exe** для Windows - -*Зависимости от внешних библиотек:* Tkinter, PyPNG / Pillow +*Зависимости от внешних библиотек:* [PyPNG](https://gitlab.com/drj11/pypng), Tkinter. Первая лежит рядом с программой в репозитории, и, слава Создателю, способна работать в таком виде без установки; вторая входит во все типовые дистрибутивы Python. *Инструкция по эксплуатации:* программы оборудованы минималистическим GUI, в результате всё, что вы должны сделать после запуска программы, это с помощью окна "Open..." выбрать и открыть файл PNG, с помощью окна "Save..." выбрать POV-файл для сохранения, подождать, пока программа отработает и закроется, затем открыть полученный POV-файл в POVRay и нажать кнопочку "Render". Экспортированная сцена содержит необходимый минимум глобальных переменных и объектов (камера, свет) для ознакомительного рендеринга без редактирования. Текстуры объекта и параметры камеры и т.п. записаны в максимально общем виде с комментариями, и должны быть просты для понимания и редактирования. diff --git a/README.md b/README.md index d514e68..1d7ef25 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,16 @@ **(EN)** [(RU)](README.RU.md) -# Bitmap to 3D triangle mesh converter +# Bitmap to POVRay 3D triangle mesh converter -Python utilities for conversion of bitmap heightfield (in [PNG format](http://www.libpng.org/pub/png/)) to 3D triangle mesh in [POVRay](https://www.povray.org/) format. Resulting triangle mesh provides better rendering in case of low-res source files as compared to using source bitmaps as a heightfield directly. +Python program for conversion of bitmap heightfield (in [PNG format](http://www.libpng.org/pub/png/)) to 3D triangle mesh in [POVRay](https://www.povray.org/) format. Resulting triangle mesh provides better rendering in case of low-res source files as compared to using source bitmaps as a heightfield directly. ![Example of img2mesh output rendering](https://dnyarri.github.io/imgmesh/640/img2mesh.png) -*Version history* +Current dir contain most recent version of img2mesh program. Some previous versions are saved in *"old_versions"* for future alien archeologist to dig. -- **img2mesh.01.xxx** - converts 2x2 pixel square into 2 triangle. ver.01.003 - folding according to local gradient. **Development cancelled at ver.01.004 in favour of ver.02**, which provides better rendering. +*Dependencies:* [PyPNG](https://gitlab.com/drj11/pypng), Tkinter. The former is placed in this repo and, thank the Maker, will work right after downloading; the latter included in all typical Python installation. -- **img2mesh.02.xxx** - converts 1 pixel into pyramid of 4 triangles, significantly improving visual appearance of rendering. Mesh is tight enough to be used in [CSG](https://www.povray.org/documentation/3.7.0/r3_4.html#r3_4_5_4) (since version 02.002 added intersection with bounding box, thus giving sides and bottom to mesh). - -- **img2mesh.02.005** - major internal change. Input module changed from Pillow to [PyPNG](https://gitlab.com/drj11/pypng) thus allowing 16 bpc PNG files to be processed, generating meshes with higher z-resolution. - -- **img2mesh.02.007** - moderate internal changes; **Windows img2mesh.exe** file generated and added to 2.6.1 release. - -*Dependencies:* Tkinter, PyPNG / Pillow - -*Usage:* programs are equipped with minimal GUI, so all you have to do after starting the programs is use standard "Open..." GUI to open image file, then use standard "Save..." GUI to set POVRay scene file to be created, then wait while program does the job, then open resulting POV file with POVRay and render the scene. Scene contains enough basic stuff (globals, light, camera) to be rendered successfully right after exporting without any editing. +*Usage:* program equipped with minimal GUI, so all you have to do after starting the program is use standard "Open..." GUI to open image file, then use standard "Save..." GUI to set POVRay scene file to be created, then wait while program does the job, then open resulting POV file with POVRay and render the scene. Scene contains enough basic stuff (globals, light, camera) to be rendered successfully right after exporting without any editing. More software at: diff --git a/img2mesh.py b/img2mesh.py new file mode 100644 index 0000000..b501c5a --- /dev/null +++ b/img2mesh.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python + +''' +IMG2MESH - Program for conversion of image heightfield to triangle mesh in POVRay format +----------------------------------------------------------------------------------------- + +Created by: Ilya Razmanov (mailto:ilyarazmanov@gmail.com) + aka Ilyich the Toad (mailto:amphisoft@gmail.com) +History: +001 Abandoned img2mesh and turned to img2mesh2 with completely different mesh structure. +002 Added mesh encapsulation with cubic box to provide solid walls and bottom. +003 Restructured output for easy reading, everything but globals and includes now at the end of scene. + Extended camera description. +004 Bug with positioning found and seem to be fixed. +005 Replaced Pillow I/O with PyPNG from: https://gitlab.com/drj11/pypng + Support for 16 bit/channel PNGs added. +006 Minor output cleanup and generalization. +007 GUI improved to show progress during long processing. Attempt to reduce import. +2.7.1.0 Significant code cleanup with .writelines. Versioning more clear. + + Main site: + https://dnyarri.github.io + + Project mirrored at: + https://github.com/Dnyarri/img2mesh + https://gitflic.ru/project/dnyarri/img2mesh + +''' + +__author__ = "Ilya Razmanov" +__copyright__ = "(c) 2023-2024 Ilya Razmanov" +__credits__ = "Ilya Razmanov" +__license__ = "unlicense" +__version__ = "2.7.1.0" +__maintainer__ = "Ilya Razmanov" +__email__ = "ilyarazmanov@gmail.com" +__status__ = "Production" + +from tkinter import Tk +from tkinter import Label +from tkinter import filedialog +from time import time +from time import ctime + +from png import Reader # I/O with PyPNG from: https://gitlab.com/drj11/pypng + +# -------------------------------------------------------------- +# Creating dialog + +sortir = Tk() +sortir.title('PNG to POV conversion') +sortir.geometry('+100+100') +zanyato = Label(sortir, text = 'Starting...', font=("arial", 14), padx=16, pady=10, justify='center') +zanyato.pack() +sortir.withdraw() + +# Main dialog created and hidden +# -------------------------------------------------------------- + +# Open source image +sourcefilename = filedialog.askopenfilename(title='Open source PNG file', filetypes=[('PNG','.png')], defaultextension = ('PNG','.png')) +if (sourcefilename == ''): + quit() + +source = Reader(filename = sourcefilename) # starting PyPNG + +X,Y,pixels,info = source.asDirect() # Opening image, iDAT comes to "pixels" as bytearray, to be tuple'd later + +Z = (info['planes']) # Maximum CHANNEL NUMBER +imagedata = tuple((pixels)) # Attempt to fix all bytearrays + +if (info['bitdepth'] == 8): + maxcolors = 255 # Maximal value for 8-bit channel +if (info['bitdepth'] == 16): + maxcolors = 65535 # Maximal value for 16-bit channel + +# Open export file +resultfile = filedialog.asksaveasfile(mode='w', title='Save resulting POV file', filetypes = + [ + ('POV-Ray scene file', '*.pov'), + ('All Files', '*.*'), + ], + defaultextension = ('POV-Ray scene file','.pov')) +if (resultfile == ''): + quit() +# Both files opened + +# src a-la FM style src(x,y,z) +# Image should be opened as "imagedata" by main program before +# Note that X, Y, Z are not determined in function, you have to determine it in main program + +def src(x, y, z): + ''' + Analog src from FM, force repeate edge instead of out of range + ''' + cx = x; cy = y + cx = max(0,cx); cx = min((X-1),cx) + cy = max(0,cy); cy = min((Y-1),cy) + + position = (cx*Z) + z # Here is the main magic of turning two x, z into one array position + channelvalue = int(((imagedata[cy])[position])) + + return channelvalue +# end of src function + +def srcY(x, y): + ''' + Converting to greyscale, returns Yntensity, force repeate edge instead of out of range + ''' + cx = x; cy = y + cx = max(0,cx); cx = min((X-1),cx) + cy = max(0,cy); cy = min((Y-1),cy) + + if (info['planes'] < 3): # supposedly L and LA + Yntensity = src(x, y, 0) + else: # supposedly RGB and RGBA + Yntensity = int(0.2989*src(x, y, 0) + 0.587*src(x, y, 1) + 0.114*src(x, y, 2)) + + return Yntensity +# end of srcY function + +# WRITING POV FILE + +# ------------ +# POV header +# ------------ + +resultfile.writelines(['/*\n', + 'Persistence of Vision Ray Tracer Scene Description File\n', + 'Version: 3.7\n', + 'Description: A triangle mesh file converted from image heightfield\n', + 'Author: Automatically generated by img2mesh Pyton program', + 'https://github.com/Dnyarri/img2mesh\n', + 'https://gitflic.ru/project/dnyarri/img2mesh\n', + 'developed by Ilya Razmanov aka Ilyich the Toad\n', + 'https://dnyarri.github.io\nmailto:ilyarazmanov@gmail.com\n', + '*/\n\n' + ]) + +resultfile.write(f'// Converted from: {sourcefilename} ') +seconds = time(); localtime = ctime(seconds) +resultfile.write(f'at: {localtime}\n// Source info: {info}\n\n') + +# Statements + +resultfile.writelines(['\n', + '#version 3.7;\n\n', + 'global_settings{\n', + ' max_trace_level 3 // Small to speed up preview. May need to be increased for metals\n', + ' adc_bailout 0.01 // High to speed up preview. May need to be decreased to 1/256\n', + ' ambient_light <0.5,0.5,0.5>\n', + ' assumed_gamma 1.0\n}\n', + '\n#include "colors.inc"\n#include "finish.inc"\n#include "golds.inc"\n#include "metals.inc"' + '\n\n' + ]) + +# Mesh + +resultfile.write('#declare thething = mesh {\n') # Opening mesh object "thething" + +# Now going to cycle through image and build mesh + +for y in range(0, Y, 1): + + message = ('Processing row ' + str(y) +' of ' + str(Y) + '...') + sortir.deiconify() + zanyato.config(text = message) + sortir.update() + sortir.update_idletasks() + + resultfile.write(f'\n\n // Row {y}\n') + + for x in range(0, X, 1): + + v9 = srcY(x,y) # Current pixel to process and write. Then going to neighbours + v1 = (v9 + srcY((x-1), y) + srcY((x-1), (y-1)) + srcY(x, (y-1)))/4.0 # По улитке 8-1-2 + v3 = (v9 + srcY(x, (y-1)) + srcY((x+1), (y-1)) + srcY((x+1), y))/4.0 # По улитке 2-3-4 + v5 = (v9 + srcY((x+1), y) + srcY((x+1), (y+1)) + srcY(x, (y+1)))/4.0 # По улитке 4-5-6 + v7 = (v9 + srcY(x, (y+1)) + srcY((x-1), (y+1)) + srcY((x-1), y))/4.0 # По улитке 6-7-8 + + # going to pyramid building + + resultfile.write('\n triangle{') # Opening triangle 2 + resultfile.write(f'<{(x-0.5)}, {(y-0.5)}, {v1}> ') + resultfile.write(f'<{(x+0.5)}, {(y-0.5)}, {v3}> ') + resultfile.write(f'<{x}, {y}, {v9}>') + resultfile.write('}') # Closing triangle 2 + + resultfile.write('\n triangle{') # Opening triangle 4 + resultfile.write(f'<{(x+0.5)}, {(y-0.5)}, {v3}> ') + resultfile.write(f'<{(x+0.5)}, {(y+0.5)}, {v5}> ') + resultfile.write(f'<{x}, {y}, {v9}>') + resultfile.write('}') # Closing triangle 4 + + resultfile.write('\n triangle{') # Opening triangle 6 + resultfile.write(f'<{(x+0.5)}, {(y+0.5)}, {v5}> ') + resultfile.write(f'<{(x-0.5)}, {(y+0.5)}, {v7}> ') + resultfile.write(f'<{x}, {y}, {v9}>') + resultfile.write('}') # Closing triangle 6 + + resultfile.write('\n triangle{') # Opening triangle 8 + resultfile.write(f'<{(x-0.5)}, {(y+0.5)}, {v7}> ') + resultfile.write(f'<{(x-0.5)}, {(y-0.5)}, {v1}> ') + resultfile.write(f'<{x}, {y}, {v9}>') + resultfile.write('}') # Closing triangle 8 + +resultfile.write('\n\ninside_vector <0, 0, 1>\n\n') + +# Transform object to fit 1, 1, 1 cube at 0, 0, 0 coordinates +resultfile.write('\n// Object transforms to fit 1, 1, 1 cube at 0, 0, 0 coordinates\n') +resultfile.write('translate <0.5, 0.5, 0>\n') # compensate for -0.5 extra, now object fit 0..X, 0..Y, 0..maxcolors +resultfile.write(f'translate <-0.5*{X}, -0.5*{Y}, 0>\n') # translate to center object bottom at x = 0, y = 0, z = 0 +resultfile.write(f'scale <-1.0/{max(X,Y)}, -1.0/{max(X,Y)}, 1.0/{maxcolors}>\n') # rescale, mirroring POV coordinates to match Photoshop coordinate system + +# Sample texture of textures +resultfile.writelines(['texture {\n', + ' gradient z\n', + ' texture_map {\n', + ' [0.01 pigment {Red} finish {phong 1}]\n', + ' [0.5 pigment {Blue} finish {phong 5}]\n', + ' [0.99 pigment {White} finish {phong 10}]\n }\n}\n', + '}\n// Closed thething\n\n', + '#declare boxedthing = object{\n', + ' intersection {\n', + ' box {<-0.5, -0.5, 0>, <0.5, 0.5, 1.0>\n', + ' pigment {rgb <0.5, 0.5, 5>}\n', + ' }\n thething\n }\n}', + '// Constructed CGS "boxedthing" of mesh plus bounding box thus adding side walls and bottom\n\n', + 'object {boxedthing}\n\n' + ]) # Closing mesh object "thething", then bounding box + +# Camera +proportions = max(X,Y)/X +resultfile.write('#declare camera_height = 3.0;\n\n') +resultfile.write('camera {\n // orthographic\n location <0.0, 0.0, camera_height>\n right x*image_width/image_height\n up y\n direction <0, 0, 1>\n angle 2.0*(degrees(atan2(') +resultfile.write(f'{0.5 * proportions}') +resultfile.write(', camera_height-1.0))) // Supposed to fit object \n look_at <0.0, 0.0, 0.0>\n}\n\n') + +# Light +resultfile.write('light_source {0*x\n color rgb <1,1,1>\n translate <20, 20, 20>\n}\n') +resultfile.write('\n/*\n\nhappy rendering\n\n 0~0\n (---)\n(.>|<.)\n-------\n\n*/') +# Close output +resultfile.close() + +# -------------------------------------------------------------- +# Destroying dialog + +sortir.destroy() +sortir.mainloop() + +# Dialog destroyed and closed +# -------------------------------------------------------------- \ No newline at end of file diff --git a/old_versions/README.RU.md b/old_versions/README.RU.md new file mode 100644 index 0000000..992701c --- /dev/null +++ b/old_versions/README.RU.md @@ -0,0 +1,31 @@ +[(EN)](README.md) **(RU)** + +# Конвертер из растровых картинок в 3D-сетку треугольников + +Программа на Python для трассировки карты высот в графическом формате ([PNG](http://www.libpng.org/pub/png/)) в трёхмерную векторную сетку треугольников (triangle meash) в формате [POVRay](https://www.povray.org/). Координаты x, y пикселя соответствуют координатам x, y узлов сетки, яркость пикселя соответствует высоте (z) узла сетки. В случае исходных графических файлов с низким разрешением полученная при трассировке 3D-сетка обеспечивает лучшее визуальное качество рендеренга, нежели исходные графические файлы при их использовании в качестве heightfield напрямую. + +![Example of img2mesh output rendering](https://dnyarri.github.io/imgmesh/640/img2mesh.png) + +*Версии* + +- **img2mesh.01.xxx** - конвертирует квадрат 2x2 пикселя в 2 треугольника с общей гипотенузой. Версия 01.003 - выбор диагонали квадрата для гипотенуз ("перегиба" квадрата) в соответствии с локальным градиентом. **Разработка прекращена на версии 01.004 в пользу версии 02**, обеспечивающей улучшенный рендеринг. + +- **img2mesh.02.xxx** - конвертирует 1 пиксель в пирамиду из 4 треугольников. Узлы сетки автоматически связываются, что обеспечивает возможность использования сетки в [CSG](https://www.povray.org/documentation/3.7.0/r3_4.html#r3_4_5_4)-операциях (начиная с версии 02.002 к сцене добавлена операция intersection с кубом, что придаёт сетке боковые поверхности и дно. Редактируя размеры куба (или заменяя его на цилиндр и т.п.), можно аккуратно обрезать бока сетки, а также менять "уровень воды", прорезая отверстия на месте минимумов). + +- **img2mesh.02.005** - существенное внутреннее изменение. Модуль чтения исходных PNG изменен с Pillow на [PyPNG](https://gitlab.com/drj11/pypng), что уменьшает объем внешних зависимостей программы, а главное - обеспечивает трассировку исходных PNG с цветовой глубиной 16 бит на канал, что резко увеличивает разрешение сигнала по оси z. + +- **img2mesh.02.007** - внутренние изменения, улучшения читаемости вывода; к релизу 2.6.1 добавлен **img2mesh.exe** для Windows + +*Зависимости от внешних библиотек:* Tkinter, PyPNG / Pillow + +*Инструкция по эксплуатации:* программы оборудованы минималистическим GUI, в результате всё, что вы должны сделать после запуска программы, это с помощью окна "Open..." выбрать и открыть файл PNG, с помощью окна "Save..." выбрать POV-файл для сохранения, подождать, пока программа отработает и закроется, затем открыть полученный POV-файл в POVRay и нажать кнопочку "Render". Экспортированная сцена содержит необходимый минимум глобальных переменных и объектов (камера, свет) для ознакомительного рендеринга без редактирования. Текстуры объекта и параметры камеры и т.п. записаны в максимально общем виде с комментариями, и должны быть просты для понимания и редактирования. + +Прочие программы: + +[Dnyarri website](https://dnyarri.github.io/) + +Во избежание санкций проект зеркалится: + +[github Dnyarri](https://github.com/Dnyarri/img2mesh) + +[gitflic Dnyarri](https://gitflic.ru/project/dnyarri/img2mesh) diff --git a/old_versions/README.md b/old_versions/README.md new file mode 100644 index 0000000..d514e68 --- /dev/null +++ b/old_versions/README.md @@ -0,0 +1,31 @@ +**(EN)** [(RU)](README.RU.md) + +# Bitmap to 3D triangle mesh converter + +Python utilities for conversion of bitmap heightfield (in [PNG format](http://www.libpng.org/pub/png/)) to 3D triangle mesh in [POVRay](https://www.povray.org/) format. Resulting triangle mesh provides better rendering in case of low-res source files as compared to using source bitmaps as a heightfield directly. + +![Example of img2mesh output rendering](https://dnyarri.github.io/imgmesh/640/img2mesh.png) + +*Version history* + +- **img2mesh.01.xxx** - converts 2x2 pixel square into 2 triangle. ver.01.003 - folding according to local gradient. **Development cancelled at ver.01.004 in favour of ver.02**, which provides better rendering. + +- **img2mesh.02.xxx** - converts 1 pixel into pyramid of 4 triangles, significantly improving visual appearance of rendering. Mesh is tight enough to be used in [CSG](https://www.povray.org/documentation/3.7.0/r3_4.html#r3_4_5_4) (since version 02.002 added intersection with bounding box, thus giving sides and bottom to mesh). + +- **img2mesh.02.005** - major internal change. Input module changed from Pillow to [PyPNG](https://gitlab.com/drj11/pypng) thus allowing 16 bpc PNG files to be processed, generating meshes with higher z-resolution. + +- **img2mesh.02.007** - moderate internal changes; **Windows img2mesh.exe** file generated and added to 2.6.1 release. + +*Dependencies:* Tkinter, PyPNG / Pillow + +*Usage:* programs are equipped with minimal GUI, so all you have to do after starting the programs is use standard "Open..." GUI to open image file, then use standard "Save..." GUI to set POVRay scene file to be created, then wait while program does the job, then open resulting POV file with POVRay and render the scene. Scene contains enough basic stuff (globals, light, camera) to be rendered successfully right after exporting without any editing. + +More software at: + +[Dnyarri website](https://dnyarri.github.io/) + +Project mirrors: + +[github Dnyarri](https://github.com/Dnyarri/img2mesh) + +[gitflic Dnyarri](https://gitflic.ru/project/dnyarri/img2mesh) diff --git a/img2mesh.01.004.py b/old_versions/img2mesh.01.004.py similarity index 100% rename from img2mesh.01.004.py rename to old_versions/img2mesh.01.004.py diff --git a/img2mesh.02.004.py b/old_versions/img2mesh.02.004.py similarity index 100% rename from img2mesh.02.004.py rename to old_versions/img2mesh.02.004.py diff --git a/img2mesh.02.005.py b/old_versions/img2mesh.02.005.py similarity index 100% rename from img2mesh.02.005.py rename to old_versions/img2mesh.02.005.py diff --git a/img2mesh.02.007.py b/old_versions/img2mesh.02.007.py similarity index 75% rename from img2mesh.02.007.py rename to old_versions/img2mesh.02.007.py index a917ab3..24ce72d 100644 --- a/img2mesh.02.007.py +++ b/old_versions/img2mesh.02.007.py @@ -125,16 +125,34 @@ def srcY(x, y): # POV header # ------------ -resultfile.write('// Persistence of Vision Ray Tracer Scene Description File\n// Vers: 3.7\n// Description: A triangle mesh file converted from image heightfield\n// Auth: Automatically generated by img2mesh Pyton program\n// https://github.com/Dnyarri/img2mesh\n// https://gitflic.ru/project/dnyarri/img2mesh\n// developed by Ilya Razmanov\n// (https://dnyarri.github.io/) (mailto:ilyarazmanov@gmail.com)\n\n') +resultfile.writelines(['/*\n', + 'Persistence of Vision Ray Tracer Scene Description File\n', + 'Version: 3.7\n', + 'Description: A triangle mesh file converted from image heightfield\n', + 'Author: Automatically generated by img2mesh Pyton program', + 'https://github.com/Dnyarri/img2mesh\n', + 'https://gitflic.ru/project/dnyarri/img2mesh\n', + 'developed by Ilya Razmanov aka Ilyich the Toad\n', + 'https://dnyarri.github.io\nmailto:ilyarazmanov@gmail.com\n', + '*/\n\n' + ]) resultfile.write(f'// Converted from: {sourcefilename} ') -seconds = time() -localtime = ctime(seconds) +seconds = time(); localtime = ctime(seconds) resultfile.write(f'at: {localtime}\n// Source info: {info}\n\n') # Statements -resultfile.write('#version 3.7;\n\nglobal_settings\n{\n max_trace_level 3\n adc_bailout 0.01\n ambient_light <0.5,0.5,0.5>\n assumed_gamma 1.0\n}\n\n#include "colors.inc"\n#include "finish.inc"\n#include "golds.inc"\n#include "metals.inc"\n\n\n') +resultfile.writelines(['\n', + '#version 3.7;\n\n', + 'global_settings{\n', + ' max_trace_level 3\n', + ' adc_bailout 0.01\n', + ' ambient_light <0.5,0.5,0.5>\n', + ' assumed_gamma 1.0\n}\n', + '\n#include "colors.inc"\n#include "finish.inc"\n#include "golds.inc"\n#include "metals.inc"' + '\n\n' + ]) # Mesh @@ -162,25 +180,25 @@ def srcY(x, y): # going to pyramid building - resultfile.write('\n triangle {') # Opening triangle 2 + resultfile.write('\n triangle{') # Opening triangle 2 resultfile.write(f'<{(x-0.5)}, {(y-0.5)}, {v1}> ') resultfile.write(f'<{(x+0.5)}, {(y-0.5)}, {v3}> ') resultfile.write(f'<{x}, {y}, {v9}>') resultfile.write('}') # Closing triangle 2 - resultfile.write('\n triangle {') # Opening triangle 4 + resultfile.write('\n triangle{') # Opening triangle 4 resultfile.write(f'<{(x+0.5)}, {(y-0.5)}, {v3}> ') resultfile.write(f'<{(x+0.5)}, {(y+0.5)}, {v5}> ') resultfile.write(f'<{x}, {y}, {v9}>') resultfile.write('}') # Closing triangle 4 - resultfile.write('\n triangle {') # Opening triangle 6 + resultfile.write('\n triangle{') # Opening triangle 6 resultfile.write(f'<{(x+0.5)}, {(y+0.5)}, {v5}> ') resultfile.write(f'<{(x-0.5)}, {(y+0.5)}, {v7}> ') resultfile.write(f'<{x}, {y}, {v9}>') resultfile.write('}') # Closing triangle 6 - resultfile.write('\n triangle {') # Opening triangle 8 + resultfile.write('\n triangle{') # Opening triangle 8 resultfile.write(f'<{(x-0.5)}, {(y+0.5)}, {v7}> ') resultfile.write(f'<{(x-0.5)}, {(y-0.5)}, {v1}> ') resultfile.write(f'<{x}, {y}, {v9}>') @@ -196,17 +214,21 @@ def srcY(x, y): # Sample texture of textures resultfile.writelines(['texture {\n', -' gradient z\n', -' texture_map {\n', -' [0.01 pigment {Red} finish {phong 1}]\n', -' [0.5 pigment {Blue} finish {phong 5}]\n', -' [0.99 pigment {White} finish {phong 10}]\n }\n}\n', -'}\n// Closed thething\n\n']) # Closing mesh object "thething" - -# Insert object into scene -# resultfile.write('object {thething}\n') -resultfile.write('#declare boxedthing = object {\n intersection {\n box {<-0.5, -0.5, 0>, <0.5, 0.5, 1.0>\n pigment {rgb <0.5, 0.5, 5>}\n }\n thething\n }\n}\n// Constructed CGS of mesh plus bounding box thus adding side walls and bottom\n\n') -resultfile.write('object {boxedthing}\n// Finally inserting CGS into the scene\n\n') + + ' gradient z\n', + ' texture_map {\n', + ' [0.01 pigment {Red} finish {phong 1}]\n', + ' [0.5 pigment {Blue} finish {phong 5}]\n', + ' [0.99 pigment {White} finish {phong 10}]\n }\n}\n', + '}\n// Closed thething\n\n', + '#declare boxedthing = object{\n', + ' intersection {\n', + ' box {<-0.5, -0.5, 0>, <0.5, 0.5, 1.0>\n', + ' pigment {rgb <0.5, 0.5, 5>}\n', + ' }\n thething\n }\n}', + '// Constructed CGS "boxedthing" of mesh plus bounding box thus adding side walls and bottom\n\n', + 'object {boxedthing}\n\n' + ]) # Closing mesh object "thething", then bounding box # Camera proportions = max(X,Y)/X