Large update with mostly rewritten character subsystem

This commit is contained in:
Segey Lapin
2019-10-17 08:48:21 +03:00
parent 6e18c898b4
commit 0945ef76ee
224 changed files with 77854 additions and 13113 deletions

Binary file not shown.

View File

@@ -0,0 +1,222 @@
extends Spatial
func get_mesh(base: Node, mesh_name: String) -> ArrayMesh:
var queue = [base]
var mesh: ArrayMesh
while queue.size() > 0:
var item = queue[0]
queue.pop_front()
if item is MeshInstance && item.name == mesh_name && item.mesh:
mesh = item.mesh
break
for c in item.get_children():
queue.push_back(c)
return mesh
func get_mi(base: Node, mesh_name: String) -> MeshInstance:
var queue = [base]
var mi: MeshInstance
while queue.size() > 0:
var item = queue[0]
queue.pop_front()
if item is MeshInstance && item.name == mesh_name && item.mesh:
mi = item
break
for c in item.get_children():
queue.push_back(c)
return mi
#var modset_body = ModifierSet.new()
#var modset_top = ModifierSet.new()
#var modset_panties = ModifierSet.new()
var body_mi
var mesh_id
var _characters = []
var slots_female = ["body", "top", "panties"]
var slots_male = ["body"]
var helpers = {
"body": "base",
"top": "tights",
"panties": "tights"
}
var data_male = {}
var data_female = {}
var cha_male
var cha_female
func _ready():
seed(OS.get_unix_time())
# var base_male = characters.characters[0].instance()
# var base_female = characters.characters[1].instance()
# var fd = File.new()
# fd.open("characters/blendmaps.bin", File.READ);
# cha_male = CharacterModifierSet.new()
# cha_female = CharacterModifierSet.new()
# cha_female.set_base_name("body")
# cha_male.set_base_name("body")
# for e in slots_female:
# data_female[e] = {
# "mod": cha_female.create(e)
# }
# data_female[e].mod.set_uv_index(1)
# cha_female.set_helper(e, helpers[e])
# for e in slots_male:
# data_male[e] = {
# "mod": cha_male.create(e)
# }
# data_male[e].mod.set_uv_index(1)
# cha_male.set_helper(e, helpers[e])
# cha_female.add_mesh_scene(base_female)
# cha_male.add_mesh_scene(base_male)
# var bcount = fd.get_32()
# for f in range(bcount):
# var pos = fd.get_position()
# cha_female.load(fd)
# fd.seek(pos)
# cha_male.load(fd)
# print("done")
# # print(data["body"].mod.get_modifier_list())
# fd.close()
# cha_male.add_bone_modifier("head_scale", base_male, "head", Transform().scaled(Vector3(1.3, 1.3, 1.3)))
# cha_female.add_bone_modifier("head_scale", base_female, "head", Transform().scaled(Vector3(1.3, 1.3, 1.3)))
# cha_male.add_bone_modifier("head_up", base_male, "head", Transform().translated(Vector3(0.0, 0.3, 0.0)))
# cha_female.add_bone_modifier("head_up", base_female, "head", Transform().translated(Vector3(0.0, 0.3, 0.0)))
# cha_male.add_bone_modifier("shoulder_l_rot", base_male, "shoulder01_L", Transform().rotated(Vector3(1, 0, 0), 95 * PI / 360.0))
# cha_female.add_bone_modifier("shoulder_l_rot", base_female, "shoulder01_L", Transform().rotated(Vector3(1, 0, 0), 95 * PI / 360.0))
# cha_male.add_bone_modifier("height", base_male, "pelvis", Transform().scaled(Vector3(1.2, 1.2, 1.2)))
# cha_female.add_bone_modifier("height", base_female, "pelvis", Transform().scaled(Vector3(1.2, 1.2, 1.2)))
# cha_male.add_bone_modifier_symmetry("shoulder", base_male, "shoulder01_L", "shoulder01_R")
# cha_female.add_bone_modifier_symmetry("shoulder", base_female, "shoulder01_L", "shoulder01_R")
# var num = 4
# for k in range(num):
# if randf() > 0.5:
# var c = characters.characters[1].instance()
# add_child(c)
# c.translation.x = float(k)* 0.9 + randf() * 0.2 - float(num) * 0.9 * 0.5
# c.translation.z = 5.0
# c.rotation.y = PI
# var cdata = {}
# var mesh_id = cha_female.add_work_mesh_scene(c)
# cdata.scene = c
# cdata.mesh_id = mesh_id
# cdata.cha = cha_female
# _characters.push_back(cdata)
# else:
# var c = characters.characters[0].instance()
# add_child(c)
# c.translation.x = float(k) * 0.9 + randf() * 0.2 - float(num) * 0.9 * 0.5
# c.translation.z = 5.0
# c.rotation.y = PI
# var cdata = {}
# var mesh_id = cha_male.add_work_mesh_scene(c)
# cdata.scene = c
# cdata.mesh_id = mesh_id
# cdata.cha = cha_male
# _characters.push_back(cdata)
$Camera.translation.x = -8.0
$Camera.fov = 50.0
var change_delay = 0.1
var mod_id = "neck_width"
var mod_val = 0.0
var char_id = 0
var char_dist = 1.0
var timeout = 30.0
func _process(delta):
var mdist = 10.0
var farthest = -1
for ie in range(_characters.size()):
var e = _characters[ie]
var cpos = e.scene.global_transform.origin
var campos = $Camera.global_transform.origin
if mdist > abs(cpos.x - campos.x):
mdist = abs(cpos.x - campos.x)
farthest = ie
# if mdist > 3.0 && farthest >= 0:
# var cf = _characters[farthest]
# cf.cha.remove_work_mesh_scene(cf.mesh_id)
# cf.scene.queue_free()
# _characters.remove(farthest)
var c
var cdata = {}
if char_dist >= 1.0:
var can_spawn = true
for mc in _characters:
if abs(mc.scene.translation.x - $Camera.translation.x - 3.0) < 1.0:
can_spawn = false
break
if can_spawn:
var xform : = Transform()
xform.origin.x = $Camera.translation.x + 3.0
xform.origin.z = 5.0
xform.basis = xform.basis.rotated(Vector3(0, 1, 0), PI)
if randf() > 0.5:
c = characters.spawn_character(1, xform)
# c = characters.characters[1].instance()
# add_child(c)
# c.translation.x = $Camera.translation.x + 3.0
# c.translation.z = 5.0
# c.rotation.y = PI
# var mesh_id = cha_female.add_work_mesh_scene(c)
cdata.scene = c
# cdata.mesh_id = mesh_id
# cdata.cha = cha_female
_characters.push_back(cdata)
else:
c = characters.spawn_character(1, xform)
# c = characters.characters[0].instance()
# add_child(c)
# c.translation.x = $Camera.translation.x + 3.0
# c.translation.z = 5.0
# c.rotation.y = PI
# var mesh_id = cha_male.add_work_mesh_scene(c)
cdata.scene = c
# cdata.mesh_id = mesh_id
# cdata.cha = cha_male
_characters.push_back(cdata)
# var mod_name_list = cha_female.get_modifier_list()
var mod_name_list = characters.get_modifier_list(c)
for cset in range(160):
var _mod_id = mod_name_list[randi() % mod_name_list.size()]
var _mod_val = randf() - 0.5
characters.set_modifier_value(cdata.scene, _mod_id, _mod_val)
# cdata.cha.set_modifier_value(cdata.mesh_id, _mod_id, _mod_val)
# cdata.cha.modify(cdata.scene)
characters.update()
char_dist = 0.0
$Camera.translation.x += 0.25 * delta
# if change_delay <= 0:
# var mod_name_list = cha_female.get_modifier_list()
# char_id = randi() % _characters.size()
# mod_id = mod_name_list[randi() % mod_name_list.size()]
# mod_val = randf() - 0.5
# change_delay = 0.1
# else:
# change_delay -= delta
# var cmod = _characters[char_id]
# cmod.cha.set_modifier_value(cmod.mesh_id, mod_id, lerp(cmod.cha.get_modifier_value(cmod.mesh_id, mod_id), mod_val, 0.5))
# cmod.cha.modify()
var remove_ids = []
for ie in range(_characters.size()):
var e = _characters[ie]
if abs($Camera.translation.x + 3.0 - e.scene.translation.x) > 6.0:
characters.remove(e.scene)
# e.cha.remove_work_meshes(e.mesh_id)
# e.scene.queue_free()
remove_ids.push_back(ie)
# remove_ids.sort()
# remove_ids.invert()
for e in remove_ids:
_characters.remove(e)
char_dist += delta
timeout -= delta
if timeout <= 0.0:
get_tree().quit()
func _physics_process(delta):
if $Camera.translation.x >= 8.0:
$Camera.translation.x -= 16.0
for cm in _characters:
cm.scene.translation.x -=16.0
char_dist = 1.0

