wavefront obj export
This commit is contained in:
parent
afbb9e7427
commit
b76f35a4a5
8 changed files with 80 additions and 7 deletions
|
@ -67,10 +67,19 @@ class Command(BaseCommand):
|
|||
renderer = MapRenderer(level.pk, minx, miny, maxx, maxy, access_permissions=options['permissions'],
|
||||
full_levels=options['full_levels'])
|
||||
|
||||
stl = renderer.render(get_engine(options['filetype']), center=not options['no_center'])
|
||||
data = stl.render()
|
||||
filename = os.path.join(settings.RENDER_ROOT,
|
||||
'level_%s_%s.%s' % (level.short_label,
|
||||
renderer.access_cache_key.replace('_', '-'),
|
||||
options['filetype']))
|
||||
|
||||
render = renderer.render(get_engine(options['filetype']), center=not options['no_center'])
|
||||
data = render.render(filename)
|
||||
if isinstance(data, tuple):
|
||||
other_data = data[1:]
|
||||
data = data[0]
|
||||
else:
|
||||
other_data = ()
|
||||
|
||||
open(filename, 'wb').write(data)
|
||||
for filename, data in other_data:
|
||||
open(filename, 'wb').write(data)
|
||||
|
|
|
@ -3,6 +3,7 @@ from django.core import checks
|
|||
|
||||
from c3nav.mapdata.render.engines.base import register_engine, get_engine, get_engine_filetypes # noqa
|
||||
from c3nav.mapdata.render.engines.openscad import OpenSCADEngine # noqa
|
||||
from c3nav.mapdata.render.engines.wavefront import WavefrontEngine # noqa
|
||||
from c3nav.mapdata.render.engines.stl import STLEngine # noqa
|
||||
from c3nav.mapdata.render.engines.svg import SVGEngine # noqa
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ class RenderEngine(ABC):
|
|||
self.background_rgb = tuple(int(background[i:i + 2], 16)/255 for i in range(1, 6, 2))
|
||||
|
||||
@abstractmethod
|
||||
def render(self) -> bytes:
|
||||
def render(self, filename=None) -> bytes:
|
||||
# render the image to png.
|
||||
pass
|
||||
|
||||
|
|
|
@ -196,7 +196,7 @@ class OpenGLEngine(Base3DEngine):
|
|||
|
||||
worker = OpenGLWorker()
|
||||
|
||||
def render(self) -> bytes:
|
||||
def render(self, filename=None) -> bytes:
|
||||
return self.worker.render(self.width, self.height, self.gl_scale, self.gl_offset, self.background_rgb,
|
||||
np.vstack(self.vertices).astype(np.float32).tobytes() if self.vertices else b'')
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ class OpenSCADEngine(Base3DEngine):
|
|||
b' convexity = 10\n' +
|
||||
b' );')
|
||||
|
||||
def render(self) -> bytes:
|
||||
def render(self, filename=None) -> bytes:
|
||||
result = (b'c3nav_export();\n\n' +
|
||||
b'module c3nav_export() {\n' +
|
||||
b'\n'.join((b' %s();' % group.replace('-', 'minus').encode())
|
||||
|
|
|
@ -21,7 +21,7 @@ class STLEngine(Base3DEngine):
|
|||
def _create_facet(self, facet) -> bytes:
|
||||
return self.facet_template % tuple(facet.flatten())
|
||||
|
||||
def render(self) -> bytes:
|
||||
def render(self, filename=None) -> bytes:
|
||||
facets = np.vstack(chain(*(chain(*v.values()) for v in self.vertices.values())))
|
||||
facets = np.hstack((np.cross(facets[:, 1]-facets[:, 0], facets[:, 2]-facets[:, 1]).reshape((-1, 1, 3)),
|
||||
facets))
|
||||
|
|
|
@ -83,7 +83,7 @@ class SVGEngine(RenderEngine):
|
|||
result += '</svg>'
|
||||
return result
|
||||
|
||||
def render(self):
|
||||
def render(self, filename=None):
|
||||
# render the image to png. returns bytes if f is None, otherwise it calls f.write()
|
||||
|
||||
if self.width == 256 and self.height == 256 and not self.g:
|
||||
|
|
63
src/c3nav/mapdata/render/engines/wavefront.py
Normal file
63
src/c3nav/mapdata/render/engines/wavefront.py
Normal file
|
@ -0,0 +1,63 @@
|
|||
import os
|
||||
from itertools import chain
|
||||
|
||||
import numpy as np
|
||||
|
||||
from c3nav.mapdata.render.engines import register_engine
|
||||
from c3nav.mapdata.render.engines.base3d import Base3DEngine
|
||||
|
||||
|
||||
@register_engine
|
||||
class WavefrontEngine(Base3DEngine):
|
||||
filetype = 'obj'
|
||||
|
||||
def _normal_normal(self, normal):
|
||||
return normal / (np.absolute(normal).max())
|
||||
|
||||
def render(self, filename=None):
|
||||
facets = np.vstack(chain(*(chain(*v.values()) for v in self.vertices.values())))
|
||||
vertices = tuple(set(tuple(vertex) for vertex in facets.reshape((-1, 3))))
|
||||
vertices_lookup = {vertex: i for i, vertex in enumerate(vertices, start=1)}
|
||||
|
||||
normals = np.cross(facets[:, 1] - facets[:, 0], facets[:, 2] - facets[:, 1]).reshape((-1, 3))
|
||||
normals = normals / np.amax(np.absolute(normals), axis=1).reshape((-1, 1))
|
||||
normals = tuple(set(tuple(normal) for normal in normals))
|
||||
normals_lookup = {normal: i for i, normal in enumerate(normals, start=1)}
|
||||
|
||||
materials = b''
|
||||
materials_filename = filename + '.mtl'
|
||||
for name, color in self.colors.items():
|
||||
materials += ((b'newmtl %s\n' % name.encode()) +
|
||||
(b'Ka %.2f %.2f %.2f\n' % color[:3]) +
|
||||
(b'Kd %.2f %.2f %.2f\n' % color[:3]) +
|
||||
b'Ks 0.00 0.00 0.00\n' +
|
||||
(b'd %.2f\n' % color[3]) +
|
||||
b'illum 2\n')
|
||||
|
||||
result = b'mtllib %s\n' % os.path.split(materials_filename)[-1].encode()
|
||||
result += b'o c3navExport\n'
|
||||
result += b''.join((b'v %.3f %.3f %.3f\n' % vertex) for vertex in vertices)
|
||||
result += b''.join((b'vn %.6f %.6f %.6f\n' % normal) for normal in normals)
|
||||
|
||||
for group, subgroups in self.groups.items():
|
||||
result += b'\n# ' + group.encode() + b'\n'
|
||||
for subgroup in subgroups:
|
||||
result += b'\n# ' + subgroup.encode() + b'\n'
|
||||
for i, vertices in enumerate(self.vertices[subgroup].values()):
|
||||
if not vertices:
|
||||
continue
|
||||
for j, facets in enumerate(vertices):
|
||||
if not facets.size:
|
||||
continue
|
||||
normals = np.cross(facets[:, 1] - facets[:, 0], facets[:, 2] - facets[:, 1]).reshape((-1, 3))
|
||||
normals = normals / np.amax(np.absolute(normals), axis=1).reshape((-1, 1))
|
||||
normals = tuple(normals_lookup[tuple(normal)] for normal in normals)
|
||||
result += ((b'g %s_%d_%d\n' % (subgroup.encode(), i, j)) +
|
||||
(b'usemtl %s\n' % subgroup.encode()) +
|
||||
b's off\n' +
|
||||
b''.join((b'f %d//%d %d//%d %d//%d\n' % (vertices_lookup[tuple(a)], normals[k],
|
||||
vertices_lookup[tuple(b)], normals[k],
|
||||
vertices_lookup[tuple(c)], normals[k],)
|
||||
for k, (a, b, c) in enumerate(facets)))
|
||||
)
|
||||
return result, (materials_filename, materials)
|
Loading…
Add table
Add a link
Reference in a new issue