SonarDeLInfini/Python/objection.py

374 lines
15 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Aug 22 19:46:36 2019
@author: mysaa
"""
import numpy as np
from data import CollageWorldChunk
from perlin import CavernedNoise2,TestNoise
def getTriangles(x0,y0,chunk,xp,yp,xy):
nx,ny = chunk.size
newChunk = CollageWorldChunk(chunk,xp,yp,xy)
# pointIndexes = np.zeros((nx+1,ny+1),dtype=np.uint32)
# pointLengthes = np.zeros((nx+1,ny+1),dtype=np.uint32)
# points = []
#
#
# pos = 0
# for j in range(ny):
# for i in range(nx):
# carotte = [(x0+i/nx,y0+j/ny,z) for z in sorted([0.]+list(chunk.getColumn(i,j)))]
# points += carotte
# pointLengthes[i,j] = len(carotte)
# pointIndexes[i,j] = pos
# pos+=len(carotte)
# carotte = [(x0+1,y0+j/ny,z) for z in sorted([0.]+list(xp.getColumn(0,j)))]
# points += carotte
# pointLengthes[nx,j]= len(carotte)
# pointIndexes[nx,j] = pos
# pos+=len(carotte)
# for i in range(nx):
# carotte = [(x0+i/nx,y0+1,z) for z in sorted([0.]+list(yp.getColumn(i,0)))]
# points += carotte
# pointLengthes[i,ny] = len(carotte)
# pointIndexes[i,ny] = pos
# pos+=len(carotte)
# carotte = [(x0+1,y0+1,z) for z in sorted([0.]+list(xy.getColumn(0,0)))]
# points += carotte
# pointLengthes[nx,ny] = len(carotte)
# pointIndexes[nx,ny] = pos
points,pointIndexes = newChunk.getIndexed(fullCoords=True,addZero=True)
points=[(p[0]/nx+x0,p[1]/ny+y0,p[2]) for p in points]
pointLengthes = np.reshape([pointIndexes[i+1]-pointIndexes[i] for i in range(len(pointIndexes)-1)],(nx+1,ny+1))
pointIndexes = np.reshape(pointIndexes[:-1],(nx+1,ny+1))
print(points,pointIndexes,pointLengthes)
triangles = []
for x in range(nx*2):
for y in range(ny):
# On récupère les coordonées entières du triangle indicé (x,y)
if(x%2==0):
col0=(x//2 ,y )
col1=(x//2+1,y )
col2=(x//2 ,y+1)
else:
col0=(x//2+1,y+1)
col1=(x//2+1,y )
col2=(x//2 ,y+1)
# On récupère la liste des points dans la colonne
colonne0 = points[pointIndexes[col0[0],col0[1]]:pointIndexes[col0[0],col0[1]]+pointLengthes[col0[0],col0[1]]]
colonne1 = points[pointIndexes[col1[0],col1[1]]:pointIndexes[col1[0],col1[1]]+pointLengthes[col1[0],col1[1]]]
colonne2 = points[pointIndexes[col2[0],col2[1]]:pointIndexes[col2[0],col2[1]]+pointLengthes[col2[0],col2[1]]]
#print("colonne:",colonne1)
# st contient des triplets (numéro de colonne,index interne dans la colonne,coordonée z)
st = [(0,i,colonne0[i][2]) for i in range(len(colonne0))]
st += [(1,i,colonne1[i][2]) for i in range(len(colonne1))]
st += [(2,i,colonne2[i][2]) for i in range(len(colonne2))]
# On y trie par coordonée z
st = sorted(st,key=lambda c:c[2])
#Liste des coordonées des colonnes, pour pouvoir sélectionner les coordonées selon l'index de la colonne
cols = [col0,col1,col2]
# Là, tout est bon à peu près
i=0
try:
while i<len(st):
v1 = st[i] ; i+=1
v2 = st[i] ; i+=1
if v1[0]==v2[0]: continue #Cas où une colonne apparait puis disparaît
von = [v1,v2,None]
voff = [None,None,None]
while not None in von and voff!=[None,None,None]:
# On est dans la chaine aller-retour 2/1
v3 = st[i] ; i+=1
if voff[v3[0]]==None and von[v3[0]]!=None:
# Il s'agit d'un changement plein->vide
voff[v3[0]] = v3
else:
# Changement vide->plein
von[v3[0]] = v3
voff[v3[0]] = None
if not None in von and not None in voff:
# Les deux colonnes ont disparu
# On peut créer le rectangle entre les deux derniers à avoir disparu et leur point d'apparitions
v3,v4 = st[i],st[i-1]
v1,v2 = von[v3[0]],von[v4[0]]
triangle1 = [pointIndexes[cols[v[0]]] + v[1] for v in (v1,v2,v3)]
triangle2 = [pointIndexes[cols[v[0]]] + v[1] for v in (v1,v3,v4)]
triangles.append(triangle1)
triangles.append(triangle2)
break
else:
# On est dans le cas ou v1,v2,v3 correspondent à trois colonnes
# différentes (le cas (1,1,1) ayant déjà été filtré par la première condition)
# On ajoute le triangle en dessous
triangle = [pointIndexes[cols[v[0]]] + v[1] for v in (v1,v2,v3)]
triangles.append(triangle)
# On "attends" jusqu'à ce que les trois colonnes soient à nouveau vides
vs = [None,None,None]
while None in vs:
print("Quentin",st,i,vs)
v = st[i] ; i+=1
vs[v[0]] = v if vs[v[0]]==None else None
# Avec cette mthode, on déssine le triangle avec les derniers points étant apparus (les plus hauts)
triangle = [pointIndexes[cols[v[0]]] + v[1] for v in vs]
triangles.append(triangle)
continue
except ValueError:
# Une fin de liste a été atteinte, la colonne n'a pas été refermée: lance un warn
print("Attention ! Une colonne n'avait pas de toit. veuillez vérifier que vos colonnes aient un nombre impair de coordonées, merci !")
return points,triangles
########################################
# while i<len(st):
# #Plein
# v0 = st[i]
# i+=1
# v1 = st[i]
# i+=1
# if(v0[0] == v1[0]): # S'est la même colonne qui est apparu puis disparu
#
# print("Tribord")
# colz = cols[v0[0]]
# # Triangle sur les bords
# # Demis-points
# halfZ = (v0[2]+v1[2])/2
# #Les deux autres colonnes sont :
# cola = cols[(v0[0]+1)%3]
# colb = cols[(v0[0]+2)%3]
#
# zi1,zi2=pointIndexes[colz]+v0[1],pointIndexes[colz]+v1[1]
# print('OoOOoO',points[zi1],points[zi2])
#
## points.append( (x0+(cola[0])/nx,y0+(cola[1])/ny,halfZ) )
## points.append( (x0+(colb[0])/nx,y0+(colb[1])/ny,halfZ) )
##
## triangles.append([zi1,len(points)-1,len(points)-2])
## triangles.append([zi2,len(points)-1,len(points)-2])
# print("Tribord-fin")
# # print(points[-1],points[-2],points[zi1])
# #print(cola,colb,points[triangles[-1][0]-1],points[triangles[-1][1]-1],points[triangles[-1][2]-1])
#
# else: # Deux colonnes différentes ont apparus successivement
# # vs stoque les états des colonnes
# # vs[i] est l'état de la ième colonne, le point de st, dernier à apparaître si
# # cette colonne est présente, None sinon
# vs=[None,None,None]
# vs[v0[0]] = v0
# vs[v1[0]] = v1
# while None in vs and vs != [None,None,None]:# Tant qu'il y a une abscente ou une présente
# v2 = st[i]
# i+=1
# vs[v2[0]] = v2 if vs[v2[0]]==None else None
#
# if not None in vs:
# # Une face complète a été créée
# # Triangle complet
# # Face dessous (apparition de la colonne)
# triangle = [pointIndexes[cols[i]] + vs[i][1] for i in range(3)]
# triangles.append(triangle)
# #print("#",[points[triangle[i]] for i in range(0,3)])
#
#
# # On inverse le sens de vs, et stoque les premiers points à apparaître
# vs = [None,None,None]
# while None in vs and i<len(st):
# v2 = st[i]
# i+=1
# vs[v2[0]] = v2 if vs[v2[0]]==None else None
#
# #Face dessus
# if not None in vs:
# triangle = [pointIndexes[cols[i]] + vs[i][1] for i in range(3)]
# triangles.append(triangle)
# #print("0",[points[triangle[i]] for i in range(3)])
# else:
# # Il faut placer un carré
# #########################################
# print(points)
# return points,triangles
def getRectangles(x0,y0,chunk):
nx,ny = chunk.size
triangles = []
points = []
for x in range(nx) :
for y in range(ny):
for z in [0]+chunk.getColumn(x,y):
points.append([x/nx+x0,y/ny+y0,z])
points.append([x/nx+x0+1/nx,y/ny+y0,z])
points.append([x/nx+x0,y/ny+y0+1/ny,z])
points.append([x/nx+x0+1/nx,y/ny+y0+1/ny,z])
triangles.append([len(points)-4,len(points)-3,len(points)-2])
triangles.append([len(points)-3,len(points)-2,len(points)-1])
return points,triangles
def getRectCols(x0,y0,chunk):
nx,ny = chunk.size
triangles = []
points = []
e=0.3
for x in range(nx) :
for y in range(ny):
for z in [0]+chunk.getColumn(x,y):
points.append([x/nx+x0-e,y/ny+y0-e,z])
points.append([x/nx+x0+e,y/ny+y0-e,z])
points.append([x/nx+x0-e,y/ny+y0+e,z])
points.append([x/nx+x0+e,y/ny+y0+e/ny,z])
triangles.append([len(points)-4,len(points)-3,len(points)-2])
triangles.append([len(points)-3,len(points)-2,len(points)-1])
return points,triangles
def getFilled(x0,y0,chunk):
nx,ny = chunk.size
triangles = []
points = []
for x in range(nx) :
for y in range(ny):
boule = True
lz = 0
for z in sorted(chunk.getColumn(x,y)):
if boule:
points.append([x/nx+x0 ,y/ny+y0 ,z ])
points.append([x/nx+x0+1/nx,y/ny+y0 ,z ])
points.append([x/nx+x0 ,y/ny+y0+1/ny,z ])
points.append([x/nx+x0+1/nx,y/ny+y0+1/ny,z ])
points.append([x/nx+x0 ,y/ny+y0 ,lz])
points.append([x/nx+x0+1/nx,y/ny+y0 ,lz])
points.append([x/nx+x0 ,y/ny+y0+1/ny,lz])
points.append([x/nx+x0+1/nx,y/ny+y0+1/ny,lz])
l = len(points)
triangles.append([l-4,l-2,l-1])
triangles.append([l-4,l-3,l-1])
triangles.append([l-4,l-2,l-6])
triangles.append([l-4,l-8,l-6])
triangles.append([l-4,l-3,l-7])
triangles.append([l-4,l-8,l-7])
triangles.append([l-5,l-1,l-2])
triangles.append([l-5,l-6,l-2])
triangles.append([l-5,l-6,l-8])
triangles.append([l-5,l-7,l-8])
triangles.append([l-5,l-7,l-3])
triangles.append([l-5,l-1,l-3])
boule = not boule
lz = z
return points,triangles
def printObject(file,name,delta,points,triangles):
file.write("o "+name+"\n\n")
sf = lambda x : "%.6f" % float(x)
si = lambda x : str(int(x+1)+delta)
for p in points:
file.write("v "+sf(p[0])+" "+sf(p[1])+" "+sf(np.array(p[2])/20.)+"\n")
file.write("\n")
for t in triangles:
file.write("f "+" ".join([si(tp) for tp in t])+"\n")
def writeMap(filePath,noise,x0,y0,sx,sy,cx,cy,objType='triangle',log=print):
log("Génération de la carte")
generated = {}
formatter='\rÉcriture du chunk {};{} '+" "*(sx//10+sy//10)
for i in range(x0,sx+x0+(1 if objType=='triangle' else 0)):
for j in range(y0,sy+y0+(1 if objType=='triangle' else 0)):
log(formatter.format(i,j), end='\r')
generated[(i,j)] = noise.getChunk(i,j,(cx,cy))
log("Génération des objets")
file = open(filePath,"w+")
file.write("g carte\n")
delta=0
for i in range(x0,sx+x0):
for j in range(y0,sy+y0):
log(formatter.format(i,j), end='\r')
if objType=='triangle':
points,triangles = getTriangles(i,j,generated[(i,j)],generated[(i+1,j)],generated[(i,j+1)],generated[(i+1,j+1)])
elif objType=='rectangle':
points,triangles = getRectangles(i,j,generated[(i,j)])
elif objType=='filled':
points,triangles = getFilled(i,j,generated[(i,j)])
elif objType=='rectcols':
points,triangles = getRectCols(i,j,generated[(i,j)])
else:
raise ValueError("Je en connais pas le type d'objet "+objType)
printObject(file,"chunk_"+objType+"_"+str(i)+"-"+str(j),delta,points,triangles)
file.write("\n\n")
delta+=len(points)
log("\nTerminé ! "+" "*(sx//10+sy//10))
file.close()
noise = CavernedNoise2(93152)
size = 12
taille=16
#writeMap("gros.obj",noise,-size//2+1,-size//2+1,size,size,taille,taille,'triangle')
#writeMap("carte.obj",noise,2,1,1,1,16,16,'triangle')
writeMap("carteTri.obj",noise,-8,-8,16,16,16,16,'triangle')
#writeMap("carteRec.obj",noise,-8,-8,16,16,16,16,'rectangle')
#writeMap("carteFil.obj",noise,-8,-8,16,16,16,16,'filled')
#writeMap("carteRCo.obj",noise,-8,-8,16,16,16,16,'rectcols')
#xy0=-taille*size
#for x in range(2*taille):
# for y in range(2*taille):
#
# writeMap("render2/carte"+str(x)+","+str(y)+".obj",noise,xy0-size//2+x*size,xy0-size//2+y*size,size,size,'rectangle')