View File

@@ -0,0 +1,36 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://tests/character_mod_test.gd" type="Script" id=1]
[sub_resource type="BoxShape" id=1]
extents = Vector3( 20, 0.1, 20 )
[sub_resource type="CubeMesh" id=2]
size = Vector3( 40, 0.1, 40 )
subdivide_width = 8
subdivide_depth = 8
[sub_resource type="SpatialMaterial" id=3]
metallic = 0.8
roughness = 0.0
[node name="character_mod_test" type="Spatial"]
script = ExtResource( 1 )
[node name="Camera" type="Camera" parent="."]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.2, 8 )
[node name="StaticBody" type="StaticBody" parent="."]
[node name="CollisionShape" type="CollisionShape" parent="StaticBody"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 )
shape = SubResource( 1 )
[node name="MeshInstance" type="MeshInstance" parent="."]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 )
mesh = SubResource( 2 )
material/0 = SubResource( 3 )
[node name="DirectionalLight" type="DirectionalLight" parent="."]
transform = Transform( 1, 0, 0, 0, 0.0871556, 0.996195, 0, -0.996195, 0.0871556, 0, 20, 0 )
shadow_enabled = true

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,80 @@
extends Spatial
onready var layers = [$base, $panties, $pants]
var pairs = [[0, 2], [1, 2], [0, 1]]
var cache = []
func cache_data():
for k in range(layers.size()):
var arrays = layers[k].mesh.surface_get_arrays(0)
var data = {}
data.vertices = arrays[Mesh.ARRAY_VERTEX]
data.normals = arrays[Mesh.ARRAY_NORMAL]
data.indices = arrays[Mesh.ARRAY_INDEX]
data.bs = layers[k].mesh.surface_get_blend_shape_arrays(0)
data.mat = layers[k].get_surface_material(0)
data.mesh_mat = layers[k].mesh.surface_get_material(0)
data.shrunk = shrink_vertices(data.vertices, data.normals)
data.aabb = layers[k].get_aabb().grow(0.02)
cache.push_back(data)
func update_meshes():
for k in range(layers.size()):
layers[k].hide()
var arrays = layers[k].mesh.surface_get_arrays(0)
arrays[Mesh.ARRAY_VERTEX] = cache[k].vertices
layers[k].mesh.surface_remove(0)
layers[k].mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays, cache[k].bs)
layers[k].set_surface_material(0, cache[k].mat)
layers[k].mesh.surface_set_material(0, cache[k].mesh_mat)
layers[k].show()
func get_layer_vertices(layer: int) -> PoolVector3Array:
return cache[layer].vertices
func get_layer_normals(layer: int) -> PoolVector3Array:
return cache[layer].normals
func get_layer_triangles(layer: int) -> PoolIntArray:
return cache[layer].indices
func shrink_vertices(v: PoolVector3Array, n: PoolVector3Array) -> PoolVector3Array:
var ret : = PoolVector3Array()
ret.resize(v.size())
for i in range(v.size()):
ret[i] = v[i] - n[i].normalized() * 0.035
return ret
func triangle_check(layer_inner: int, layer_outer: int) -> PoolVector3Array:
var start_time = OS.get_unix_time()
var inner_verts = get_layer_vertices(layer_inner)
var inner_normals = get_layer_normals(layer_inner)
var inner_verts_shrunk = cache[layer_inner].shrunk
var outer_verts = get_layer_vertices(layer_outer)
var outer_triangles = get_layer_triangles(layer_outer)
for pt in range(inner_verts.size()):
if !cache[layer_outer].aabb.has_point(inner_verts_shrunk[pt]):
continue
for tri in range(0, outer_triangles.size(), 3):
var ray_pos = inner_verts_shrunk[pt]
var ray_dir = inner_verts[pt] - inner_verts_shrunk[pt]
var r = Geometry.ray_intersects_triangle(ray_pos, ray_dir,
outer_verts[outer_triangles[tri]],
outer_verts[outer_triangles[tri + 1]],
outer_verts[outer_triangles[tri + 2]])
if r:
var dst = inner_verts_shrunk[pt].distance_to(r)
if dst <= 0.035:
var ndist = clamp(dst / 0.035, 0.0, 1.0)
print(r, " ", ndist)
inner_verts[pt] = inner_verts_shrunk[pt].linear_interpolate(inner_verts[pt], ndist)
var end_time = OS.get_unix_time()
print(" triangle_check time: ", end_time - start_time)
return inner_verts
func update_layers(layer_inner: int, layer_outer: int):
var verts = triangle_check(layer_inner, layer_outer)
cache[layer_inner].vertices = verts
func _ready():
cache_data()
for p in pairs:
update_layers(p[0], p[1])
# $panties.hide()
# $pants.hide()
update_meshes()

