365 lines
15 KiB
Python
365 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
|
|
v3 = st[i] ; i+=1
|
|
v4=v3 # Pour pouvoir observer le changement de colonne dans la chaine aller/retour 2/1
|
|
while v1[0]+v2[0]+v3[0]!=3:
|
|
# On est dans la chaine aller-retour 2/1
|
|
|
|
if v4[0]!=v3[0]:
|
|
# Les deux colonnes ont disparu
|
|
# On peut créer le rectangle v1,v2,v3,v4
|
|
triangle1 = [pointIndexes[cols[v[0]]] + v[1] for v in (v1,v2,v3)]
|
|
triangle2 = [pointIndexes[cols[v[0]]] + v[1] for v in (v1 if v1[0]==v3[0] else v2,v3,v4)]
|
|
triangles.append(triangle1)
|
|
triangles.append(triangle2)
|
|
break
|
|
v4=v3
|
|
v3 = st[i] ; i+=1
|
|
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:
|
|
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,4,4,'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')
|
|
|
|
|
|
|