Compare commits

..

No commits in common. "master" and "ad14be7b75e32a040bdd86cf36684d7fe977c2eb" have entirely different histories.

4 changed files with 1019 additions and 1038 deletions

View File

@ -46,10 +46,10 @@ cela fait, vous pouvez allez sur [localhost:8000](http://localhost:8000) pour
lancer le streaming. Le navigateur télécharge progressivement les données et
les affiche.
Les modèles peuvent être
visualisés en ajoutant `?chemin/nom_du_modele.obj` à la fin de l'url. Par exemple,
[localhost:8000/?example/bunny.obja](http://localhost:8000/?example/bunny.obja)
chargera le modèle `bunny.obja` du dossier `example`. Ce modèle est un modèle
Les modèles doivent être sauvegardés dans le dossiers `assets`, et peuvent être
visualisés en ajouter `?nom_du_modele.obj` à la fin de l'url. Par exemple,
[localhost:8000/?example/suzanne.obja](http://localhost:8000/?example/suzanne.obja)
chargera le modèle `bunny.obj` du dossier `assets`. Ce modèle est un modèle
d'exemple, il commence par encoder la version basse résolution du [Stanford
bunny](https://graphics.stanford.edu/data/3Dscanrep/), translate tous ses
sommets, les retranslate vers leurs positions d'origine puis supprime toutes

File diff suppressed because it is too large Load Diff

94
obja.py
View File

@ -8,13 +8,11 @@ import random
obja model for python.
"""
class Face:
"""
The class that holds a, b, and c, the indices of the vertices of the face.
"""
def __init__(self, a, b, c, visible=True):
def __init__(self, a, b, c, visible = True):
self.a = a
self.b = b
self.c = c
@ -22,7 +20,7 @@ class Face:
def from_array(array):
"""
Initializes a face from an array of strings representing vertex indices (starting at 1)
Initializes a face from an array of strings representing vector indices (starting at 1)
"""
face = Face(0, 0, 0)
face.set(array)
@ -31,7 +29,7 @@ class Face:
def set(self, array):
"""
Sets a face from an array of strings representing vertex indices (starting at 1)
Sets a face from an array of strings representing vector indices (starting at 1)
"""
self.a = int(array[0].split('/')[0]) - 1
self.b = int(array[1].split('/')[0]) - 1
@ -54,7 +52,7 @@ class Face:
self.visible = other.visible
return self
def test(self, vertices, line="unknown"):
def test(self, vertices, line = "unknown"):
"""
Tests if a face references only vertices that exist when the face is declared.
"""
@ -71,12 +69,10 @@ class Face:
def __repr__(self):
return str(self)
class VertexError(Exception):
"""
An operation references a vertex that does not exist.
"""
def __init__(self, index, line):
"""
Creates the error from index of the referenced vertex and the line where the error occured.
@ -89,17 +85,15 @@ class VertexError(Exception):
"""
Pretty prints the error.
"""
return f"There is no vertex {self.index} (line {self.line})"
return f'There is no vector {self.index} (line {self.line})'
class FaceError(Exception):
"""
An operation references a face that does not exist.
"""
def __init__(self, index, line):
"""
Creates the error from index of the referenced face and the line where the error occurred.
Creates the error from index of the referenced face and the line where the error occured.
"""
self.line = line
self.index = index
@ -111,15 +105,13 @@ class FaceError(Exception):
"""
return f'There is no face {self.index} (line {self.line})'
class FaceVertexError(Exception):
"""
An operation references a face vertex that does not exist.
An operation references a face vector that does not exist.
"""
def __init__(self, index, line):
"""
Creates the error from index of the referenced face vertex and the line where the error occured.
Creates the error from index of the referenced face vector and the line where the error occured.
"""
self.line = line
self.index = index
@ -129,14 +121,12 @@ class FaceVertexError(Exception):
"""
Pretty prints the error.
"""
return f'Face has no vertex {self.index} (line {self.line})'
return f'Face has no vector {self.index} (line {self.line})'
class UnknownInstruction(Exception):
"""
An instruction is unknown.
"""
def __init__(self, instruction, line):
"""
Creates the error from instruction and the line where the error occured.
@ -151,25 +141,23 @@ class UnknownInstruction(Exception):
"""
return f'Instruction {self.instruction} unknown (line {self.line})'
class Model:
"""
The OBJA model.
"""
def __init__(self):
"""
Initializes an empty model.
Intializes an empty model.
"""
self.vertices = []
self.faces = []
self.line = 0
def get_vertex_from_string(self, string):
def get_vector_from_string(self, string):
"""
Gets a vertex from a string representing the index of the vertex, starting at 1.
Gets a vector from a string representing the index of the vector, starting at 1.
To get the vertex from its index, simply use model.vertices[i].
To get the vector from its index, simply use model.vertices[i].
"""
index = int(string) - 1
if index >= len(self.vertices):
@ -210,14 +198,14 @@ class Model:
self.vertices.append(np.array(split[1:], np.double))
elif split[0] == "ev":
self.get_vertex_from_string(split[1]).set(split[2:])
self.get_vector_from_string(split[1]).set(split[2:])
elif split[0] == "tv":
self.get_vertex_from_string(split[1]).translate(split[2:])
self.get_vector_from_string(split[1]).translate(split[2:])
elif split[0] == "f" or split[0] == "tf":
for i in range(1, len(split) - 2):
face = Face.from_array(split[i:i + 3])
face = Face.from_array(split[i:i+3])
face.test(self.vertices, self.line)
self.faces.append(face)
@ -235,16 +223,16 @@ class Model:
elif split[0] == "efv":
face = self.get_face_from_string(split[1])
vertex = int(split[2])
vector = int(split[2])
new_index = int(split[3]) - 1
if vertex == 1:
if vector == 1:
face.a = new_index
elif vertex == 2:
elif vector == 2:
face.b = new_index
elif vertex == 3:
elif vector == 3:
face.c = new_index
else:
raise FaceVertexError(vertex, self.line)
raise FaceVertexError(vector, self.line)
elif split[0] == "df":
self.get_face_from_string(split[1]).visible = False
@ -256,7 +244,6 @@ class Model:
return
# raise UnknownInstruction(split[0], self.line)
def parse_file(path):
"""
Parses a file and returns the model.
@ -265,15 +252,13 @@ def parse_file(path):
model.parse_file(path)
return model
class Output:
"""
The type for a model that outputs as obja.
"""
def __init__(self, output, random_color=False):
def __init__(self, output, random_color = False):
"""
Initializes the index mapping dictionaries.
Initializes the index mapping dictionnaries.
"""
self.vertex_mapping = dict()
self.face_mapping = dict()
@ -285,17 +270,16 @@ class Output:
Adds a new vertex to the model with the specified index.
"""
self.vertex_mapping[index] = len(self.vertex_mapping)
print('v {} {} {}'.format(vertex[0], vertex[1], vertex[2]), file=self.output)
print('v {} {} {}'.format(vertex[0], vertex[1], vertex[2]), file = self.output)
def edit_vertex(self, index, vertex):
"""
Changes the coordinates of a vertex.
"""
if len(self.vertex_mapping) == 0:
print('ev {} {} {} {}'.format(index, vertex[0], vertex[1], vertex[2]), file=self.output)
print('ev {} {} {} {}'.format(index, vertex[0], vertex[1],vertex[2]), file = self.output)
else:
print('ev {} {} {} {}'.format(self.vertex_mapping[index] + 1, vertex[0], vertex[1], vertex[2]),
file=self.output)
print('ev {} {} {} {}'.format(self.vertex_mapping[index] + 1, vertex[0], vertex[1],vertex[2]), file = self.output)
def add_face(self, index, face):
"""
@ -303,11 +287,11 @@ class Output:
"""
self.face_mapping[index] = len(self.face_mapping)
print('f {} {} {}'.format(
self.vertex_mapping[face.a] + 1,
self.vertex_mapping[face.b] + 1,
self.vertex_mapping[face.c] + 1,
),
file=self.output
self.vertex_mapping[face.a] + 1,
self.vertex_mapping[face.b] + 1,
self.vertex_mapping[face.c] + 1,
),
file = self.output
)
if self.random_color:
@ -316,7 +300,7 @@ class Output:
random.uniform(0, 1),
random.uniform(0, 1),
random.uniform(0, 1)),
file=self.output
file = self.output
)
def edit_face(self, index, face):
@ -324,15 +308,14 @@ class Output:
Changes the indices of the vertices of the specified face.
"""
print('ef {} {} {} {}'.format(
self.face_mapping[index] + 1,
self.vertex_mapping[face.a] + 1,
self.vertex_mapping[face.b] + 1,
self.vertex_mapping[face.c] + 1
),
file=self.output
self.face_mapping[index] + 1,
self.vertex_mapping[face.a] + 1,
self.vertex_mapping[face.b] + 1,
self.vertex_mapping[face.c] + 1
),
file = self.output
)
def main():
if len(sys.argv) == 1:
print("obja needs a path to an obja file")
@ -342,6 +325,5 @@ def main():
print(model.vertices)
print(model.faces)
if __name__ == "__main__":
main()

View File

@ -6,6 +6,7 @@
# Standard library imports.
import sys
if sys.version_info[0] < 3:
from SocketServer import ThreadingMixIn
import BaseHTTPServer
@ -16,7 +17,7 @@ else:
import http.server as BaseHTTPServer
from http.server import SimpleHTTPRequestHandler
from socketserver import ThreadingMixIn
from urllib.parse import quote, unquote
from urllib.parse import quote, unquote
from io import BytesIO as cStringIO
import os
@ -34,7 +35,6 @@ import errno
DATA_DIR = getcwd()
class ThreadingHTTPServer(ThreadingMixIn, BaseHTTPServer.HTTPServer):
pass
@ -61,7 +61,7 @@ class RequestHandler(SimpleHTTPRequestHandler):
in_file.seek(self.range_from)
# Add 1 because the range is inclusive
left_to_copy = 1 + self.range_to - self.range_from
buf_length = 64 * 1024
buf_length = 64*1024
bytes_copied = 0
while bytes_copied < left_to_copy:
read_buf = in_file.read(min(buf_length, left_to_copy - bytes_copied))
@ -125,7 +125,7 @@ class RequestHandler(SimpleHTTPRequestHandler):
file_size = fs.st_size
if self.range_from is not None:
if self.range_to is None or self.range_to >= file_size:
self.range_to = file_size - 1
self.range_to = file_size-1
self.send_header("Content-Range",
"bytes %d-%d/%d" % (self.range_from,
self.range_to,
@ -184,8 +184,8 @@ class RequestHandler(SimpleHTTPRequestHandler):
def translate_path(self, path):
""" Override to handle redirects.
"""
path = path.split('?', 1)[0]
path = path.split('#', 1)[0]
path = path.split('?',1)[0]
path = path.split('#',1)[0]
path = normpath(unquote(path))
words = path.split('/')
words = filter(None, words)
@ -240,13 +240,12 @@ def get_server(port=8000, next_attempts=0, serve_path=None):
else:
raise
def main(args=None):
if args is None:
args = sys.argv[1:]
PORT = 8000
if len(args) > 0:
if len(args)>0:
PORT = int(args[-1])
serve_path = DATA_DIR
if len(args) > 1:
@ -257,6 +256,6 @@ def main(args=None):
print("serving at port " + str(PORT))
httpd.serve_forever()
if __name__ == "__main__":
if __name__ == "__main__" :
main()