View File

@@ -0,0 +1,32 @@
[gd_scene load_steps=7 format=2]
[ext_resource path="res://tests/clothes-test.escn" type="PackedScene" id=1]
[ext_resource path="res://tests/clothes-test.gd" type="Script" id=2]
[sub_resource type="SpatialMaterial" id=1]
albedo_color = Color( 0.207843, 0.807843, 0.286275, 1 )
[sub_resource type="SpatialMaterial" id=2]
albedo_color = Color( 0.827451, 0.513726, 0.513726, 1 )
[sub_resource type="CubeMesh" id=3]
[sub_resource type="SpatialMaterial" id=4]
albedo_color = Color( 0.176471, 0.733333, 0.745098, 1 )
[node name="clothes-test" instance=ExtResource( 1 )]
script = ExtResource( 2 )
[node name="Camera" parent="." index="1"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.00116634, 1.00691, 1.43248 )
[node name="panties" parent="." index="3"]
material/0 = SubResource( 1 )
[node name="pants" parent="." index="4"]
material/0 = SubResource( 2 )
[node name="MeshInstance" type="MeshInstance" parent="." index="5"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.759001, -1.82452 )
mesh = SubResource( 3 )
material/0 = SubResource( 4 )

78
proto2/tests/linreg.gd Normal file
View File

@@ -0,0 +1,78 @@
extends Reference
class_name LinReg
var data = []
var m = []
var b = []
var errors = []
var size = 30
func _init():
b.resize(size)
m.resize(size)
errors.resize(size)
for j in range(size):
b[j] = 0.0
m[j] = 1.0
print("hello linreg")
func sample_x():
var ret = []
for k in range(size):
ret.push_back(randf() * 2.0 - 1.0)
return ret
func iterate(delta):
var x = sample_x()
var y = 0.0
for nx in x:
y += nx * nx
y /= size
data.push_back([x, y])
linearRegression_gd()
# print(m)
# print(b)
print(errors)
return false
func linearRegression_sq():
var xsum = []
var num = []
var den = []
xsum.resize(size)
num.resize(size)
den.resize(size)
for j in range(xsum.size()):
xsum[j] = 0.0
num[j] = 0.0
den[j] = 0.0
b[j] = 0.0
m[j] = 1.0
var ysum = 0.0
for i in range(data.size()):
for j in range(data[i][0].size()):
xsum[j] += data[i][0][j]
ysum += data[i][1]
var xmean = []
for j in range(xsum.size()):
xmean.push_back(xsum[j] / data.size())
var ymean = ysum / data.size()
for i in range(data.size()):
var x = data[i][0]
var y = data[i][1]
for j in range(x.size()):
num[j] += (x[j] - xmean[j]) * (y - ymean)
den[j] += (x[j] - xmean[j]) * (x[j] - xmean[j])
for j in range(size):
m[j] = num[j] / den[j]
b[j] = ymean - m[j] * xmean[j]
var learning_rate = 0.15
func linearRegression_gd():
for e in range(30):
for i in range(data.size()):
var x = data[i][0]
var y = data[i][1]
for j in range(x.size()):
var guess = m[j] * x[j] + b[j]
var error = y - guess
errors[j] = error
m[j] += error * x[j] * learning_rate
b[j] += error * learning_rate

View File

@@ -0,0 +1,10 @@
extends MainLoop
var pct
func _initialize():
print("hello, world!")
pct = LinReg.new()
return
func _iteration(delta):
return pct.iterate(delta)

184
proto2/tests/nn.gd Normal file
View File

@@ -0,0 +1,184 @@
extends Reference
class_name NeuralNetwork
class Matrix:
var r
var c
var data = []
func _init(rows, cols):
r = rows
c = cols
data.resize(r * c)
for i in range(r):
for j in range(c):
data[i * c + j] = 0.0
func _s(row, col, value):
data[row * c + col] = value
func _g(row, col):
return data[row * c + col]
static func multiply(m1, m2):
assert(m1.c == m2.r)
var result = Matrix.new(m1.r, m2.c)
for i in range(result.r):
for j in range(result.c):
var sum = 0.0
for k in range(m1.c):
sum += m1.data[i * m1.c + k] * m2.data[k * m2.c + j]
result.data[i * result.c + j] = sum
return result
func multiply_elementwise(val):
if val is Matrix:
for i in range(data.size()):
data[i] *= val.data[i]
else:
for i in range(data.size()):
data[i] *= val
func add(val):
if val is Matrix:
for i in range(data.size()):
data[i] += val.data[i]
else:
for i in range(data.size()):
data[i] += val
func randomize():
for i in range(data.size()):
data[i] = floor(randf() * 2.0 - 1.0)
func transposed():
var result = Matrix.new(c, r)
for i in range(r):
for j in range(c):
result.data[j * result.c + i] = data[i * c + j]
return result
static func transpose(mat):
var result = Matrix.new(mat.c, mat.r)
for i in range(mat.r):
for j in range(mat.c):
result.data[j * result.c + i] = mat.data[i * mat.c + j]
return result
static func from_array(arr):
var m = Matrix.new(arr.size(), 1)
for i in range(m.data.size()):
m.data[i] = arr[i]
return m
static func subtract(m1, m2):
var result = Matrix.new(m1.r, m1.c)
for e in range(m1.data.size()):
result.data[e] = m1.data[e] - m2.data[e]
return result
func display():
print("[")
for i in range(r):
var mat_row = "\t[ "
for j in range(c):
mat_row += str(data[i * c + j])
if j < c - 1:
mat_row += " "
else:
mat_row += " ]"
print(mat_row)
print("]")
func map(obj, f):
for e in range(data.size()):
var val = obj.call(f, data[e])
data[e] = val
static func map_s(m, obj, f):
var result = Matrix.new(m.r, m.c)
for e in range(m.data.size()):
var val = obj.call(f, m.data[e])
result.data[e] = val
return result
func to_array():
return data
var input_nodes
var hidden_nodes
var output_nodes
var weights_ih
var weights_ho
var bias_h
var bias_o
var learning_rate = 0.1
# 3Blue1Brown
func tst(data):
return 1.0
func sigmoid(x):
return 1.0 / (1.0 + exp(-x))
func dsigmoid(x):
return x * (1.0 - x)
func feedforward(inputs_array):
# Hidden outputs
var inputs = Matrix.from_array(inputs_array)
var hidden = Matrix.multiply(weights_ih, inputs)
hidden.add(bias_h)
hidden.map(self, "sigmoid")
var output = Matrix.multiply(weights_ho, hidden)
output.add(bias_o)
output.map(self, "sigmoid")
return output.to_array()
func train(inputs_array, targets_array):
var inputs = Matrix.from_array(inputs_array)
var hidden = Matrix.multiply(weights_ih, inputs)
hidden.add(bias_h)
hidden.map(self, "sigmoid")
var outputs = Matrix.multiply(weights_ho, hidden)
outputs.add(bias_o)
outputs.map(self, "sigmoid")
var targets = Matrix.from_array(targets_array)
var output_errors = Matrix.subtract(targets, outputs)
var gradients = Matrix.map_s(outputs, self, "dsigmoid")
gradients.multiply_elementwise(output_errors)
gradients.multiply_elementwise(learning_rate)
var hidden_T = Matrix.transpose(hidden)
var weights_ho_deltas = Matrix.multiply(gradients, hidden_T)
weights_ho.add(weights_ho_deltas)
bias_o.add(gradients)
var who_t = Matrix.transpose(weights_ho)
var hidden_errors = Matrix.multiply(who_t, output_errors)
var hidden_gradients = Matrix.map_s(hidden, self, "dsigmoid")
hidden_gradients.multiply_elementwise(hidden_errors)
hidden_gradients.multiply_elementwise(learning_rate)
var inputs_T = Matrix.transpose(inputs)
var weights_ih_deltas = Matrix.multiply(hidden_gradients, inputs_T)
weights_ih.add(weights_ih_deltas)
bias_h.add(hidden_gradients)
# outputs.display()
# targets.display()
# error.display()
func _init(numI, numH, numO):
input_nodes = numI
hidden_nodes = numH
output_nodes = numO
weights_ih = Matrix.new(hidden_nodes, input_nodes)
weights_ho = Matrix.new(output_nodes, hidden_nodes)
weights_ih.randomize()
weights_ho.randomize()
bias_h = Matrix.new(hidden_nodes, 1)
bias_h.randomize()
bias_o = Matrix.new(output_nodes, 1)
bias_o.randomize()
# var matrix = Matrix.new(3, 2)
# matrix.randomize()
# matrix.display()
# var matrix2 = Matrix.new(2, 3)
# matrix2.randomize()
# matrix2.display()
# var matrix3 = Matrix.multiply(matrix, matrix2)
# matrix3.display()
# Matrix.transpose(matrix3).display()
# matrix3.map(self, "tst")
# matrix3.display()

28
proto2/tests/nn_test.gd Normal file
View File

@@ -0,0 +1,28 @@
extends MainLoop
var nn
var train_ds = [
[1, 0, 1],
[0, 1, 1],
[0, 0, 0],
[1, 1, 0]
]
func _initialize():
print("hello, world!")
nn = NeuralNetwork.new(2, 2, 1)
# var o = nn.feedforward([1,2,3])
# print(o)
for k in range(10000):
for k in range(train_ds.size()):
var d = randi() % train_ds.size()
var e = train_ds[d]
var inputs = [e[0], e[1]]
var targets = [e[2]]
nn.train(inputs, targets)
print(nn.feedforward([0, 0]))
print(nn.feedforward([1, 0]))
print(nn.feedforward([0, 1]))
print(nn.feedforward([1, 1]))
func _iteration(delta):
return true

View File

@@ -0,0 +1,21 @@
extends Reference
class_name Perceptron
var weights = []
var learning_rate = 0.15
func _init():
print("hello perceptron")
weights.resize(3)
for i in range(weights.size()):
weights[i] = randf()
func guess(inputs):
var sum = 0.0
for i in range(weights.size()):
sum += inputs[i] * weights[i]
var ret = sign(sum)
return ret
func train(inputs, target):
var g = guess(inputs)
var err = target - g
for i in range(weights.size()):
weights[i] += err * inputs[i] * learning_rate

View File

@@ -0,0 +1,34 @@
extends MainLoop
var pct
var dataset
func build_training_set():
var data = []
for k in range(400000):
var x = randf() * 2.0 - 1.0
var y = randf() * 2.0 - 1.0
var label = 0
if x > y:
label = 1
else:
label = -1
data.push_back([x, y, label])
return data
func _initialize():
print("hello, world!")
pct = Perceptron.new()
dataset = build_training_set()
for i in range(dataset.size()):
var pt = dataset[i]
pct.train([pt[0], pt[1], 1.0], pt[2])
return
func _iteration(delta):
if dataset.size() == 0:
return true
var pt = dataset.pop_front()
var output = pct.guess([pt[0], pt[1], 1.0])
print(output, " / ", pt[2] - output)
return false

5
proto2/tests/quit.gd Normal file
View File

@@ -0,0 +1,5 @@
tool
extends Node
func _ready():
get_tree().quit()

6
proto2/tests/quit.tscn Normal file
View File

@@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://tests/quit.gd" type="Script" id=1]
[node name="quit" type="Node"]
script = ExtResource( 1 )

View File

@@ -0,0 +1,191 @@
extends Spatial
var ch
var current_data = {}
var nn
func train(quality):
var inputs = []
var dk = current_data.keys()
dk.sort()
for k in dk:
if k == "quality":
continue
inputs.push_back(current_data[k])
nn.train(inputs, [quality])
func guess():
var inputs = []
var dk = current_data.keys()
dk.sort()
for k in dk:
if k == "quality":
continue
inputs.push_back(current_data[k])
var outputs = nn.feedforward(inputs)
$VBoxContainer/Label.text = str(outputs[0])
func train_by_data():
var data = []
var fd = File.new()
if fd.file_exists("res://tests/training_set.json"):
fd.open("res://tests/training_set.json", File.READ)
var json = JSON.parse(fd.get_as_text())
data = json.result
fd.close()
for t in range(data.size() * 5):
var inputs = []
var dataset = data[randi() % data.size()]
var dk = dataset.keys()
dk.sort()
for k in dk:
if k == "quality":
continue
inputs.push_back(dataset[k])
nn.train(inputs, [dataset["quality"]])
var cdirty = false
func change_scroll_value(value, mod_name):
characters.set_modifier_value(ch, mod_name, float(value) / 100.0)
cdirty = true
func update_controls():
for c in $VBoxContainer/s/b.get_children():
c.queue_free()
var mod_list = Array(characters.get_modifier_list(ch))
mod_list.sort()
for m in mod_list:
var item = HBoxContainer.new()
$VBoxContainer/s/b.add_child(item)
var t = Label.new()
item.add_child(t)
t.rect_min_size.x = 100.0
t.text = m
var scroll = HScrollBar.new()
item.add_child(scroll)
scroll.rect_min_size.x = 100.0
scroll.rect_min_size.y = 4.0
scroll.min_value = -100.0
scroll.max_value = 100.0
scroll.value = characters.get_modifier_value(ch, m) * 100.0
scroll.connect("value_changed", self, "change_scroll_value", [m])
func save_data(quality):
var data = []
var fd = File.new()
if fd.file_exists("res://tests/training_set.json"):
fd.open("res://tests/training_set.json", File.READ)
var json = JSON.parse(fd.get_as_text())
data = json.result
fd.close()
current_data["quality"] = quality
data.push_back(current_data)
fd.open("res://tests/training_set.json", File.WRITE)
fd.store_string(JSON.print(data, "\t", true))
fd.close()
print(current_data.keys().size())
func get_skeleton(base: Node):
var queue = [base]
var skel: Skeleton
while queue.size() > 0:
var item = queue[0]
queue.pop_front()
if item is Skeleton:
skel = item
break
for c in item.get_children():
queue.push_back(c)
return skel
func get_head_pos():
var skel = get_skeleton(ch)
var head_id = skel.find_bone("head")
var xform = skel.get_bone_global_pose(head_id)
return skel.global_transform.xform(xform.origin)
var rotate = 0
func select_ok():
train(0.5)
save_data(0.5)
remove()
call_deferred("spawn")
func select_bad():
train(0.0)
save_data(0.0)
remove()
call_deferred("spawn")
func select_good():
train(1.0)
save_data(1.0)
remove()
call_deferred("spawn")
func trigger_cam():
if $r/Camera.current:
$r/face_cam.global_transform.origin = get_head_pos() + Vector3(0, 0, 0.4)
$r/face_cam.make_current()
elif $r/face_cam.current:
$r/Camera.make_current()
func trigger_rotate():
rotate += 1
match(rotate):
0:
$r.rotation.y = 0.0
1:
$r.rotation.y = PI / 2.0
2:
$r.rotation.y = PI
3:
$r.rotation.y = PI * 3.0 / 4.0
5:
rotate = 0
$r.rotation.y = 0.0
func _ready():
$r/Camera.fov = 50.0
$VBoxContainer/bad.connect("pressed", self, "select_bad")
$VBoxContainer/ok.connect("pressed", self, "select_ok")
$VBoxContainer/good.connect("pressed", self, "select_good")
$VBoxContainer/face_trig.connect("pressed", self, "trigger_cam")
$VBoxContainer/rotate.connect("pressed", self, "trigger_rotate")
# characters.set_root_scene(self)
call_deferred("init_tail")
func init_tail():
remove()
spawn()
nn = NeuralNetwork.new(current_data.keys().size(), 160, 1)
train_by_data()
guess()
print(characters.get_modifier_list(ch))
var gender = -1
func spawn():
if randf() >= 0.5:
gender = 1
else:
gender = 0
ch = characters.spawn_character(gender, Transform().rotated(Vector3(0, 1, 0), PI))
current_data["gender"] = gender
var mod_name_list = characters.get_modifier_list(ch)
for cset in range(mod_name_list.size()):
var _mod_id = mod_name_list[cset]
var _mod_val = randf() * 1.5 - 0.75
characters.set_modifier_value(ch, _mod_id, _mod_val)
current_data[_mod_id] = _mod_val
# characters.modify(ch)
characters.update()
if nn:
guess()
update_controls()
func remove():
if ch:
characters.remove(ch)
func _process(delta):
if rotate == 4:
$r.rotation.y += delta
if cdirty:
characters.update()
var mod_name_list = characters.get_modifier_list(ch)
for cset in range(mod_name_list.size()):
var _mod_id = mod_name_list[cset]
current_data[_mod_id] = characters.get_modifier_value(ch, _mod_id)

View File

@@ -0,0 +1,100 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://tests/test-collect-data.gd" type="Script" id=1]
[sub_resource type="SpatialMaterial" id=1]
albedo_color = Color( 0.219608, 0.32549, 0.552941, 1 )
[sub_resource type="CubeMesh" id=2]
material = SubResource( 1 )
size = Vector3( 20, 0.2, 20 )
[sub_resource type="BoxShape" id=3]
extents = Vector3( 10, 0.1, 10 )
[node name="test-collect-data" type="Spatial"]
script = ExtResource( 1 )
[node name="r" type="Spatial" parent="."]
[node name="Camera" type="Camera" parent="r"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.2, 3 )
[node name="face_cam" type="Camera" parent="r"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.4, 0.4 )
[node name="MeshInstance" type="MeshInstance" parent="."]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.1, 0 )
mesh = SubResource( 2 )
material/0 = null
[node name="DirectionalLight" type="DirectionalLight" parent="."]
transform = Transform( 1, 0, 0, 0, 0.258819, 0.965926, 0, -0.965926, 0.258819, 0, 20, 0 )
[node name="StaticBody" type="StaticBody" parent="."]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.1, 0 )
[node name="CollisionShape" type="CollisionShape" parent="StaticBody"]
shape = SubResource( 3 )
[node name="VBoxContainer" type="VBoxContainer" parent="."]
anchor_bottom = 1.0
margin_right = 78.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="good" type="Button" parent="VBoxContainer"]
margin_right = 160.0
margin_bottom = 20.0
text = "Good"
[node name="ok" type="Button" parent="VBoxContainer"]
margin_top = 24.0
margin_right = 160.0
margin_bottom = 44.0
text = "OK"
[node name="bad" type="Button" parent="VBoxContainer"]
margin_top = 48.0
margin_right = 160.0
margin_bottom = 68.0
text = "Bad"
[node name="face_trig" type="Button" parent="VBoxContainer"]
margin_top = 72.0
margin_right = 160.0
margin_bottom = 92.0
text = "Face/Body"
[node name="rotate" type="Button" parent="VBoxContainer"]
margin_top = 96.0
margin_right = 160.0
margin_bottom = 116.0
text = "Rotate/Still"
[node name="HSeparator2" type="HSeparator" parent="VBoxContainer"]
margin_top = 120.0
margin_right = 160.0
margin_bottom = 124.0
[node name="Label" type="Label" parent="VBoxContainer"]
margin_top = 128.0
margin_right = 160.0
margin_bottom = 142.0
text = "Unknown"
[node name="HSeparator" type="HSeparator" parent="VBoxContainer"]
margin_top = 146.0
margin_right = 160.0
margin_bottom = 150.0
[node name="s" type="ScrollContainer" parent="VBoxContainer"]
margin_top = 154.0
margin_right = 160.0
margin_bottom = 600.0
rect_min_size = Vector2( 160, 40 )
size_flags_vertical = 3
scroll_horizontal_enabled = false
[node name="b" type="VBoxContainer" parent="VBoxContainer/s"]

View File

@@ -0,0 +1,137 @@
extends Node
var common = []
var common_path = "characters/common"
func load_data():
var fd = File.new()
fd.open("characters/common/data.json", File.READ)
var json = fd.get_as_text()
var json_result = JSON.parse(json)
var json_data = json_result.result
fd.close()
for e in json_data.files:
print("loading ", e)
var load_path = "res://" + e
var item = load(load_path)
assert(item)
common.push_back(item)
print("done loading ", e)
func get_mesh(base: Node, mesh_name: String) -> ArrayMesh:
var queue = [base]
var mesh: ArrayMesh
while queue.size() > 0:
var item = queue[0]
queue.pop_front()
if item is MeshInstance && item.name == mesh_name && item.mesh:
mesh = item.mesh
break
for c in item.get_children():
queue.push_back(c)
return mesh
func _ready():
print("loading data")
load_data()
print("data loaded")
var fd = File.new()
fd.open("characters/blendmaps.bin", File.WRITE);
var bcount = 0
for c in common:
var obj = c.instance()
for cm in ["base", "tights_helper", "robe_helper", "skirt_helper"]:
print(obj.name, " ", cm)
var mesh: ArrayMesh = get_mesh(obj, cm)
bcount += mesh.get_blend_shape_count()
fd.store_32(bcount)
var deflate_size = 0
var rle_size = 0
for c in common:
var obj = c.instance()
print(obj.name)
for cm in ["base", "tights_helper", "robe_helper", "skirt_helper"]:
print(cm)
var mesh: ArrayMesh = get_mesh(obj, cm)
var base_array = mesh.surface_get_arrays(0)
assert(base_array.size() > 0)
var shape_arrays = mesh.surface_get_blend_shape_arrays(0)
assert(shape_arrays.size() > 0)
for x in range(mesh.get_blend_shape_count()):
var triset = TriangleSet.new()
var shape_name = mesh.get_blend_shape_name(x)
print(obj.name, " ", shape_name, " ", x)
var shape_array = shape_arrays[x]
triset.create_from_array_shape(base_array, shape_array)
var img = Image.new()
var imgn = Image.new()
img.create(512, 512, false, Image.FORMAT_RGBA8)
imgn.create(512, 512, false, Image.FORMAT_RGBA8)
triset.draw(img, imgn, 1)
var rledata = triset.get_data(img, imgn)
triset.save(fd, cm.replace("_helper", "") + ":" + shape_name, img, imgn)
# var minp = triset.get_min()
# var maxp = triset.get_max()
# var min_normal = triset.get_min_normal()
# var max_normal = triset.get_max_normal()
# fd.store_pascal_string(cm.replace("_helper", "") + ":" + shape_name)
# fd.store_float(minp.x)
# fd.store_float(minp.y)
# fd.store_float(minp.z)
# fd.store_float(maxp.x)
# fd.store_float(maxp.y)
# fd.store_float(maxp.z)
# fd.store_32(img.get_width())
# fd.store_32(img.get_height())
# fd.store_32(img.get_format())
# fd.store_32(img.get_data().size())
# var imgbuf = img.get_data().compress(File.COMPRESSION_FASTLZ)
# fd.store_32(imgbuf.size())
# fd.store_buffer(imgbuf)
# fd.store_float(min_normal.x)
# fd.store_float(min_normal.y)
# fd.store_float(min_normal.z)
# fd.store_float(max_normal.x)
# fd.store_float(max_normal.y)
# fd.store_float(max_normal.z)
# fd.store_32(imgn.get_width())
# fd.store_32(imgn.get_height())
# fd.store_32(imgn.get_format())
# fd.store_32(imgn.get_data().size())
# var imgnbuf = imgn.get_data().compress(File.COMPRESSION_FASTLZ)
# print("rle size = ", rledata.size(), ", deflate size = ", imgbuf.size() + imgnbuf.size())
# rle_size += rledata.size()
# deflate_size += imgbuf.size() + imgnbuf.size()
# fd.store_32(imgnbuf.size())
# fd.store_buffer(imgnbuf)
img.save_png("res://" + common_path + "/" + cm + "_" + shape_name + ".png")
imgn.save_png("res://" + common_path + "/" + cm + "_" + shape_name + "_normal.png")
fd.close()
print("saved")
var c = characters.characters[1]
var obj = c.instance()
print(obj.name)
print("body")
var mesh_target: ArrayMesh = load("res://characters/accessory/female/body/body_default.mesh")
print("base")
var mesh_base: ArrayMesh = get_mesh(common[0].instance(), "base")
assert(mesh_target)
assert(mesh_base)
var base_array = mesh_base.surface_get_arrays(0)
var target_array = mesh_target.surface_get_arrays(0)
var triset = TriangleSet.new()
triset.create_from_mesh_difference(base_array, 1, target_array, 1)
var img = Image.new()
var imgn = Image.new()
img.create(512, 512, false, Image.FORMAT_RGBA8)
imgn.create(512, 512, false, Image.FORMAT_RGBA8)
triset.draw(img, imgn, 1)
img.save_png("res://" + common_path + "/female.png")
imgn.save_png("res://" + common_path + "/female_normal.png")
var minp = triset.get_min()
var maxp = triset.get_max()
var min_normal = triset.get_min_normal()
var max_normal = triset.get_max_normal()
print([minp, maxp, min_normal, max_normal])
print("complete")
print("deflate size: ", deflate_size, " rle size: ", rle_size)

View File

@@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://tests/test-triangles.gd" type="Script" id=1]
[node name="test-triangles" type="Node"]
script = ExtResource( 1 )

View File

@@ -0,0 +1,12 @@
extends Node
func _ready():
var dnatool : = DNATool.new()
var pt : = Vector3(0.25, 0.25, 3)
var p1 : = Vector3(0, 0, 0)
var p2 : = Vector3(1, 0, 0)
var p3 : = Vector3(0, 1, 0)
var bc = dnatool.get_baricentric(pt, p1, p2, p3)
print(bc)
print([1.0 - bc.x, 1.0 - bc.y, 1.0 - bc.z])
print(p1 * bc.x + p2 * bc.y + p3 * bc.z)

View File

@@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://tests/test_baricentric.gd" type="Script" id=1]
[node name="test_baricentric" type="Node"]
script = ExtResource( 1 )

View File

@@ -0,0 +1,41 @@
extends Spatial
var instances = []
var genders = ["male", "female"]
var count = 10
var x = -float(count - 1) / 2.0 * 0.6
func create_ch():
for k in range(count):
var instance = CharacterInstanceList.create(genders[randi() % genders.size()], Transform().translated(Vector3(x, 0, 0)).rotated(Vector3(0, 1, 0), PI), {})
var ml = CharacterInstanceList.get_base_modifier_list()
print(ml)
for k in ml:
CharacterInstanceList.set_mod_value(instance, k, randf() * 0.5)
instances.push_back(instance)
x += 0.6
CharacterInstanceList.update()
print("OK")
func _ready():
seed(OS.get_unix_time())
CharacterGenderList.config()
call_deferred("create_ch")
var quit_delay = 1.4
func _process(delta):
quit_delay -= delta
if quit_delay <= 0.0:
get_tree().quit()
elif instances.size() < 200:
var instance = CharacterInstanceList.create(genders[randi() % genders.size()], Transform().translated(Vector3(x, 0, 0)).rotated(Vector3(0, 1, 0), PI), {})
var ml = CharacterInstanceList.get_base_modifier_list()
for k in ml:
CharacterInstanceList.set_mod_value(instance, k, randf() * 0.5)
instances.push_back(instance)
print(instances.size())
x += 0.6
CharacterInstanceList.update()

View File

@@ -0,0 +1,28 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://tests/test_character_refactor.gd" type="Script" id=1]
[sub_resource type="CubeMesh" id=1]
size = Vector3( 20, 0.1, 20 )
[sub_resource type="ConcavePolygonShape" id=2]
data = PoolVector3Array( -10, 0.05, 10, 10, 0.05, 10, -10, -0.05, 10, 10, 0.05, 10, 10, -0.05, 10, -10, -0.05, 10, 10, 0.05, -10, -10, 0.05, -10, 10, -0.05, -10, -10, 0.05, -10, -10, -0.05, -10, 10, -0.05, -10, 10, 0.05, 10, 10, 0.05, -10, 10, -0.05, 10, 10, 0.05, -10, 10, -0.05, -10, 10, -0.05, 10, -10, 0.05, -10, -10, 0.05, 10, -10, -0.05, -10, -10, 0.05, 10, -10, -0.05, 10, -10, -0.05, -10, 10, 0.05, 10, -10, 0.05, 10, 10, 0.05, -10, -10, 0.05, 10, -10, 0.05, -10, 10, 0.05, -10, -10, -0.05, 10, 10, -0.05, 10, -10, -0.05, -10, 10, -0.05, 10, 10, -0.05, -10, -10, -0.05, -10 )
[node name="test_character_refactor" type="Spatial"]
script = ExtResource( 1 )
[node name="Camera" type="Camera" parent="."]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.3, 4 )
fov = 50.0
[node name="MeshInstance" type="MeshInstance" parent="."]
mesh = SubResource( 1 )
material/0 = null
[node name="StaticBody" type="StaticBody" parent="MeshInstance"]
[node name="CollisionShape" type="CollisionShape" parent="MeshInstance/StaticBody"]
shape = SubResource( 2 )
[node name="DirectionalLight" type="DirectionalLight" parent="."]
transform = Transform( 1, 0, 0, 0, -1.62921e-07, 1, 0, -1, -1.62921e-07, 0, 20, 0 )

File diff suppressed because it is too large Load Diff