Compare commits

..
121 changed files with 4562 additions and 2648 deletions

No files matched your search

Regular → Executable
View File
File mode changed.
-3
View File
@@ -1,3 +0,0 @@
{
"effect": "effects/confetti.json"
}
-102
View File
@@ -1,102 +0,0 @@
{
"name": "Sparkler - бенгальский огонь",
"emitters":
[
{
"name": "Spark",
"maxParticles": 300,
"preloading": 100,
"texturePath": "textures/spark.png",
"textureSize": [ 10, 10 ],
"hasInertion": "false",
"gravity": [0, 0, 0],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0,
"value": 0
},
{
"t": 1,
"value": 5
}
]
},
"spawnRange":
{
"value": [ 0, 0, 0, 0 ]
},
"lifeTime":
{
"value": 2
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"rotation_system": "PARTICLE_EFFECT",
"coords":
{
"interpolation": "CUBIC_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 100, 0, 0]
},
{
"t": 0.1,
"value": [ 95, 30, 0]
},
{
"t": 0.5,
"value": [ 0, 100, 0]
},
{
"t": 1.0,
"value": [ -100, 0, 0]
},
{
"t": 1.5,
"value": [ 0, -100, 0]
},
{
"t": 1.9,
"value": [ 95, -30, 0]
},
{
"t": 2.000,
"value": [ 100, 0, 0]
}
]
},
"rotation":
{
"value": [ 0, 0, 0 ]
},
"scale":
{
"value": 1
},
"color":
{
"value": [ 1, 1, 0, 1 ]
}
}
]
}
-94
View File
@@ -1,94 +0,0 @@
{
"name": "Sparkler - бенгальский огонь",
"emitters":
[
{
"name": "Spark",
"maxParticles": 300,
"preloading": 100,
"texturePath": "textures/spark.png",
"textureSize": [ 10, 10 ],
"hasInertion": "false",
"gravity": [0, 0, 0],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0,
"value": 0
},
{
"t": 1,
"value": 5
}
]
},
"spawnRange":
{
"value": [ 0, 0, 0, 0 ]
},
"lifeTime":
{
"value": 2
},
"coords_system": "PARTICLE_EFFECT",
"coords_axis_system": "PARTICLE_BIRTH",
"rotation_system": "PARTICLE_EFFECT",
"coords":
{
"interpolation": "CUBIC_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0]
},
{
"t": 0.5,
"value": [ 50, 20, 0]
},
{
"t": 1.0,
"value": [ 100, 100, 0]
},
{
"t": 1.5,
"value": [ 150, 180, 0]
},
{
"t": 2.000,
"value": [ 200, 200, 0]
}
]
},
"rotation":
{
"value": [ 0, 0, 0 ]
},
"scale":
{
"value": 1
},
"color":
{
"value": [ 1, 1, 0, 1 ]
}
}
]
}
-116
View File
@@ -1,116 +0,0 @@
{
"emitters":
[
{
"maxParticles": 300,
"preloading": 100,
"texturePath": "textures/spark.png",
"textureSize": [ 10, 10 ],
"hasInertion": "false",
"gravity": [0, 0, 0],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0,
"value": 0
},
{
"t": 1,
"value": 5
}
]
},
"spawnRange":
{
"value": [ 0, 0, 0, 360 ]
},
"lifeTime":
{
"value": 3
},
"coords_system": "PARTICLE_EFFECT",
"offset_axis_system": "PARTICLE_EFFECT",
"coords_axis_system": "PARTICLE_BIRTH",
"rotation_system": "PARTICLE_EFFECT",
"coords":
{
"interpolation": "CUBIC_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0]
},
{
"t": 3.000,
"value": [ 500, 0, 0]
}
]
},
"offset":
{
"interpolation": "CUBIC_SPLINE",
"timelineType": "LOOPED",
"timeline":
[
{
"t": 0.000,
"value": [ 10, 0, 0]
},
{
"t": 0.025,
"value": [ 9.5, 3, 0]
},
{
"t": 0.125,
"value": [ 0, 10, 0]
},
{
"t": 0.25,
"value": [ -10, 0, 0]
},
{
"t": 0.375,
"value": [ 0, -10, 0]
},
{
"t": 0.475,
"value": [ 9.5, -3, 0]
},
{
"t": 0.5,
"value": [ 10, 0, 0]
}
]
},
"rotation":
{
"value": [ 0, 0, 0 ]
},
"scale":
{
"value": 1
},
"color":
{
"value": [ 1, 1, 0, 1 ]
}
}
]
}
-861
View File
@@ -1,861 +0,0 @@
{
"emitters":
[
{
"maxParticles": 10000,
"preloading": 1000,
"texturePath": "textures/star-white.png",
"textureSize": [ 5, 5 ],
"gravity": [ 0, -100, 0 ],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": 0
},
{
"t": 1.000,
"value": 15
}
]
},
"spawnRange":
{
"value": [ 0, 0, 360, 0]
},
"lifeTime":
{
"min": 10,
"max": 10
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"offset_axis_system": "PARTICLE_BIRTH",
"rotation_system": "PARTICLE_ITSELF",
"coords":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0 ]
},
{
"t": 1.000,
"min": [ 100, 0, 0 ],
"max": [ 200, 0, 0 ]
}
]
},
"offset":
{
"interpolation": "CUBIC_SPLINE",
"timelineType": "LOOPED",
"timeOffset":
{
"min": 0,
"max": 1
},
"timeline":
[
{
"t": 0.00,
"value": [ 10, 0, 0]
},
{
"t": 0.05,
"value": [ 9.5, 3, 0]
},
{
"t": 0.25,
"value": [ 0, 10, 0]
},
{
"t": 0.5,
"value": [ -10, 0, 0]
},
{
"t": 0.75,
"value": [ 0, -10, 0]
},
{
"t": 0.95,
"value": [ 9.5, -3, 0]
},
{
"t": 1.0,
"value": [ 10, 0, 0]
}
]
},
"rotation":
{
"interpolation": "LINEAR_SPLINE",
"timeOffset":
{
"min": 0,
"max": 1
},
"timelineType": "LOOPED",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 45, 0 ]
},
{
"t": 1.000,
"value": [ 360, 45, 0 ]
}
]
},
"scale":
{
"interpolation": "DISCRETE",
"timeline":
[
{
"min": 1,
"max": 2
}
]
},
"color":
{
"value": [ 0, 1, 0, 1 ]
}
},
{
"name": "Magic Star",
"maxParticles": 10000,
"preloading": 1000,
"texturePath": "textures/rect-white.png",
"textureSize": [ 5, 5 ],
"gravity": [ 0, -100, 0 ],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": 0
},
{
"t": 1.000,
"value": 15
}
]
},
"spawnRange":
{
"value": [ 0, 0, 360, 0]
},
"lifeTime":
{
"min": 10,
"max": 10
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"offset_axis_system": "PARTICLE_BIRTH",
"rotation_system": "PARTICLE_EFFECT",
"coords":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0 ]
},
{
"t": 1.000,
"min": [ 100, 0, 0 ],
"max": [ 200, 0, 0 ]
}
]
},
"offset":
{
"interpolation": "CUBIC_SPLINE",
"timelineType": "LOOPED",
"timeOffset":
{
"min": 0,
"max": 1
},
"timeline":
[
{
"t": 0.00,
"value": [ 10, 0, 0]
},
{
"t": 0.05,
"value": [ 9.5, 3, 0]
},
{
"t": 0.25,
"value": [ 0, 10, 0]
},
{
"t": 0.5,
"value": [ -10, 0, 0]
},
{
"t": 0.75,
"value": [ 0, -10, 0]
},
{
"t": 0.95,
"value": [ 9.5, -3, 0]
},
{
"t": 1.0,
"value": [ 10, 0, 0]
}
]
},
"rotation":
{
"interpolation": "LINEAR_SPLINE",
"timeOffset":
{
"min": 0,
"max": 1
},
"timelineType": "LOOPED",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 45, 0 ]
},
{
"t": 1.000,
"value": [ 360, 45, 0 ]
}
]
},
"scale":
{
"interpolation": "DISCRETE",
"timeline":
[
{
"min": 1,
"max": 2
}
]
},
"color":
{
"value": [ 1, 0, 0, 1 ]
}
},
{
"name": "Magic Star",
"maxParticles": 10000,
"preloading": 1000,
"texturePath": "textures/circle-white.png",
"textureSize": [ 5, 5 ],
"gravity": [ 0, -100, 0 ],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": 0
},
{
"t": 1.000,
"value": 15
}
]
},
"spawnRange":
{
"value": [ 0, 0, 360, 0]
},
"lifeTime":
{
"min": 10,
"max": 10
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"offset_axis_system": "PARTICLE_BIRTH",
"rotation_system": "PARTICLE_EFFECT",
"coords":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0 ]
},
{
"t": 1.000,
"min": [ 100, 0, 0 ],
"max": [ 200, 0, 0 ]
}
]
},
"offset":
{
"interpolation": "CUBIC_SPLINE",
"timelineType": "LOOPED",
"timeOffset":
{
"min": 0,
"max": 1
},
"timeline":
[
{
"t": 0.00,
"value": [ 10, 0, 0]
},
{
"t": 0.05,
"value": [ 9.5, 3, 0]
},
{
"t": 0.25,
"value": [ 0, 10, 0]
},
{
"t": 0.5,
"value": [ -10, 0, 0]
},
{
"t": 0.75,
"value": [ 0, -10, 0]
},
{
"t": 0.95,
"value": [ 9.5, -3, 0]
},
{
"t": 1.0,
"value": [ 10, 0, 0]
}
]
},
"rotation":
{
"interpolation": "LINEAR_SPLINE",
"timeOffset":
{
"min": 0,
"max": 1
},
"timelineType": "LOOPED",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 45, 0 ]
},
{
"t": 1.000,
"value": [ 360, 45, 0 ]
}
]
},
"scale":
{
"interpolation": "DISCRETE",
"timeline":
[
{
"min": 1,
"max": 2
}
]
},
"color":
{
"value": [ 0, 0, 1, 1 ]
}
},
{
"name": "Magic Star",
"maxParticles": 10000,
"preloading": 1000,
"texturePath": "textures/star-white.png",
"textureSize": [ 5, 5 ],
"gravity": [ 0, -100, 0 ],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": 0
},
{
"t": 1.000,
"value": 15
}
]
},
"spawnRange":
{
"value": [ 0, 0, 360, 0]
},
"lifeTime":
{
"min": 10,
"max": 10
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"offset_axis_system": "PARTICLE_BIRTH",
"rotation_system": "PARTICLE_EFFECT",
"coords":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0 ]
},
{
"t": 1.000,
"min": [ 100, 0, 0 ],
"max": [ 200, 0, 0 ]
}
]
},
"offset":
{
"interpolation": "CUBIC_SPLINE",
"timelineType": "LOOPED",
"timeOffset":
{
"min": 0,
"max": 1
},
"timeline":
[
{
"t": 0.00,
"value": [ 10, 0, 0]
},
{
"t": 0.05,
"value": [ 9.5, 3, 0]
},
{
"t": 0.25,
"value": [ 0, 10, 0]
},
{
"t": 0.5,
"value": [ -10, 0, 0]
},
{
"t": 0.75,
"value": [ 0, -10, 0]
},
{
"t": 0.95,
"value": [ 9.5, -3, 0]
},
{
"t": 1.0,
"value": [ 10, 0, 0]
}
]
},
"rotation":
{
"interpolation": "LINEAR_SPLINE",
"timeOffset":
{
"min": 0,
"max": 1
},
"timelineType": "LOOPED",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 45, 0 ]
},
{
"t": 1.000,
"value": [ 360, 45, 0 ]
}
]
},
"scale":
{
"interpolation": "DISCRETE",
"timeline":
[
{
"min": 1,
"max": 2
}
]
},
"color":
{
"value": [ 1, 1, 0, 1 ]
}
},
{
"name": "Magic Star",
"maxParticles": 10000,
"preloading": 1000,
"texturePath": "textures/rect-white.png",
"textureSize": [ 5, 5 ],
"gravity": [ 0, -100, 0 ],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": 0
},
{
"t": 1.000,
"value": 15
}
]
},
"spawnRange":
{
"value": [ 0, 0, 360, 0]
},
"lifeTime":
{
"min": 10,
"max": 10
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"offset_axis_system": "PARTICLE_BIRTH",
"rotation_system": "PARTICLE_EFFECT",
"coords":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0 ]
},
{
"t": 1.000,
"min": [ 100, 0, 0 ],
"max": [ 200, 0, 0 ]
}
]
},
"offset":
{
"interpolation": "CUBIC_SPLINE",
"timelineType": "LOOPED",
"timeOffset":
{
"min": 0,
"max": 1
},
"timeline":
[
{
"t": 0.00,
"value": [ 10, 0, 0]
},
{
"t": 0.05,
"value": [ 9.5, 3, 0]
},
{
"t": 0.25,
"value": [ 0, 10, 0]
},
{
"t": 0.5,
"value": [ -10, 0, 0]
},
{
"t": 0.75,
"value": [ 0, -10, 0]
},
{
"t": 0.95,
"value": [ 9.5, -3, 0]
},
{
"t": 1.0,
"value": [ 10, 0, 0]
}
]
},
"rotation":
{
"interpolation": "LINEAR_SPLINE",
"timeOffset":
{
"min": 0,
"max": 1
},
"timelineType": "LOOPED",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 45, 0 ]
},
{
"t": 1.000,
"value": [ 360, 45, 0 ]
}
]
},
"scale":
{
"interpolation": "DISCRETE",
"timeline":
[
{
"min": 1,
"max": 2
}
]
},
"color":
{
"value": [ 0, 1, 1, 1 ]
}
},
{
"name": "Magic Star",
"maxParticles": 10000,
"preloading": 1000,
"texturePath": "textures/circle-white.png",
"textureSize": [ 5, 5 ],
"gravity": [ 0, -100, 0 ],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": 0
},
{
"t": 1.000,
"value": 15
}
]
},
"spawnRange":
{
"value": [ 0, 0, 360, 0]
},
"lifeTime":
{
"min": 10,
"max": 10
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"offset_axis_system": "PARTICLE_BIRTH",
"rotation_system": "PARTICLE_EFFECT",
"coords":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0 ]
},
{
"t": 1.000,
"min": [ 100, 0, 0 ],
"max": [ 200, 0, 0 ]
}
]
},
"offset":
{
"interpolation": "CUBIC_SPLINE",
"timelineType": "LOOPED",
"timeOffset":
{
"min": 0,
"max": 1
},
"timeline":
[
{
"t": 0.00,
"value": [ 10, 0, 0]
},
{
"t": 0.05,
"value": [ 9.5, 3, 0]
},
{
"t": 0.25,
"value": [ 0, 10, 0]
},
{
"t": 0.5,
"value": [ -10, 0, 0]
},
{
"t": 0.75,
"value": [ 0, -10, 0]
},
{
"t": 0.95,
"value": [ 9.5, -3, 0]
},
{
"t": 1.0,
"value": [ 10, 0, 0]
}
]
},
"rotation":
{
"interpolation": "LINEAR_SPLINE",
"timeOffset":
{
"min": 0,
"max": 1
},
"timelineType": "LOOPED",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 45, 0 ]
},
{
"t": 1.000,
"value": [ 360, 45, 0 ]
}
]
},
"scale":
{
"interpolation": "DISCRETE",
"timeline":
[
{
"min": 1,
"max": 2
}
]
},
"color":
{
"value": [ 1, 0, 1, 1 ]
}
}
]
}
-274
View File
@@ -1,274 +0,0 @@
{
"emitters":
[
{
"preloading": 20,
"texturePath": "textures/magic-star.png",
"textureSize": [ 22.625, 12.5 ],
"hasInertion": "false",
"gravity": [0, 0, 0],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0,
"value": 0
},
{
"t": 1,
"value": 2
}
]
},
"spawnRange":
{
"value": [ 0, 30, 0, 45 ]
},
"lifeTime":
{
"min": 1.5,
"max": 3
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"rotation_system": "PARTICLE_BIRTH",
"coords":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0 ]
},
{
"t": 1.000,
"min": [ 300, 0, 0 ],
"max": [ 300, 0, 0 ]
}
]
},
"rotation":
{
"value": [ 0, 0, 0 ]
},
"scale":
{
"interpolation": "DISCRETE",
"timeline":
[
{
"value": 1
}
]
},
"color":
{
"value": [ 1, 1, 1, 1 ]
},
"emitters":
[
{
"name": "Spark",
"maxParticles": 110,
"preloading": 110,
"texturePath": "textures/spark-white.png",
"textureSize": [ 10, 10 ],
"gravity": [0, -100, 0],
"spawnRange_system": "PARTICLE_BIRTH",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"matchDeathTime": "true",
"timeline":
[
{
"t": 0.000,
"value": 0
},
{
"t": 1,
"value": 50
}
]
},
"spawnRange":
{
"value": [ 0, 0, 0, 360 ]
},
"lifeTime":
{
"min": 1,
"max": 2
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"rotation_system": "PARTICLE_BIRTH",
"coords":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0 ]
},
{
"t": 1.000,
"min": [ 0, 0, 0 ],
"max": [ 50, 0, 0 ]
}
]
},
"rotation":
{
"value": [ 0, 0, 0 ]
},
"scale":
{
"value": 1
},
"color":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 1, 1, 1 ]
},
{
"t": 1.000,
"value": [ 0, 0, 1, 1 ]
},
{
"t": 1.200,
"value": [ 0, 0, 1, 0 ]
}
]
}
},
{
"name": "Spark",
"maxParticles": 300,
"preloading": 300,
"texturePath": "textures/spark-white.png",
"textureSize": [ 10, 10 ],
"hasInertion": "true",
"gravity": [0, -100, 0],
"spawnRange_system": "PARTICLE_BIRTH",
"spawnTotal":
{
"interpolation": "DISCRETE",
"matchDeathTime": "true",
"timeline":
[
{
"t": 0.000,
"value": 0
},
{
"t": 2.000,
"value": 300
}
]
},
"spawnRange":
{
"value": [ 0, 0, 0, 360 ]
},
"lifeTime":
{
"min": 1,
"max": 2
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"rotation_system": "PARTICLE_BIRTH",
"coords":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0 ]
},
{
"t": 1.000,
"min": [ 25, 0, 0 ],
"max": [ 300, 0, 0 ]
}
]
},
"rotation":
{
"value": [ 0, 0, 0 ]
},
"scale":
{
"value": 1
},
"color":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 1, 1, 0, 1 ]
},
{
"t": 1.000,
"value": [ 1, 0, 0, 1 ]
},
{
"t": 1.200,
"value": [ 1, 0, 0, 0 ]
}
]
}
}
]
}
]
}
-110
View File
@@ -1,110 +0,0 @@
{
"name": "Sparkler - бенгальский огонь",
"emitters":
[
{
"name": "Spark",
"maxParticles": 300,
"preloading": 100,
"texturePath": "textures/comet.png",
"textureSize": [ 20, 7.12 ],
"hasInertion": "false",
"gravity": [0, 0, 0],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0,
"value": 0
},
{
"t": 1,
"value": 3
}
]
},
"spawnRange":
{
"value": [ 0, 0, 0, 0 ]
},
"lifeTime":
{
"value": 6
},
"coords_system": "PARTICLE_EFFECT",
"coords_axis_system": "PARTICLE_BIRTH",
"rotation_system": "PARTICLE_ITSELF",
"coords":
{
"interpolation": "CUBIC_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 50, 0, 0 ]
},
{
"t": 0.001,
"value": [ 50, 0, 0 ]
},
{
"t": 1.000,
"value": [ 100, 100, 0 ]
},
{
"t": 2.000,
"value": [ 200, -100, 0 ]
},
{
"t": 3.000,
"value": [ 300, 100, 0 ]
},
{
"t": 4.000,
"value": [ 400, -100, 0 ]
},
{
"t": 5.000,
"value": [ 500, 100, 0 ]
},
{
"t": 5.999,
"value": [ 600, -100, 0 ]
},
{
"t": 6.000,
"value": [ 600, -100, 0 ]
}
]
},
"rotation":
{
"value": [ 0, 0, 0 ]
},
"scale":
{
"value": 1
},
"color":
{
"value": [ 1, 1, 1, 1 ]
}
}
]
}
-110
View File
@@ -1,110 +0,0 @@
{
"name": "Sparkler - бенгальский огонь",
"emitters":
[
{
"name": "Spark",
"maxParticles": 300,
"preloading": 100,
"texturePath": "textures/spark.png",
"textureSize": [ 10, 10 ],
"hasInertion": "false",
"gravity": [0, 0, 0],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0,
"value": 0
},
{
"t": 1,
"value": 20
}
]
},
"spawnRange":
{
"value": [ 0, 0, 0, 0 ]
},
"lifeTime":
{
"value": 6
},
"coords_system": "PARTICLE_EFFECT",
"coords_axis_system": "PARTICLE_BIRTH",
"rotation_system": "PARTICLE_EFFECT",
"coords":
{
"interpolation": "CUBIC_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 50, 0, 0 ]
},
{
"t": 0.001,
"value": [ 50, 0, 0 ]
},
{
"t": 1.000,
"value": [ 100, 100, 0 ]
},
{
"t": 2.000,
"value": [ 200, -100, 0 ]
},
{
"t": 3.000,
"value": [ 300, 100, 0 ]
},
{
"t": 4.000,
"value": [ 400, -100, 0 ]
},
{
"t": 5.000,
"value": [ 500, 100, 0 ]
},
{
"t": 5.999,
"value": [ 600, -100, 0 ]
},
{
"t": 6.000,
"value": [ 600, -100, 0 ]
}
]
},
"rotation":
{
"value": [ 0, 0, 0 ]
},
"scale":
{
"value": 1
},
"color":
{
"value": [ 1, 1, 0, 1 ]
}
}
]
}
-93
View File
@@ -1,93 +0,0 @@
{
"name": "Simple Sparkler",
"emitters":
[
{
"name": "Spark",
"maxParticles": 2000,
"preloading": 2000,
"texturePath": "textures/spark-white.png",
"textureSize": [ 10, 10 ],
"hasInertion": "false",
"gravity": [0, 0, 0],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "CUBIC_SPLINE",
"timelineType": "LOOPED",
"timeline":
[
{
"t": 0.000,
"value": 0
},
{
"t": 0.001,
"value": 0
},
{
"t": 9.999,
"value": 10000
},
{
"t": 10.000,
"value": 10000
}
]
},
"spawnRange":
{
"value": [ 0, 0, 0, 360 ]
},
"lifeTime":
{
"min": 0.1,
"max": 1
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"rotation_system": "PARTICLE_EFFECT",
"coords":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0 ]
},
{
"t": 1,
"min": [ 300, 0, 0 ],
"max": [ 600, 0, 0 ]
}
]
},
"rotation":
{
"value": [ 0, 0, 0 ]
},
"scale":
{
"value": 1
},
"color":
{
"value": [ 1, 1, 0, 1 ]
}
}
]
}
-85
View File
@@ -1,85 +0,0 @@
{
"name": "Simple Sparkler",
"emitters":
[
{
"name": "Spark",
"maxParticles": 1100,
"preloading": 1100,
"texturePath": "textures/spark-white.png",
"textureSize": [ 10, 10 ],
"hasInertion": "false",
"gravity": [0, 0, 0],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timelineType": "CONTINUED",
"timeline":
[
{
"t": 0.000,
"value": 0
},
{
"t": 1.000,
"value": 1000
}
]
},
"spawnRange":
{
"value": [ 0, 0, 0, 360 ]
},
"lifeTime":
{
"min": 0.1,
"max": 1
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"rotation_system": "PARTICLE_EFFECT",
"coords":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0 ]
},
{
"t": 1,
"min": [ 300, 0, 0 ],
"max": [ 600, 0, 0 ]
}
]
},
"rotation":
{
"value": [ 0, 0, 0 ]
},
"scale":
{
"value": 1
},
"color":
{
"value": [ 1, 1, 0, 1 ]
}
}
]
}
-646
View File
@@ -1,646 +0,0 @@
{
"emitters":
[
{
"maxParticles": 10000,
"preloading": 1000,
"texturePath": "textures/star-white.png",
"textureSize": [ 5, 5 ],
"gravity": [ 0, -100, 0 ],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": 0
},
{
"t": 1.000,
"value": 5
}
]
},
"spawnRange":
{
"value": [ 0, 0, 360, 180 ]
},
"lifeTime":
{
"min": 10,
"max": 10
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"offset_axis_system": "PARTICLE_ITSELF",
"rotation_system": "PARTICLE_ITSELF",
"coords":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0 ]
},
{
"t": 1.000,
"min": [ 150, 0, 0 ],
"max": [ 300, 0, 0 ]
}
]
},
"offset":
{
"interpolation": "CUBIC_SPLINE",
"timelineType": "LOOPED",
"timeline":
[
{
"t": 0.00,
"value": [ 10, 0, 0]
},
{
"t": 0.05,
"value": [ 9.5, 3, 0]
},
{
"t": 0.25,
"value": [ 0, 10, 0]
},
{
"t": 0.5,
"value": [ -10, 0, 0]
},
{
"t": 0.75,
"value": [ 0, -10, 0]
},
{
"t": 0.95,
"value": [ 9.5, -3, 0]
},
{
"t": 1.0,
"value": [ 10, 0, 0]
}
]
},
"rotation":
{
"interpolation": "LINEAR_SPLINE",
"timeOffset":
{
"min": 0,
"max": 1
},
"timelineType": "LOOPED",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 45, 0 ]
},
{
"t": 1.000,
"value": [ 360, 45, 0 ]
}
]
},
"scale":
{
"interpolation": "DISCRETE",
"timeline":
[
{
"min": 1,
"max": 2
}
]
},
"color":
{
"value": [ 0, 1, 0, 1 ]
}
},
{
"name": "Magic Star",
"maxParticles": 10000,
"preloading": 1000,
"texturePath": "textures/rect-white.png",
"textureSize": [ 5, 5 ],
"gravity": [ 0, -100, 0 ],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": 0
},
{
"t": 1.000,
"value": 5
}
]
},
"spawnRange":
{
"value": [ 0, 0, 360, 180 ]
},
"lifeTime":
{
"min": 10,
"max": 10
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"offset_axis_system": "PARTICLE_ITSELF",
"rotation_system": "PARTICLE_ITSELF",
"coords":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0 ]
},
{
"t": 1.000,
"min": [ 150, 0, 0 ],
"max": [ 300, 0, 0 ]
}
]
},
"rotation":
{
"interpolation": "LINEAR_SPLINE",
"timeOffset":
{
"min": 0,
"max": 1
},
"timelineType": "LOOPED",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 45, 0 ]
},
{
"t": 1.000,
"value": [ 360, 45, 0 ]
}
]
},
"scale":
{
"interpolation": "DISCRETE",
"timeline":
[
{
"min": 1,
"max": 2
}
]
},
"color":
{
"value": [ 1, 0, 0, 1 ]
}
},
{
"name": "Magic Star",
"maxParticles": 10000,
"preloading": 1000,
"texturePath": "textures/circle-white.png",
"textureSize": [ 5, 5 ],
"gravity": [ 0, -100, 0 ],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": 0
},
{
"t": 1.000,
"value": 5
}
]
},
"spawnRange":
{
"value": [ 0, 0, 360, 180 ]
},
"lifeTime":
{
"min": 10,
"max": 10
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"offset_axis_system": "PARTICLE_ITSELF",
"rotation_system": "PARTICLE_ITSELF",
"coords":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0 ]
},
{
"t": 1.000,
"min": [ 150, 0, 0 ],
"max": [ 300, 0, 0 ]
}
]
},
"rotation":
{
"interpolation": "LINEAR_SPLINE",
"timeOffset":
{
"min": 0,
"max": 1
},
"timelineType": "LOOPED",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 45, 0 ]
},
{
"t": 1.000,
"value": [ 360, 45, 0 ]
}
]
},
"scale":
{
"interpolation": "DISCRETE",
"timeline":
[
{
"min": 1,
"max": 2
}
]
},
"color":
{
"value": [ 0, 0, 1, 1 ]
}
},
{
"name": "Magic Star",
"maxParticles": 10000,
"preloading": 1000,
"texturePath": "textures/star-white.png",
"textureSize": [ 5, 5 ],
"gravity": [ 0, -100, 0 ],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": 0
},
{
"t": 1.000,
"value": 5
}
]
},
"spawnRange":
{
"value": [ 0, 0, 360, 180 ]
},
"lifeTime":
{
"min": 10,
"max": 10
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"offset_axis_system": "PARTICLE_ITSELF",
"rotation_system": "PARTICLE_ITSELF",
"coords":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0 ]
},
{
"t": 1.000,
"min": [ 150, 0, 0 ],
"max": [ 300, 0, 0 ]
}
]
},
"rotation":
{
"interpolation": "LINEAR_SPLINE",
"timeOffset":
{
"min": 0,
"max": 1
},
"timelineType": "LOOPED",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 45, 0 ]
},
{
"t": 1.000,
"value": [ 360, 45, 0 ]
}
]
},
"scale":
{
"interpolation": "DISCRETE",
"timeline":
[
{
"min": 1,
"max": 2
}
]
},
"color":
{
"value": [ 1, 1, 0, 1 ]
}
},
{
"name": "Magic Star",
"maxParticles": 10000,
"preloading": 1000,
"texturePath": "textures/rect-white.png",
"textureSize": [ 5, 5 ],
"gravity": [ 0, -100, 0 ],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": 0
},
{
"t": 1.000,
"value": 5
}
]
},
"spawnRange":
{
"value": [ 0, 0, 360, 180 ]
},
"lifeTime":
{
"min": 10,
"max": 10
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"offset_axis_system": "PARTICLE_ITSELF",
"rotation_system": "PARTICLE_ITSELF",
"coords":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0 ]
},
{
"t": 1.000,
"min": [ 150, 0, 0 ],
"max": [ 300, 0, 0 ]
}
]
},
"rotation":
{
"interpolation": "LINEAR_SPLINE",
"timeOffset":
{
"min": 0,
"max": 1
},
"timelineType": "LOOPED",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 45, 0 ]
},
{
"t": 1.000,
"value": [ 360, 45, 0 ]
}
]
},
"scale":
{
"interpolation": "DISCRETE",
"timeline":
[
{
"min": 1,
"max": 2
}
]
},
"color":
{
"value": [ 0, 1, 1, 1 ]
}
},
{
"name": "Magic Star",
"maxParticles": 10000,
"preloading": 1000,
"texturePath": "textures/circle-white.png",
"textureSize": [ 5, 5 ],
"gravity": [ 0, -100, 0 ],
"spawnRange_system": "PARTICLE_EFFECT",
"spawnTotal":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": 0
},
{
"t": 1.000,
"value": 5
}
]
},
"spawnRange":
{
"value": [ 0, 0, 360, 180 ]
},
"lifeTime":
{
"min": 10,
"max": 10
},
"coords_system": "PARTICLE_BIRTH",
"coords_axis_system": "PARTICLE_BIRTH",
"offset_axis_system": "PARTICLE_ITSELF",
"rotation_system": "PARTICLE_ITSELF",
"coords":
{
"interpolation": "LINEAR_SPLINE",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 0, 0 ]
},
{
"t": 1.000,
"min": [ 150, 0, 0 ],
"max": [ 300, 0, 0 ]
}
]
},
"rotation":
{
"interpolation": "LINEAR_SPLINE",
"timeOffset":
{
"min": 0,
"max": 1
},
"timelineType": "LOOPED",
"timeline":
[
{
"t": 0.000,
"value": [ 0, 45, 0 ]
},
{
"t": 1.000,
"value": [ 360, 45, 0 ]
}
]
},
"scale":
{
"interpolation": "DISCRETE",
"timeline":
[
{
"min": 1,
"max": 2
}
]
},
"color":
{
"value": [ 1, 0, 1, 1 ]
}
}
]
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

+249
View File
@@ -0,0 +1,249 @@
{
"transform version": "V1",
"models": [
{
"type": "EmojiModel",
"name": "Smile"
}],
"renderParams": [
{
"vertexShader": "./assets/shaders/vertex/orthoVertexShader.txt",
"fragmentShader": "./assets/shaders/fragment/orthoFragmentShader.txt",
"alphaTest": "true",
"blend": "true",
"TAG": "smile & tongue 0"
}
],
"initialModules": [0, 1, 2, 3, 4],
"modules": [
{
"iconPath": "./assets/fx/emoji/Asset 3@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 3@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 24@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 24@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 13@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 13@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 23@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 23@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 19@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 19@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 20@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 20@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 17@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 17@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 18@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 18@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 15@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 15@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 16@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 16@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 21@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 21@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 4@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 4@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 22@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 22@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 14@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 14@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 11@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 11@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 25@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 25@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 26@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 26@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 27@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 27@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 28@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 28@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 5@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 5@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 6@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 6@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 7@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 7@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 8@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 8@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 9@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 9@20x.png"
}
]
},
{
"iconPath": "./assets/fx/emoji/Asset 10@20x.png",
"suits": [
{
"renderParamsID": 0,
"emojiTexture": "./assets/fx/emoji/Asset 10@20x.png"
}
]
}
]
}
+12
View File
@@ -0,0 +1,12 @@
precision mediump float;
uniform sampler2D Texture;
uniform float Brightness;
varying vec2 texCoord;
void main()
{
vec3 color = texture2D(Texture,texCoord).rgb;
gl_FragColor = vec4(color * Brightness, 1.0);
}
@@ -1,12 +1,12 @@
attribute vec3 vPosition;
attribute vec2 vTexCoord;
varying vec2 texCoord;
uniform mat4 ProjectionMatrix;
void main()
{
//480x320
gl_Position = ProjectionMatrix * vec4(vPosition.xyz, 1.0);
texCoord = vTexCoord;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

-42
View File
@@ -1,42 +0,0 @@
<EMITTER_DESCRIPTION>
bool enabled;
< Emitter Description >
uint maxParticles;
uint preloading;
std::string texturePath;
Vector2f textureSize;
bool hasInertion;
Vector3f gravity;
RelatedCoordinateSystem spawnRange_system; = { PARTICLE_EFFECT , PARTICLE_EMITTER }
RandomValueAtTimeline<FloatWrapper, RandomFloat> spawnTotal;
RandomValueAtTimeline<Vector4fWrapper, RandomVector4f> spawnRange; // yaw + pitch + delta yaw + delta pitch
< / Emitter Description >
< Particle Description >
RandomFloat lifeTime;
RelatedCoordinateSystem coords_system; = { PARTICLE_EFFECT , PARTICLE_EMITTER , PARTICLE_BIRTH , PARTICLE_ITSELF }
RelatedCoordinateSystem offset_axis_system;
RelatedCoordinateSystem coords_axis_system;
RelatedCoordinateSystem rotation_system;
RandomValueAtTimeline<Vector3fWrapper, RandomVector3f> coords;
RandomValueAtTimeline<Vector3fWrapper, RandomVector3f> offset;
RandomValueAtTimeline<Vector3fWrapper, RandomVector3f> rotation; // yaw + pitch + roll
RandomValueAtTimeline<FloatWrapper, RandomFloat> scale;
RandomValueAtTimeline<Vector4fWrapper, RandomVector4f> color;
std::vector<std::shared_ptr<EmitterDescription>> emittersTypes;
</ Particle Description >
std::vector<EmitterDescription> emittersTypes;
</EMITTER_DESCRIPTION>
+14
View File
@@ -0,0 +1,14 @@
precision mediump float;
uniform sampler2D Texture;
uniform float Transparency;
varying vec2 texCoord;
void main()
{
vec4 color = texture2D(Texture,texCoord).rgba;
gl_FragColor = vec4(color.rgb, color.a * Transparency);
}
@@ -1,15 +1,12 @@
attribute vec3 vPosition;
attribute vec2 vTexCoord;
attribute vec4 vColor;
out vec2 texCoord;
flat out vec4 color;
varying vec2 texCoord;
uniform mat4 ProjectionMatrix;
void main()
{
//480x320
gl_Position = ProjectionMatrix * vec4(vPosition.xyz, 1.0);
texCoord = vTexCoord;
color = vColor;
}
-8
View File
@@ -1,8 +0,0 @@
precision mediump float;
uniform vec4 Color;
void main()
{
gl_FragColor = Color;
}
-8
View File
@@ -1,8 +0,0 @@
attribute vec3 vPosition;
uniform mat4 ProjectionMatrix;
void main()
{
gl_Position = ProjectionMatrix * vec4(vPosition.xyz, 1.0);
}
-11
View File
@@ -1,11 +0,0 @@
precision mediump float;
in vec2 texCoord;
flat in vec4 color;
uniform sampler2D Texture;
void main()
{
gl_FragColor = texture2D(Texture,texCoord) * color;
}
-10
View File
@@ -1,10 +0,0 @@
precision mediump float;
varying vec2 texCoord;
uniform sampler2D Texture;
void main()
{
gl_FragColor = texture2D(Texture,texCoord);
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 690 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

Regular → Executable
View File
File mode changed.
Regular → Executable
View File
File mode changed.
Regular → Executable
View File
File mode changed.
Regular → Executable
View File
File mode changed.
Regular → Executable
View File
File mode changed.
+592
View File
@@ -0,0 +1,592 @@
#include "main_code.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "include/Engine.h"
#include "main_code.h"
FaceStruct::FaceStruct()
{
}
FaceStruct::FaceStruct(const std::array<cv::Point2f, LANDMARK_POINT_COUNT>& fromPreds)
{
ApplyPreds(fromPreds);
}
void FaceStruct::CalcFromPreds()
{
float minX = preds[0](0);
float maxX = preds[0](0);
float minY = preds[0](1);
float maxY = preds[0](1);
float sumX = preds[0](0);
float sumY = preds[0](1);
for (size_t i = 1; i < LANDMARK_POINT_COUNT; i++)
{
if (minX > preds[i](0))
{
minX = preds[i](0);
}
if (minY > preds[i](1))
{
minY = preds[i](1);
}
if (maxX < preds[i](0))
{
maxX = preds[i](0);
}
if (maxY < preds[i](1))
{
maxY = preds[i](1);
}
sumX += preds[i](0);
sumY += preds[i](1);
}
float avgX = sumX / static_cast<float>(LANDMARK_POINT_COUNT);
float avgY = sumY / static_cast<float>(LANDMARK_POINT_COUNT);
center = { avgX, avgY };
size = { maxX- minX,maxY - minY };
//center = { centerXSmoother.responsiveAnalogReadSimple(avgX), centerYSmoother.responsiveAnalogReadSimple(avgY) };
//size = { sizeWidthSmoother.responsiveAnalogReadSimple(maxX- minX), sizeHeightSmoother.responsiveAnalogReadSimple(maxY - minY) };
}
void FaceStruct::ApplyPreds(const std::array<cv::Point2f, LANDMARK_POINT_COUNT>& fromPreds)
{
InnerApplyPreds(fromPreds);
CalcFromPreds();
/*
for (size_t i = 0; i < LANDMARK_POINT_COUNT; i++)
{
preds[i] = preds[i] - center;
}
historicalPreds.push_back(preds);
if (historicalPreds.size() > 4)
{
historicalPreds.erase(historicalPreds.begin());
}
for (size_t i = 0; i < LANDMARK_POINT_COUNT; i++)
{
preds[i] = { 0.f, 0.f };
for (size_t x = 0; x < historicalPreds.size(); x++)
{
preds[i] += historicalPreds[x][i];
}
preds[i] = preds[i] / static_cast<float>(historicalPreds.size());
}
for (size_t i = 0; i < LANDMARK_POINT_COUNT; i++)
{
preds[i] = preds[i] + center;
}*/
}
void FaceStruct::InnerApplyPreds(const std::array<cv::Point2f, LANDMARK_POINT_COUNT>& fromPreds)
{
for (size_t i = 0; i < LANDMARK_POINT_COUNT; i++)
{
preds[i] = { fromPreds[i].x, 720 - fromPreds[i].y};
}
}
cv::VideoCapture cap;
FaceLandmarkDetector faceLandmarkDetector;
GLuint lastFrameTexture;
std::array<FaceLandmarkStruct, MAX_FACE_COUNT> faceLandmarkArr;
cv::Mat frame;
std::vector<cv::Mat> frameArr;
int currentIndex = -1;
int lastProcessedIndex = 0;
int lineShift = 0;
int prevPassedIndex = 0;
int indexStep = 0;
std::array<FaceStruct, MAX_FACE_COUNT> faceStruct;
const std::string CONST_LOADING_BACKGROUND_BLACK = "loading_background_black";
TMyApplication* Application;
void TMyApplication::InnerInit()
{
Application = this;
#ifdef TARGET_WIN32
#ifdef NDEBUG
//ST::PathToResources = "resources/";
ST::PathToResources = "../../../assets/";
#else
ST::PathToResources = "../../../assets/";
#endif
#endif
#ifdef TARGET_IOS
ST::PathToResources = "assets/";
#endif
if (Console != NULL)
{
*Console<<"APP INIT\n";
}
srand (static_cast<size_t>(time(NULL)));
ResourceManager->ShaderManager.AddShader("DefaultShader", "shader1vertex.txt", "shader1fragment.txt");
ResourceManager->ShaderManager.AddShader("FrameShader", "frameshader_vertex.txt", "frameshader_fragment.txt");
Renderer->PushShader("DefaultShader");
ResourceManager->TexList.AddTexture(CONST_LOADING_BACKGROUND_BLACK + ".png", CONST_LOADING_BACKGROUND_BLACK);
auto texid = ResourceManager->TexList.AddTexture("emoji/Asset 3@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 4@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 5@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 6@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 7@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 8@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 9@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 10@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 11@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 13@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 14@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 15@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 16@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 17@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 18@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 19@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 20@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 21@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 22@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 23@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 24@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 25@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 26@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 27@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 28@20x.png");
ResourceManager->FontManager.AddFont("droid_sans14", "droid_sans14_font_bitmap.png", "droid_sans14_font_charmap.txt");
ResourceManager->FontManager.PushFont("droid_sans14");
lastFrameTexture = ResourceManager->TexList.AddEmptyTexture("lastFrameTexture", 1280, 720);
Renderer->SetOrthoProjection();
Renderer->SetFullScreenViewport();
for (size_t i = 0; i < MAX_FACE_COUNT; i++)
{
faceRenderPair[i].first.SamplerMap[CONST_STRING_TEXTURE_UNIFORM] = "Asset "+boost::lexical_cast<std::string>(i+3)+"@20x.png";
faceRenderPair[i].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(Vector3f(0, 0, 0));
faceRenderPair[i].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(Vector3f(0, 512, 0));
faceRenderPair[i].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(Vector3f(512, 512, 0));
faceRenderPair[i].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(Vector3f(512, 512, 0));
faceRenderPair[i].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(Vector3f(512, 0, 0));
faceRenderPair[i].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(Vector3f(0, 0, 0));
faceRenderPair[i].second.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(Vector2f(0, 0));
faceRenderPair[i].second.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(Vector2f(0, 1));
faceRenderPair[i].second.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(Vector2f(1, 1));
faceRenderPair[i].second.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(Vector2f(1, 1));
faceRenderPair[i].second.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(Vector2f(1, 0));
faceRenderPair[i].second.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(Vector2f(0, 0));
faceRenderPair[i].second.RefreshBuffer();
}
cap = cv::VideoCapture(0);
//cap = cv::VideoCapture("video.mp4");
//cap = cv::VideoCapture("bp.mp4");
// Check if camera opened successfully
if (!cap.isOpened()) {
std::cout << "Error opening video stream or file" << std::endl;
}
cap.set(CV_CAP_PROP_FRAME_WIDTH, 1280);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 720);
faceLandmarkDetector.StartTrackProcess();
Inited = true;
}
void TMyApplication::InnerDeinit()
{
faceLandmarkDetector.StopTrackProcess();
cap.release();
Inited = false;
if (Console != NULL)
{
*Console<<"APP DEINIT\n";
}
}
void TMyApplication::InnerOnTapDown(Vector2f p)
{
}
void TMyApplication::InnerOnTapUp(Vector2f p)
{
}
void TMyApplication::InnerOnTapUpAfterMove(Vector2f p)
{
}
void TMyApplication::InnerOnMove(Vector2f p, Vector2f shift)
{
}
void TMyApplication::OnFling(Vector2f v)
{
}
void TMyApplication::InnerDraw()
{
glDisable(GL_DEPTH_TEST);
//glBindTexture(GL_TEXTURE_2D, ResourceManager->TexList[CONST_LOADING_BACKGROUND_BLACK]);
glBindTexture(GL_TEXTURE_2D, lastFrameTexture);
Renderer->DrawRect(Vector2f(0.f, 0.f), Vector2f(Renderer->GetMatrixWidth(), Renderer->GetMatrixHeight()));
/*
for (size_t i = 0; i < MAX_FACE_COUNT; i++)
{
TRenderParamsSetter params(faceRenderPair[i].first);
Renderer->DrawTriangleList(faceRenderPair[i].second);
}*/
}
void TMyApplication::InnerUpdate(size_t dt)
{
/*cap >> lastFrame;
if (lastFrame.empty())
{
return;
}
faceLandmarkTracker.HandleOneFrame(lastFrame, localInputStructArr, localFaceShift, localOutputStructArr);
high_resolution_clock::time_point t2 = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(t2 - FaceLandmarkTracker::lastTimePoint).count();
FaceLandmarkTracker::lastTimePoint = t2;
std::stringstream ofs;
ofs << round(1000000.0 / duration);
for (size_t index = 0; index < CONST_FACE_COUNT; index++)
{
if (localOutputStructArr[index].valid && localInputStructArr[index].valid)
{
cv::Rect oldFaceRect = localOutputStructArr[index].face;
cv::Rect newFaceRect = localInputStructArr[index].face;
cv::Point2f oldCenter(oldFaceRect.x + oldFaceRect.width*0.5f, oldFaceRect.y + oldFaceRect.height*0.5f);
cv::Point2f newCenter(newFaceRect.x + newFaceRect.width*0.5f, newFaceRect.y + newFaceRect.height*0.5f);
localFaceShift[index] = newCenter - oldCenter;
}
else
{
localFaceShift[index] = cv::Point2f(0, 0);
}
}
for (size_t index = 0; index < CONST_FACE_COUNT; index++)
{
if (localOutputStructArr[index].valid)
{
faceStruct[index].ApplyPreds(localOutputStructArr[index].preds);
for (size_t i = 0; i < CONST_PREDS_COUNT; i++)
{
//cv::ellipse(lastFrame, cv::Point2f(faceStruct[index].preds[i](0), 720 - faceStruct[index].preds[i](1)) + localFaceShift[index], cv::Size(2, 2), 0, 0, 360, cv::Scalar(255, 128, 128), 4, 8, 0);
}
Vector2f posFrom = faceStruct[index].center - faceStruct[index].size*0.5f* 1.25f;
Vector2f posTo = faceStruct[index].center + faceStruct[index].size*0.5f* 1.25f;
ApplyVertexCoordVec(faceRenderPair[index].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB], posFrom, posTo, 0);
faceRenderPair[index].second.RefreshBuffer();
}
else
{
ApplyVertexCoordVec(faceRenderPair[index].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB], {0,0}, { 0,0 }, 0);
faceRenderPair[index].second.RefreshBuffer();
}
}
for (size_t index = 0; index < CONST_FACE_COUNT; index++)
{
if (localInputStructArr[index].valid)
{
//cv::rectangle(lastFrame, localInputStructArr[index].face, cv::Scalar(255, 0, 255), 4, 8, 0);
}
}
*/
cap >> frame; // get a new frame from camera/video or read image
if (frame.empty())
{
return;
}
cv::Mat image = frame.clone();
frameArr.push_back(image);
while (frameArr.size() > 40)
{
lineShift++;
frameArr.erase(frameArr.begin());
}
currentIndex++;
faceLandmarkArr = faceLandmarkDetector.GetFaceLandmarks(frame, currentIndex);
bool newProcessedIndexFound = false;
int newProcessedIndex;
for (size_t i = 0; i < faceLandmarkArr.size(); i++)
{
if (faceLandmarkArr[i].valid)
{
if (!newProcessedIndexFound)
{
newProcessedIndexFound = true;
newProcessedIndex = faceLandmarkArr[i].frameIndex;
}
else
{
if (newProcessedIndex < faceLandmarkArr[i].frameIndex)
{
newProcessedIndex = faceLandmarkArr[i].frameIndex;
}
}
}
}
if (newProcessedIndexFound && newProcessedIndex > lastProcessedIndex)
{
indexStep = 0;
lastProcessedIndex = newProcessedIndex;
prevPassedIndex = currentIndex;
}
else
{
if (prevPassedIndex > lastProcessedIndex + indexStep)
{
indexStep++;
}
}
//std::cout << currentIndex << " " << lastProcessedIndex << " stepped:" << lastProcessedIndex + indexStep << " indexStep: " << indexStep << std::endl;
cv::Mat renderImage;
if (lastProcessedIndex + indexStep - lineShift < 0)
{
renderImage = frameArr[0];
}
else if (lastProcessedIndex + indexStep - lineShift >= frameArr.size())
{
renderImage = frameArr[frameArr.size() - 1];
}
else
{
renderImage = frameArr[lastProcessedIndex + indexStep - lineShift];
}
renderImage = renderImage.clone();
cv::Rect frameRect(cv::Point(), renderImage.size());
for (size_t i = 0; i < faceLandmarkArr.size(); i++)
{
if (faceLandmarkArr[i].valid)
{
cv::rectangle(renderImage, faceLandmarkArr[i].faceRect, cv::Scalar(0, 0, 255), 1, 4, 0);
for (size_t j = 0; j < faceLandmarkArr[i].landmarkArr.size(); j++)
{
//cv::circle(renderImage, faceLandmarkArr[i].landmarkArr[j], 0.1, cv::Scalar(0, 255, 255), 4, 8, 0);
}
}
}
for (size_t index = 0; index < faceLandmarkArr.size(); index++)
{
if (faceLandmarkArr[index].valid)
{
faceStruct[index].ApplyPreds(faceLandmarkArr[index].landmarkArr);
for (size_t i = 0; i < LANDMARK_POINT_COUNT; i++)
{
cv::ellipse(renderImage, cv::Point2f(faceStruct[index].preds[i](0), 720 - faceStruct[index].preds[i](1)), cv::Size(2, 2), 0, 0, 360, cv::Scalar(255, 128, 128), 4, 8, 0);
}
Vector2f posFrom = faceStruct[index].center - faceStruct[index].size*0.5f* 1.35f;
Vector2f posTo = faceStruct[index].center + faceStruct[index].size*0.5f* 1.35f;
ApplyVertexCoordVec(faceRenderPair[index].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB], posFrom, posTo, 0);
faceRenderPair[index].second.RefreshBuffer();
}
else
{
ApplyVertexCoordVec(faceRenderPair[index].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB], { 0,0 }, { 0,0 }, 0);
faceRenderPair[index].second.RefreshBuffer();
}
}
glBindTexture(GL_TEXTURE_2D, lastFrameTexture);
static std::array<char, 1280 * 720 * 3> buffer;
int step = renderImage.step;
int height = renderImage.rows;
int width = renderImage.cols;
int channels = 3;
char * data = (char *)renderImage.data;
for (int i = 0; i < height; i++)
{
int ci = height - i - 1;
memcpy(&buffer[i*width*channels], &(data[ci*step]), width*channels);
}
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGB,
1280,
720,
0,
GL_BGR_EXT,
GL_UNSIGNED_BYTE,
&buffer[0]);
}
bool TMyApplication::IsInited()
{
return Inited;
}
Regular → Executable
+489 -43
View File
@@ -7,7 +7,185 @@
#include "include/Engine.h"
#include <boost/property_tree/json_parser.hpp>
#include "main_code.h"
//#define USE_PREDICTION
cv::Point flipVertical(cv::Point point) {
return cv::Point(point.x, 720 - point.y);
}
FaceStruct::FaceStruct()
{
modelPoints.push_back(cv::Point3d(6.825897, 6.760612, 4.402142)); // left brow left corner
modelPoints.push_back(cv::Point3d(1.330353, 7.122144, 6.903745)); // left brow right corner
modelPoints.push_back(cv::Point3d(-1.330353, 7.122144, 6.903745)); // right brow left corner
modelPoints.push_back(cv::Point3d(-6.825897, 6.760612, 4.402142)); // right brow right corner
modelPoints.push_back(cv::Point3d(5.311432, 5.485328, 3.987654)); // left eye left corner
modelPoints.push_back(cv::Point3d(1.789930, 5.393625, 4.413414)); // left eye right corner
modelPoints.push_back(cv::Point3d(-1.789930, 5.393625, 4.413414)); // right eye left corner
modelPoints.push_back(cv::Point3d(-5.311432, 5.485328, 3.987654)); // right eye right corner
modelPoints.push_back(cv::Point3d(2.005628, 1.409845, 6.165652)); // nose left corner
modelPoints.push_back(cv::Point3d(-2.005628, 1.409845, 6.165652)); // nose right corner
modelPoints.push_back(cv::Point3d(2.774015, -2.080775, 5.048531)); // mouth left corner
modelPoints.push_back(cv::Point3d(-2.774015, -2.080775, 5.048531)); // mouth right corner
modelPoints.push_back(cv::Point3d(0.000000, -3.116408, 6.097667)); // mouth central bottom corner
modelPoints.push_back(cv::Point3d(0.000000, -7.415691, 4.070434)); // chin corner
poseMatrix = cv::Mat(3, 4, CV_64FC1);
eulerAngles = cv::Mat(3, 1, CV_64FC1);
boxModelSrc.push_back(cv::Point3d(10.0, 10.0, 10.0));
boxModelSrc.push_back(cv::Point3d(10.0, 10.0, -10.0));
boxModelSrc.push_back(cv::Point3d(10.0, -10.0, -10.0));
boxModelSrc.push_back(cv::Point3d(10.0, -10.0, 10.0));
boxModelSrc.push_back(cv::Point3d(-10.0, 10.0, 10.0));
boxModelSrc.push_back(cv::Point3d(-10.0, 10.0, -10.0));
boxModelSrc.push_back(cv::Point3d(-10.0, -10.0, -10.0));
boxModelSrc.push_back(cv::Point3d(-10.0, -10.0, 10.0));
}
FaceStruct::FaceStruct(const std::array<cv::Point2f, LANDMARK_POINT_COUNT>& fromPreds, cv::Mat& cameraMatrix, cv::Mat& distortionCoefficients)
{
FaceStruct();
ApplyPreds(fromPreds, 0.0, cameraMatrix, distortionCoefficients);
}
void FaceStruct::CalcFromPreds(bool noticeablyChanged, cv::Mat& cameraMatrix, cv::Mat& distortionCoefficients)
{
for(size_t i = 0; i < LANDMARK_POINT_COUNT; i++) {
if(noticeablyChanged) {
landmarkSmoothers[i * 2].reset();
landmarkSmoothers[i * 2 + 1].reset();
} else {
preds[i] = Vector2f(
landmarkSmoothers[i * 2].responsiveAnalogReadSimple(preds[i](0)),
landmarkSmoothers[i * 2 + 1].responsiveAnalogReadSimple(preds[i](1))
);
}
}
float minX = preds[0](0);
float maxX = preds[0](0);
float minY = preds[0](1);
float maxY = preds[0](1);
float sumX = preds[0](0);
float sumY = preds[0](1);
for (size_t i = 1; i < LANDMARK_POINT_COUNT; i++)
{
if (minX > preds[i](0))
{
minX = preds[i](0);
}
if (minY > preds[i](1))
{
minY = preds[i](1);
}
if (maxX < preds[i](0))
{
maxX = preds[i](0);
}
if (maxY < preds[i](1))
{
maxY = preds[i](1);
}
sumX += preds[i](0);
sumY += preds[i](1);
}
float avgX = sumX / static_cast<float>(LANDMARK_POINT_COUNT);
float avgY = sumY / static_cast<float>(LANDMARK_POINT_COUNT);
std::vector<cv::Point2f> imagePoints;
imagePoints.push_back(cv::Point2f(preds[17](0), preds[17](1))); // #17 left brow left corner
imagePoints.push_back(cv::Point2f(preds[21](0), preds[21](1))); // #21 left brow right corner
imagePoints.push_back(cv::Point2f(preds[22](0), preds[22](1))); // #22 right brow left corner
imagePoints.push_back(cv::Point2f(preds[26](0), preds[26](1))); // #26 right brow right corner
imagePoints.push_back(cv::Point2f(preds[36](0), preds[36](1))); // #36 left eye left corner
imagePoints.push_back(cv::Point2f(preds[39](0), preds[39](1))); // #39 left eye right corner
imagePoints.push_back(cv::Point2f(preds[42](0), preds[42](1))); // #42 right eye left corner
imagePoints.push_back(cv::Point2f(preds[45](0), preds[45](1))); // #45 right eye right corner
imagePoints.push_back(cv::Point2f(preds[31](0), preds[31](1))); // #31 nose left corner
imagePoints.push_back(cv::Point2f(preds[35](0), preds[35](1))); // #35 nose right corner
imagePoints.push_back(cv::Point2f(preds[48](0), preds[48](1))); // #48 mouth left corner
imagePoints.push_back(cv::Point2f(preds[54](0), preds[54](1))); // #54 mouth right corner
imagePoints.push_back(cv::Point2f(preds[57](0), preds[57](1))); // #57 mouth central bottom corner
imagePoints.push_back(cv::Point2f(preds[8](0), preds[8](1))); // #8 chin corner
cv::solvePnP(modelPoints, imagePoints, cameraMatrix, distortionCoefficients, rotationVector, translationVector);
//if(similarity > 0.01) {
// for (size_t i = 0; i < 3; i++) {
// rotationVectorSmoothers[i].reset();
// translationVectorSmoothers[i].reset();
// }
//}
/*for(size_t i = 0; i < 3; i++) {
rotationVector.at<double>(i) = rotationVectorSmoothers[i].responsiveAnalogReadSimple(rotationVector.at<double>(i));
translationVector.at<double>(i) = translationVectorSmoothers[i].responsiveAnalogReadSimple(translationVector.at<double>(i));
}*/
cv::projectPoints(boxModelSrc, rotationVector, translationVector, cameraMatrix, distortionCoefficients, boxModelDst);
// calc Euler angles
cv::Rodrigues(rotationVector, rotationMatrix);
cv::hconcat(rotationMatrix, translationVector, poseMatrix);
cv::Mat outIntrinsics = cv::Mat(3, 3, CV_64FC1);
cv::Mat outRotation = cv::Mat(3, 3, CV_64FC1);
cv::Mat outTranslation = cv::Mat(3, 1, CV_64FC1);
cv::decomposeProjectionMatrix(poseMatrix, outIntrinsics, outRotation, outTranslation, cv::noArray(), cv::noArray(), cv::noArray(), eulerAngles);
center = {avgX, avgY};
size = {maxX- minX, maxY - minY};
}
void FaceStruct::ApplyPreds(const std::array<cv::Point2f, LANDMARK_POINT_COUNT>& fromPreds, bool noticeablyChanged, cv::Mat& cameraMatrix, cv::Mat& distortionCoefficients)
{
InnerApplyPreds(fromPreds);
CalcFromPreds(noticeablyChanged, cameraMatrix, distortionCoefficients);
}
void FaceStruct::InnerApplyPreds(const std::array<cv::Point2f, LANDMARK_POINT_COUNT>& fromPreds)
{
for (size_t i = 0; i < LANDMARK_POINT_COUNT; i++)
{
preds[i] = { fromPreds[i].x, 720 - fromPreds[i].y};
}
}
cv::VideoCapture cap;
FaceLandmarkDetector faceLandmarkDetector;
GLuint lastFrameTexture;
std::array<FaceLandmarkStruct, MAX_FACE_COUNT> faceLandmarkArr;
cv::Mat frame;
std::vector<cv::Mat> frameArr;
int currentIndex = -1;
int lastProcessedIndex = 0;
int lineShift = 0;
int prevPassedIndex = 0;
int indexStep = 0;
std::array<FaceStruct, MAX_FACE_COUNT> faceStruct;
const std::string CONST_LOADING_BACKGROUND_BLACK = "loading_background_black";
TMyApplication* Application;
@@ -19,6 +197,7 @@ void TMyApplication::InnerInit()
#ifdef TARGET_WIN32
#ifdef NDEBUG
//ST::PathToResources = "resources/";
ST::PathToResources = "../../../assets/";
#else
ST::PathToResources = "../../../assets/";
@@ -35,81 +214,348 @@ void TMyApplication::InnerInit()
}
srand (static_cast<size_t>(time(NULL)));
ResourceManager->ShaderManager.AddShader("DefaultShader", "shaders/texture-shader.vertex", "shaders/texture-shader.fragment");
ResourceManager->ShaderManager.AddShader("ColorShader", "shaders/color-shader.vertex", "shaders/color-shader.fragment");
ResourceManager->ShaderManager.AddShader(ParticleEffect::PARTICLE_SHADER, "shaders/particle-shader.vertex", "shaders/particle-shader.fragment");
Renderer->PushShader("ColorShader");
ResourceManager->ShaderManager.AddShader("DefaultShader", "shader1vertex.txt", "shader1fragment.txt");
ResourceManager->ShaderManager.AddShader("FrameShader", "frameshader_vertex.txt", "frameshader_fragment.txt");
Renderer->PushShader("DefaultShader");
float width = Renderer->GetScreenWidth();
float height = Renderer->GetScreenHeight();
ResourceManager->TexList.AddTexture(CONST_LOADING_BACKGROUND_BLACK + ".png", CONST_LOADING_BACKGROUND_BLACK);
auto texid = ResourceManager->TexList.AddTexture("emoji/Asset 3@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 4@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 5@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 6@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 7@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 8@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 9@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 10@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 11@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 13@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 14@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 15@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 16@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 17@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 18@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 19@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 20@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 21@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 22@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 23@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 24@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 25@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 26@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 27@20x.png");
ResourceManager->TexList.AddTexture("emoji/Asset 28@20x.png");
ResourceManager->FontManager.AddFont("droid_sans14", "droid_sans14_font_bitmap.png", "droid_sans14_font_charmap.txt");
ResourceManager->FontManager.PushFont("droid_sans14");
lastFrameTexture = ResourceManager->TexList.AddEmptyTexture("lastFrameTexture", 1280, 720);
Renderer->SetOrthoProjection();
Renderer->PushProjectionMatrix(width, height, -500, 500);
//Renderer->SetFullScreenViewport();
boost::property_tree::ptree JSONsource;
Renderer->SetFullScreenViewport();
boost::property_tree::json_parser::read_json(ST::PathToResources + "config.json", JSONsource);
std::string effectJSON = JSONsource.get<std::string>("effect");
for (size_t i = 0; i < MAX_FACE_COUNT; i++)
{
faceRenderPair[i].first.SamplerMap[CONST_STRING_TEXTURE_UNIFORM] = "Asset "+boost::lexical_cast<std::string>(i+3)+"@20x.png";
faceRenderPair[i].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(Vector3f(0, 0, 0));
faceRenderPair[i].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(Vector3f(0, 512, 0));
faceRenderPair[i].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(Vector3f(512, 512, 0));
faceRenderPair[i].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(Vector3f(512, 512, 0));
faceRenderPair[i].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(Vector3f(512, 0, 0));
faceRenderPair[i].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB].push_back(Vector3f(0, 0, 0));
faceRenderPair[i].second.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(Vector2f(0, 0));
faceRenderPair[i].second.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(Vector2f(0, 1));
faceRenderPair[i].second.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(Vector2f(1, 1));
faceRenderPair[i].second.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(Vector2f(1, 1));
faceRenderPair[i].second.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(Vector2f(1, 0));
faceRenderPair[i].second.Data.Vec2CoordArr[CONST_STRING_TEXCOORD_ATTRIB].push_back(Vector2f(0, 0));
faceRenderPair[i].second.RefreshBuffer();
}
cap = cv::VideoCapture(0);
//cap = cv::VideoCapture("video.mp4");
//cap = cv::VideoCapture("bp.mp4");
// Check if camera opened successfully
if (!cap.isOpened()) {
std::cout << "Error opening video stream or file" << std::endl;
}
cap.set(CV_CAP_PROP_FRAME_WIDTH, 1280);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 720);
faceLandmarkDetector.StartTrackProcess();
Inited = true;
boost::property_tree::json_parser::read_json(ST::PathToResources + effectJSON, JSONsource);
sparkler.parse(JSONsource); // parse JSON
sparkler.load(); // load textures
sparkler.setCoords({ width / 2, height / 2, 0 });
}
void TMyApplication::InnerDeinit()
{
faceLandmarkDetector.StopTrackProcess();
cap.release();
Inited = false;
if (Console != NULL)
{
*Console<<"APP DEINIT\n";
}
}
void TMyApplication::InnerOnMouseDown(TMouseState& mouseState)
void TMyApplication::InnerOnTapDown(Vector2f p)
{
if (mouseState.LeftButtonPressed)
{
sparkler.setCoords({ (float)mouseState.X, Renderer->GetScreenHeight() - (float)mouseState.Y, 0 });
}
if (mouseState.RightButtonPressed)
{
if (sparkler.isSpawning())
{
sparkler.stopSpawn();
}
else
{
sparkler.startSpawn();
}
}
}
void TMyApplication::InnerOnMouseMove(TMouseState& mouseState)
void TMyApplication::InnerOnTapUp(Vector2f p)
{
if (mouseState.LeftButtonPressed)
{
sparkler.setCoords({ (float)mouseState.X, Renderer->GetScreenHeight() - (float)mouseState.Y, 0 });
}
}
void TMyApplication::InnerOnTapUpAfterMove(Vector2f p)
{
}
void TMyApplication::InnerOnMove(Vector2f p, Vector2f shift)
{
}
void TMyApplication::OnFling(Vector2f v)
{
}
void TMyApplication::InnerDraw()
{
glDisable(GL_DEPTH_TEST);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
sparkler.draw();
//glBindTexture(GL_TEXTURE_2D, ResourceManager->TexList[CONST_LOADING_BACKGROUND_BLACK]);
glBindTexture(GL_TEXTURE_2D, lastFrameTexture);
Renderer->DrawRect(Vector2f(0.f, 0.f), Vector2f(Renderer->GetMatrixWidth(), Renderer->GetMatrixHeight()));
/*
for (size_t i = 0; i < MAX_FACE_COUNT; i++)
{
TRenderParamsSetter params(faceRenderPair[i].first);
Renderer->DrawTriangleList(faceRenderPair[i].second);
}*/
}
void TMyApplication::InnerUpdate(size_t dt)
{
if (dt > 50)
cap >> frame; // get a new frame from camera/video or read image
if (frame.empty())
{
dt = 50;
return;
}
sparkler.update(dt / 1000.f);
cv::Mat image = frame.clone();
currentIndex++;
faceLandmarkArr = faceLandmarkDetector.GetFaceLandmarks(frame, currentIndex);
#ifdef USE_PREDICTION
frameArr.push_back(image);
while (frameArr.size() > 40)
{
lineShift++;
frameArr.erase(frameArr.begin());
}
currentIndex++;
faceLandmarkArr = faceLandmarkDetector.GetFaceLandmarks(frame, currentIndex);
bool newProcessedIndexFound = false;
int newProcessedIndex;
for (size_t i = 0; i < faceLandmarkArr.size(); i++)
{
if (faceLandmarkArr[i].valid)
{
if (!newProcessedIndexFound)
{
newProcessedIndexFound = true;
newProcessedIndex = faceLandmarkArr[i].frameIndex;
}
else
{
if (newProcessedIndex < faceLandmarkArr[i].frameIndex)
{
newProcessedIndex = faceLandmarkArr[i].frameIndex;
}
}
}
}
if (newProcessedIndexFound && newProcessedIndex > lastProcessedIndex)
{
indexStep = 0;
lastProcessedIndex = newProcessedIndex;
prevPassedIndex = currentIndex;
}
else
{
if (prevPassedIndex > lastProcessedIndex + indexStep)
{
indexStep++;
}
}
//std::cout << currentIndex << " " << lastProcessedIndex << " stepped:" << lastProcessedIndex + indexStep << " indexStep: " << indexStep << std::endl;
cv::Mat renderImage;
if (lastProcessedIndex + indexStep - lineShift < 0)
{
renderImage = frameArr[0];
}
else if (lastProcessedIndex + indexStep - lineShift >= frameArr.size())
{
renderImage = frameArr[frameArr.size() - 1];
}
else
{
renderImage = frameArr[lastProcessedIndex + indexStep - lineShift];
}
renderImage = renderImage.clone();
#else
cv::Mat renderImage = image;
#endif
cv::Mat cameraMatrix = (cv::Mat_<float>(3, 3) << 9.5434798118121421e+02, 0.0, 640.0, 0.0, 9.5434798118121421e+02, 360.0, 0.0, 0.0, 1.0);
cv::Mat distortionCoefficients = (cv::Mat_<float>(5, 1) << 3.5475494652047600e-02, - 5.9818881494543774e-01, 0.0, 0.0, 1.4642154802454528e+00);
for (size_t i = 0; i < faceLandmarkArr.size(); i++)
{
if (faceLandmarkArr[i].valid)
{
cv::rectangle(renderImage, faceLandmarkArr[i].faceRect, cv::Scalar(0, 0, 255), 1, 4, 0);
for (size_t j = 0; j < faceLandmarkArr[i].landmarkArr.size(); j++)
{
//cv::circle(renderImage, faceLandmarkArr[i].landmarkArr[j], 0.1, cv::Scalar(0, 255, 255), 4, 8, 0);
}
}
}
for (size_t index = 0; index < faceLandmarkArr.size(); index++)
{
if (faceLandmarkArr[index].valid)
{
faceStruct[index].ApplyPreds(faceLandmarkArr[index].landmarkArr, faceLandmarkArr[index].noticeablyChanged, cameraMatrix, distortionCoefficients);
for (size_t i = 0; i < LANDMARK_POINT_COUNT; i++)
{
cv::ellipse(renderImage, cv::Point2f(faceStruct[index].preds[i](0), 720 - faceStruct[index].preds[i](1)), cv::Size(2, 2), 0, 0, 360, cv::Scalar(255, 128, 128), 4, 8, 0);
}
cv::line(renderImage, flipVertical(faceStruct[index].boxModelDst[0]), flipVertical(faceStruct[index].boxModelDst[1]), cv::Scalar(0, 0, 255));
cv::line(renderImage, flipVertical(faceStruct[index].boxModelDst[1]), flipVertical(faceStruct[index].boxModelDst[2]), cv::Scalar(0, 0, 255));
cv::line(renderImage, flipVertical(faceStruct[index].boxModelDst[2]), flipVertical(faceStruct[index].boxModelDst[3]), cv::Scalar(0, 0, 255));
cv::line(renderImage, flipVertical(faceStruct[index].boxModelDst[3]), flipVertical(faceStruct[index].boxModelDst[0]), cv::Scalar(0, 255, 0));
cv::line(renderImage, flipVertical(faceStruct[index].boxModelDst[4]), flipVertical(faceStruct[index].boxModelDst[5]), cv::Scalar(0, 0, 255));
cv::line(renderImage, flipVertical(faceStruct[index].boxModelDst[5]), flipVertical(faceStruct[index].boxModelDst[6]), cv::Scalar(0, 0, 255));
cv::line(renderImage, flipVertical(faceStruct[index].boxModelDst[6]), flipVertical(faceStruct[index].boxModelDst[7]), cv::Scalar(0, 0, 255));
cv::line(renderImage, flipVertical(faceStruct[index].boxModelDst[7]), flipVertical(faceStruct[index].boxModelDst[4]), cv::Scalar(0, 255, 0));
cv::line(renderImage, flipVertical(faceStruct[index].boxModelDst[0]), flipVertical(faceStruct[index].boxModelDst[4]), cv::Scalar(0, 255, 0));
cv::line(renderImage, flipVertical(faceStruct[index].boxModelDst[1]), flipVertical(faceStruct[index].boxModelDst[5]), cv::Scalar(0, 0, 255));
cv::line(renderImage, flipVertical(faceStruct[index].boxModelDst[2]), flipVertical(faceStruct[index].boxModelDst[6]), cv::Scalar(0, 0, 255));
cv::line(renderImage, flipVertical(faceStruct[index].boxModelDst[3]), flipVertical(faceStruct[index].boxModelDst[7]), cv::Scalar(0, 255, 0));
Vector2f posFrom = faceStruct[index].center - faceStruct[index].size*0.5f* 1.35f;
Vector2f posTo = faceStruct[index].center + faceStruct[index].size*0.5f* 1.35f;
ApplyVertexCoordVec(faceRenderPair[index].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB], posFrom, posTo, 0);
faceRenderPair[index].second.RefreshBuffer();
}
else
{
ApplyVertexCoordVec(faceRenderPair[index].second.Data.Vec3CoordArr[CONST_STRING_POSITION_ATTRIB], { 0,0 }, { 0,0 }, 0);
faceRenderPair[index].second.RefreshBuffer();
}
}
glBindTexture(GL_TEXTURE_2D, lastFrameTexture);
static std::array<char, 1280 * 720 * 3> buffer;
int step = renderImage.step;
int height = renderImage.rows;
int width = renderImage.cols;
int channels = 3;
char * data = (char *)renderImage.data;
for (int i = 0; i < height; i++)
{
int ci = height - i - 1;
memcpy(&buffer[i*width*channels], &(data[ci*step]), width*channels);
}
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGB,
1280,
720,
0,
GL_BGR_EXT,
GL_UNSIGNED_BYTE,
&buffer[0]);
}
bool TMyApplication::IsInited()
{
return Inited;
}
Regular → Executable
+55 -13
View File
@@ -24,25 +24,56 @@
#include "boost/signals2.hpp"//Signal must be included after asio
#include "../windows/DoubleHitBalls-win/DoubleHitBalls-win/FaceLandmarkDetector.h"
#include "../windows/DoubleHitBalls-win/DoubleHitBalls-win/ValueSmoother.h"
struct FaceStruct
{
SE::Vector2f center;
SE::Vector2f size;
std::array<SE::Vector2f, LANDMARK_POINT_COUNT> preds;
std::vector<cv::Point3f> modelPoints;
cv::Mat rotationVector;
cv::Mat translationVector;
cv::Mat rotationMatrix;
cv::Mat poseMatrix;
cv::Mat eulerAngles;
std::vector<cv::Point3d> boxModelSrc;
std::vector<cv::Point2d> boxModelDst;
ValueSmoother landmarkSmoothers[2 * LANDMARK_POINT_COUNT];
ValueSmoother rotationVectorSmoothers[3];
ValueSmoother translationVectorSmoothers[3];
FaceStruct();
FaceStruct(const std::array<cv::Point2f, LANDMARK_POINT_COUNT>& fromPreds, cv::Mat& cameraMatrix, cv::Mat& distortionCoefficients);
void CalcFromPreds(bool noticeablyChanged, cv::Mat& cameraMatrix, cv::Mat& distortionCoefficients);
void ApplyPreds(const std::array<cv::Point2f, LANDMARK_POINT_COUNT>& fromPred, bool noticeablyChanged, cv::Mat& cameraMatrix, cv::Mat& distortionCoefficientss);
void InnerApplyPreds(const std::array<cv::Point2f, LANDMARK_POINT_COUNT>& fromPreds);
};
using namespace SE;
extern boost::signals2::signal<void(Vector2f)> OnTapUpSignal;
extern boost::signals2::signal<void(Vector2f)> OnTapUpAfterMoveSignal;
extern boost::signals2::signal<void(Vector2f)> OnTapDownSignal;
extern boost::signals2::signal<void(Vector2f)> OnFlingSignal;
extern boost::signals2::signal<void(Vector2f)> OnScrollSignal;
extern boost::signals2::signal<void()> OnDrawSignal;
extern const std::string CONST_LOADING_BACKGROUND_BLACK;
class TMyApplication : public TApplication
{
protected:
ParticleEffect sparkler;
bool Inited;
std::array<TRenderPair, MAX_FACE_COUNT> faceRenderPair;
public:
TMyApplication() : TApplication() { }
TMyApplication() : TApplication(), Inited(false) { }
virtual void InnerInit();
@@ -52,9 +83,17 @@ public:
virtual void InnerUpdate(size_t dt);
virtual void InnerOnMouseDown(TMouseState& mouseState);
bool IsInited();
virtual void InnerOnMouseMove(TMouseState& mouseState);
virtual void InnerOnTapDown(Vector2f p);
virtual void InnerOnTapUp(Vector2f p);
virtual void InnerOnTapUpAfterMove(Vector2f p);
virtual void InnerOnMove(Vector2f p, Vector2f shift);
virtual void OnFling(Vector2f v);
};
@@ -62,4 +101,7 @@ public:
extern TMyApplication* Application;
#endif
View File
File mode changed.
File mode changed.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

File mode changed.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

File mode changed.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File
File mode changed.
Regular → Executable
View File
File mode changed.
Regular → Executable
View File
File mode changed.
File mode changed.
File mode changed.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

File mode changed.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

File mode changed.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

File mode changed.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

File mode changed.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 67 KiB

File mode changed.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

File mode changed.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

File mode changed.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

File mode changed.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

File mode changed.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

File mode changed.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File
File mode changed.
View File
File mode changed.
Regular → Executable
View File
File mode changed.
Regular → Executable
View File
File mode changed.
Regular → Executable
View File
File mode changed.
Regular → Executable
View File
File mode changed.
View File
File mode changed.
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -22,33 +22,35 @@
<ProjectGuid>{1CC98EEE-BBCB-4D79-B6D7-8511789172C5}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>DoubleHitBallswin</RootNamespace>
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
<ProjectName>TorchFaceTracker</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>NotSet</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>NotSet</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -110,13 +112,13 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>TARGET_WIN32;DEBUG;_WIN32_WINNT=0x0501;EIGEN_DONT_ALIGN_STATICALLY;_WINDOWS;WIN32;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../../../game;../../../../tes-engine;../../../../eigen;../../../../boost_1_63_0/;../../../../boost_1_63_0/bin.v2/libs/system/build/msvc-14.0/debug/address-model-64/link-static/threading-multi;../../../../boost_1_63_0/bin.v2/libs/date_time/build/msvc-14.0/debug/address-model-64/link-static/threading-multi/;../../../../boost_1_63_0/bin.v2/libs/regex/build/msvc-14.0/debug/address-model-64/link-static/threading-multi;../../../../boost_1_63_0/bin.v2/libs/thread/build/msvc-14.0/debug/address-model-64/link-static/threading-multi;../../../../boost_1_63_0/bin.v2/libs/chrono/build/msvc-14.0/debug/address-model-64/link-static/threading-multi;../../../../boost_1_63_0/bin.v2/libs/signals/build/msvc-14.0/debug/address-model-64/link-static/threading-multi;../../../../libs/boost-gil-extension;../../../../libs/jpeg-9;../../../../libs/jpeg-9/vc10;../../../../libs/lpng1510</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../../../../luajit-vlad/luajit-vlad;..\..\..\..\..\Torch7\distro\install\include;C:\Work\TorchProjects\dlib;D:\Work\TorchProjects\dlib\dlib\..;..\..\..\..\..\Torch7\distro\exe\luajit-2.1\src;..\..\..\..\..\opencv3.4\build\include;D:\Work\Torch7\distro\install\include;../../../game;../../../../tes-engine;../../../../eigen;../../../../boost_1_67_0/;../../../../libs/boost-gil-extension;../../../../libs/jpeg-9;../../../../libs/jpeg-9/vc10;../../../../libs/lpng1510</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4503</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>../../../game;../../../../tes-engine;../../../../eigen;../../../../boost_1_63_0/;../../../../boost_1_63_0/bin.v2/libs/system/build/msvc-14.0/debug/address-model-64/link-static/threading-multi;../../../../boost_1_63_0/bin.v2/libs/date_time/build/msvc-14.0/debug/address-model-64/link-static/threading-multi/;../../../../boost_1_63_0/bin.v2/libs/regex/build/msvc-14.0/debug/address-model-64/link-static/threading-multi;../../../../boost_1_63_0/bin.v2/libs/thread/build/msvc-14.0/debug/address-model-64/link-static/threading-multi;../../../../boost_1_63_0/bin.v2/libs/chrono/build/msvc-14.0/debug/address-model-64/link-static/threading-multi;../../../../boost_1_63_0/bin.v2/libs/filesystem/build/msvc-14.0/debug/address-model-64/link-static/threading-multi;../../../../boost_1_63_0/bin.v2/libs/signals/build/msvc-14.0/debug/address-model-64/link-static/threading-multi;../../../../libs/boost-gil-extension;../../../../libs/jpeg-9;../../../../libs/jpeg-9/vc10;../../../../libs/lpng1510;../x64/Debug</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>../../../game;../../../../tes-engine;../../../../eigen;../../../../boost_1_67_0/stage/lib;../../../../libs/jpeg-9;../../../../libs/jpeg-9/vc10;../../../../libs/lpng1510;../x64/Debug</AdditionalLibraryDirectories>
<AdditionalDependencies>libjpeg.lib;libpng.lib;Engine.lib;opengl32.lib;glu32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
@@ -146,30 +148,33 @@
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<Optimization>Disabled</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;TARGET_WIN32;_WIN32_WINNT=0x0501;WIN32_LEAN_AND_MEAN;EIGEN_DONT_ALIGN_STATICALLY;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../../../game;../../../../tes-engine;../../../../eigen;../../../../boost_1_63_0/;../../../../boost_1_63_0/bin.v2/libs/system/build/msvc-14.0/release/address-model-64/link-static/threading-multi;../../../../boost_1_63_0/bin.v2/libs/date_time/build/msvc-14.0/release/address-model-64/link-static/threading-multi/;../../../../boost_1_63_0/bin.v2/libs/regex/build/msvc-14.0/release/address-model-64/link-static/threading-multi;../../../../boost_1_63_0/bin.v2/libs/thread/build/msvc-14.0/release/address-model-64/link-static/threading-multi;../../../../boost_1_63_0/bin.v2/libs/chrono/build/msvc-14.0/release/address-model-64/link-static/threading-multi;../../../../boost_1_63_0/bin.v2/libs/signals/build/msvc-14.0/release/address-model-64/link-static/threading-multi;../../../../libs/boost-gil-extension;../../../../libs/jpeg-9;../../../../libs/jpeg-9/vc10;../../../../libs/lpng1510</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../../../../luajit-vlad/luajit-vlad;..\..\..\..\..\Torch7\distro\install\include;C:\Work\TorchProjects\dlib;D:\Work\TorchProjects\dlib\dlib\..;..\..\..\..\..\Torch7\distro\exe\luajit-2.1\src;..\..\..\..\..\opencv3.4\build\include;D:\Work\Torch7\distro\install\include;../../../game;../../../../tes-engine;../../../../eigen;../../../../boost_1_67_0/;../../../../libs/boost-gil-extension;../../../../libs/jpeg-9;../../../../libs/jpeg-9/vc10;../../../../libs/lpng1510</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4503</DisableSpecificWarnings>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>../../../game;../../../../tes-engine;../../../../eigen;../../../../boost_1_63_0/;../../../../boost_1_63_0/stage/x64/lib;../../../../boost_1_63_0/bin.v2/libs/system/build/msvc-14.0/release/address-model-64/link-static/threading-multi;../../../../boost_1_63_0/bin.v2/libs/date_time/build/msvc-14.0/release/address-model-64/link-static/threading-multi/;../../../../boost_1_63_0/bin.v2/libs/regex/build/msvc-14.0/release/address-model-64/link-static/threading-multi;../../../../boost_1_63_0/bin.v2/libs/thread/build/msvc-14.0/release/address-model-64/link-static/threading-multi;../../../../boost_1_63_0/bin.v2/libs/chrono/build/msvc-14.0/release/address-model-64/link-static/threading-multi;../../../../boost_1_63_0/bin.v2/libs/signals/build/msvc-14.0/release/address-model-64/link-static/threading-multi;../../../../libs/boost-gil-extension;../../../../libs/jpeg-9;../../../../libs/jpeg-9/vc10;../../../../libs/lpng1510;../x64/Release</AdditionalLibraryDirectories>
<AdditionalDependencies>libjpeg.lib;libpng.lib;Engine.lib;opengl32.lib;glu32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\..\..\..\opencv3.4-build\lib\$(Configuration);..\..\..\..\..\opencv3.4-build\3rdparty\lib\$(Configuration);..\..\..\..\..\opencv3.4-build\3rdparty\ippicv\ippicv_win\lib\intel64;../../../game;../../../../tes-engine;../../../../eigen;../../../../boost_1_67_0/stage/lib;../../../../libs/jpeg-9;../../../../libs/jpeg-9/vc10;../x64/Release;C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v9.1/lib/x64;C:/Program Files/NVIDIA GPU Computing</AdditionalLibraryDirectories>
<AdditionalDependencies>ippiw.lib;ippicvmt.lib;cudart.lib;nppc.lib;nppial.lib;nppicc.lib;nppicom.lib;nppidei.lib;nppif.lib;nppig.lib;nppim.lib;nppist.lib;nppisu.lib;nppitc.lib;npps.lib;cufft.lib;opencv_dnn341.lib;opencv_highgui341.lib;opencv_videoio341.lib;opencv_imgcodecs341.lib;opencv_imgproc341.lib;opencv_core341.lib;opencv_calib3d341.lib;opencv_cudev341.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;Engine.lib;opengl32.lib;glu32.lib;libjpeg-static.lib;libpng-static.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\game\main_code.cpp" />
<ClCompile Include="FaceLandmarkDetector.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="ValueSmoother.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\game\main_code.h" />
<ClInclude Include="FaceLandmarkDetector.h" />
<ClInclude Include="main.h" />
<ClInclude Include="ValueSmoother.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
@@ -21,6 +21,12 @@
<ClCompile Include="..\..\..\game\main_code.cpp">
<Filter>Файлы исходного кода</Filter>
</ClCompile>
<ClCompile Include="FaceLandmarkDetector.cpp">
<Filter>Файлы исходного кода</Filter>
</ClCompile>
<ClCompile Include="ValueSmoother.cpp">
<Filter>Файлы исходного кода</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="main.h">
@@ -29,5 +35,11 @@
<ClInclude Include="..\..\..\game\main_code.h">
<Filter>Заголовочные файлы</Filter>
</ClInclude>
<ClInclude Include="FaceLandmarkDetector.h">
<Filter>Заголовочные файлы</Filter>
</ClInclude>
<ClInclude Include="ValueSmoother.h">
<Filter>Заголовочные файлы</Filter>
</ClInclude>
</ItemGroup>
</Project>
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
@@ -0,0 +1,490 @@
#include "FaceLandmarkDetector.h"
static const size_t faceTrackerWidth = 300;
static const size_t faceTrackerHeight = 300;
static const double faceTrackerScaleFactor = 1.0;
static const cv::Scalar faceTrackerMeanVal(104.0, 177.0, 123.0);
float calcSquaredDistanceBetweenFaces(const cv::Rect& face1, const cv::Rect& face2)
{
cv::Point2f oldCenter(face1.x + face1.width*0.5f, face1.y + face1.height*0.5f);
cv::Point2f newCenter(face2.x + face2.width*0.5f, face2.y + face2.height*0.5f);
float distanceX = newCenter.x - oldCenter.x;
float distanceY = newCenter.y - oldCenter.y;
float squareDistance = distanceX * distanceX + distanceY * distanceY;
return squareDistance;
}
double calcSimilarity(const cv::Mat& first, const cv::Mat& second)
{
// assumes that first and second have the same size
double errorL2 = cv::norm(first, second, CV_L2);
// Convert to a reasonable scale, since L2 error is summed across all pixels of the image.
double similarity = errorL2 / static_cast<double>(first.rows * first.cols);
return similarity;
}
FaceLandmarkDetector::FaceLandmarkDetector()
{
static const cv::String faceTrackerConfiguration = "deploy.prototxt";
static const cv::String faceTrackerBinary = "res10_300x300_ssd_iter_140000.caffemodel";
#ifdef USE_3D_LANDMARKS
static const cv::String landmarkTrackerConfiguration = "fa_deploy.prototxt";
static const cv::String landmarkTrackerBinary = "fa__iter_1400000.caffemodel";
#else
static const cv::String landmarkTrackerConfiguration = "landmark_deploy.prototxt";
static const cv::String landmarkTrackerBinary = "VanFace.caffemodel";
#endif
faceNet = cv::dnn::readNetFromCaffe(faceTrackerConfiguration, faceTrackerBinary);
for (size_t i = 0; i < MAX_FACE_COUNT; i++)
{
landmarkNetArr[i] = cv::dnn::readNetFromCaffe(landmarkTrackerConfiguration, landmarkTrackerBinary);
}
}
FaceLandmarkDetector::~FaceLandmarkDetector()
{
StopTrackProcess();
}
void FaceLandmarkDetector::StartTrackProcess()
{
if (started)
{
return;
}
//Some init setup
syncStop = false;
for (size_t i = 0; i < MAX_FACE_COUNT; i++)
{
syncFaceRectArr[i].valid = false;
syncFaceLandmarkArr[i].valid = false;
}
syncLastFrame = cv::Mat();
//Start threads
findFaceThread = std::thread([this]() { this->FindFaceThreadProc(); });
for (size_t i = 0; i < MAX_FACE_COUNT; i++)
{
landmarkThreadArr[i] = std::thread([this, i]() { this->FindLandmarkThreadProc(i); });
}
started = true;
}
void FaceLandmarkDetector::StopTrackProcess()
{
if (!started)
{
return;
}
//Do not remove braces
{
std::unique_lock<std::mutex> lock(syncMutex);
syncStop = true;
syncFaceRectCond.notify_all();
}
findFaceThread.join();
for (size_t i = 0; i < MAX_FACE_COUNT; i++)
{
landmarkThreadArr[i].join();
}
started = false;
}
std::array<FaceLandmarkStruct, MAX_FACE_COUNT> FaceLandmarkDetector::GetFaceLandmarks(cv::Mat frame, int frameIndex)
{
std::array<FaceLandmarkStruct, MAX_FACE_COUNT> result;
//Sync area
std::unique_lock<std::mutex> lock(syncMutex);
// OUT to face rect thread >>>>
syncLastFrame = frame;
syncLastFrameIndex = frameIndex;
// IN from landmark threads <<<<
result = syncFaceLandmarkArr;
return result;
}
void FaceLandmarkDetector::FindFaceThreadProc()
{
cv::Mat localFrame;
std::array<FaceIntermediateStruct, MAX_FACE_COUNT> localFaceRectArr;
bool localStop = false;
int localFrameIndex = 0;
while (!syncStop)
{
if (!localFrame.empty())
{
std::vector<cv::Rect> faces = InnerFindFaces(localFrame);
std::vector<cv::Mat> faceFrames;
//Get rid of faces that are too big
for (size_t i = 0; i < faces.size(); )
{
if (faces[i].x < 0 || faces[i].y < 0 || (faces[i].x + faces[i].width >= localFrame.cols) || (faces[i].y + faces[i].height >= localFrame.rows))
{
faces.erase(faces.begin() + i);
}
else
{
i++;
}
}
//Cut faces from frame
for (size_t i = 0; i <faces.size(); i++)
{
faceFrames.push_back(InnerCutFaceFrame(localFrame, faces[i]));
}
InnerSeparateFacesToBuckets(faces, faceFrames, localFaceRectArr);
for (size_t i = 0; i < localFaceRectArr.size(); i++)
{
if (localFaceRectArr[i].valid)
{
localFaceRectArr[i].frameIndex = localFrameIndex;
}
}
}
//Sync area
std::unique_lock<std::mutex> lock(syncMutex);
// OUT to landmark Threads >>>>
syncFaceRectArr = localFaceRectArr;
syncFaceRectCond.notify_all();
// IN from main thread <<<<
localFrame = syncLastFrame;
localFrameIndex = syncLastFrameIndex;
localStop = syncStop;
}
}
void FaceLandmarkDetector::FindLandmarkThreadProc(size_t threadIndex)
{
FaceIntermediateStruct localInputFace;
FaceLandmarkStruct localOutputLandmarks;
bool localStop = false;
while (!localStop)
{
if (localInputFace.valid)
{
#ifdef USE_3D_LANDMARKS
cv::Mat landmarkInputBlob = cv::dnn::blobFromImage(localInputFace.faceFrame, 1.0, cv::Size(40, 40), cv::Scalar(), false, false);
#else
cv::Mat landmarkInputBlob = cv::dnn::blobFromImage(localInputFace.faceFrame, 1.0, cv::Size(60, 60), cv::Scalar(), false, false);
#endif
landmarkInputBlob.reshape(0, std::vector<int>{ 1, 1, localInputFace.faceFrame.rows, localInputFace.faceFrame.cols });
landmarkNetArr[threadIndex].setInput(landmarkInputBlob);
#ifdef USE_3D_LANDMARKS
cv::Mat featureBlob = landmarkNetArr[threadIndex].forward("Dense2");
#else
cv::Mat featureBlob = landmarkNetArr[threadIndex].forward("Dense3");
#endif
for (int i = 0; i < featureBlob.cols / 2; i++)
{
cv::Point landmarkPoint;
landmarkPoint.x = int(featureBlob.at<float>(0, 2 * i) * (localInputFace.faceRect.width) + localInputFace.faceRect.x);
landmarkPoint.y = int(featureBlob.at<float>(0, 2 * i + 1) * (localInputFace.faceRect.height) + localInputFace.faceRect.y);
localOutputLandmarks.landmarkArr[i] = landmarkPoint;
}
localOutputLandmarks.faceRect = localInputFace.faceRect;
localOutputLandmarks.frameIndex = localInputFace.frameIndex;
localOutputLandmarks.noticeablyChanged = localInputFace.noticeablyChanged;
localOutputLandmarks.valid = true;
}
else
{
localOutputLandmarks.valid = false;
}
//Sync area
std::unique_lock<std::mutex> lock(syncMutex);
// OUT to main thread >>>>
syncFaceLandmarkArr[threadIndex] = localOutputLandmarks;
bool doLoop = true;
while (doLoop)
{
//IN from face rect thread <<<<
localInputFace = syncFaceRectArr[threadIndex];
localStop = syncStop;
//Time to quit
if (localStop)
{
doLoop = false;
}
if (!localInputFace.valid)
{
syncFaceLandmarkArr[threadIndex].valid = false;
syncFaceRectCond.wait(lock);
}
else
{
doLoop = false;
}
}
}
}
std::vector<cv::Rect> FaceLandmarkDetector::InnerFindFaces(cv::Mat frame)
{
if (frame.channels() == 4)
{
cvtColor(frame, frame, cv::COLOR_BGRA2BGR);
}
cv::Mat inputBlob = cv::dnn::blobFromImage(frame, faceTrackerScaleFactor, cv::Size(faceTrackerWidth, faceTrackerHeight), faceTrackerMeanVal, false, false);
faceNet.setInput(inputBlob, "data");
cv::Mat detection = faceNet.forward("detection_out");
cv::Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());
float confidenceThreshold = 0.5f;
std::vector<cv::Rect> faces;
for (int i = 0; i < detectionMat.rows; i++)
{
float confidence = detectionMat.at<float>(i, 2);
if (confidence > confidenceThreshold)
{
int xLeftBottom = static_cast<int>(detectionMat.at<float>(i, 3) * frame.cols);
int yLeftBottom = static_cast<int>(detectionMat.at<float>(i, 4) * frame.rows);
int xRightTop = static_cast<int>(detectionMat.at<float>(i, 5) * frame.cols);
int yRightTop = static_cast<int>(detectionMat.at<float>(i, 6) * frame.rows);
cv::Rect object((int)xLeftBottom, (int)yLeftBottom,
(int)(xRightTop - xLeftBottom),
(int)(yRightTop - yLeftBottom));
object.x = object.x - object.width*0.1f;
object.y = object.y - object.height*0.1f;
object.width = object.width*1.2f;
object.height = object.height*1.2f;
faces.push_back(object);
}
}
return faces;
}
cv::Mat FaceLandmarkDetector::InnerCutFaceFrame(cv::Mat frame, cv::Rect faceRect)
{
cv::Mat srcROI(frame, faceRect);
cv::Mat img2;
cvtColor(srcROI, img2, CV_RGB2GRAY);
img2.convertTo(img2, CV_32FC1);
#ifdef USE_3D_LANDMARKS
cv::Size dsize = cv::Size(40, 40);
#else
cv::Size dsize = cv::Size(60, 60);
#endif
cv::Mat img3 = cv::Mat(dsize, CV_32FC1);
cv::resize(img2, img3, dsize, 0, 0, cv::INTER_CUBIC);
cv::Mat tmp_m, tmp_sd;
double m = 0, sd = 0;
meanStdDev(img3, tmp_m, tmp_sd);
m = tmp_m.at<double>(0, 0);
sd = tmp_sd.at<double>(0, 0);
img3 = (img3 - m) / (0.000001 + sd);
return img3;
}
void FaceLandmarkDetector::InnerSeparateFacesToBuckets(std::vector<cv::Rect>& faceArr, std::vector<cv::Mat>& faceFrameArr, std::array<FaceIntermediateStruct, MAX_FACE_COUNT>& inOutBucketArr)
{
static std::array<std::vector<std::pair<cv::Rect, cv::Mat>>, MAX_FACE_COUNT> facesBelongsToSpace;
for (size_t i = 0; i < MAX_FACE_COUNT; i++)
{
facesBelongsToSpace[i].clear();
}
//Distribute current faces to nearest old positions
for (size_t i = 0; i < faceArr.size(); )
{
float lastDistance = 1000000.f;
int lastIndex = -1;
for (size_t j = 0; j < MAX_FACE_COUNT; j++)
{
if (inOutBucketArr[j].valid)
{
float newDistance = calcSquaredDistanceBetweenFaces(inOutBucketArr[j].faceRect, faceArr[i]);
if (newDistance < lastDistance)
{
lastDistance = newDistance;
lastIndex = j;
}
}
}
if (lastIndex != -1)
{
facesBelongsToSpace[lastIndex].push_back(std::make_pair(faceArr[i], faceFrameArr[i]));
faceArr.erase(faceArr.begin() + i);
faceFrameArr.erase(faceFrameArr.begin() + i);
}
else
{
i++;
}
}
//Mark "free spots" to those that don't have any face belong to
for (size_t j = 0; j < MAX_FACE_COUNT; j++)
{
if (inOutBucketArr[j].valid)
{
if (facesBelongsToSpace[j].size() == 0)
{
inOutBucketArr[j].valid = false;
}
}
}
//Find nearest face in each space - others return back to pool
for (size_t j = 0; j < MAX_FACE_COUNT; j++)
{
if (inOutBucketArr[j].valid)
{
float lastDistance = calcSquaredDistanceBetweenFaces(inOutBucketArr[j].faceRect, facesBelongsToSpace[j][0].first);
int lastIndex = 0;
for (size_t i = 1; i < facesBelongsToSpace[j].size(); i++)
{
float newDistance = calcSquaredDistanceBetweenFaces(inOutBucketArr[j].faceRect, facesBelongsToSpace[j][i].first);
if (newDistance < lastDistance)
{
lastDistance = newDistance;
lastIndex = i;
}
}
inOutBucketArr[j].faceRect = facesBelongsToSpace[j][lastIndex].first;
inOutBucketArr[j].faceFrame = facesBelongsToSpace[j][lastIndex].second;
inOutBucketArr[j].noticeablyChanged =
calcSimilarity(inOutBucketArr[j].faceFrame, facesBelongsToSpace[j][lastIndex].second) > 0.01 ||
lastDistance > 100.0;
facesBelongsToSpace[j].erase(facesBelongsToSpace[j].begin() + lastIndex);
for (size_t k = 0; k < facesBelongsToSpace[j].size(); k++)
{
faceArr.push_back(facesBelongsToSpace[j][k].first);
faceFrameArr.push_back(facesBelongsToSpace[j][k].second);
}
}
}
//Distribute faces from pool to empty slots
for (size_t j = 0; j < MAX_FACE_COUNT; j++)
{
if (!inOutBucketArr[j].valid)
{
if (faceArr.size() > 0)
{
inOutBucketArr[j].valid = true;
inOutBucketArr[j].faceRect = faceArr[0];
inOutBucketArr[j].faceFrame = faceFrameArr[0];
faceArr.erase(faceArr.begin());
faceFrameArr.erase(faceFrameArr.begin());
}
}
}
}
@@ -0,0 +1,103 @@
#pragma once
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/calib3d.hpp>
#include <algorithm>
#include <memory>
#include <string>
#include <vector>
#include <chrono>
#include <iostream>
#include <opencv2/dnn.hpp>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#define USE_3D_LANDMARKS
//#include "boost/thread.hpp"
constexpr size_t LANDMARK_POINT_COUNT = 68;
constexpr size_t MAX_FACE_COUNT = 5;
struct FaceIntermediateStruct
{
bool valid = false;
cv::Rect faceRect;
cv::Mat faceFrame;
int frameIndex;
bool noticeablyChanged = false;
};
struct FaceLandmarkStruct
{
bool valid = false;
cv::Rect faceRect;
std::array<cv::Point2f, LANDMARK_POINT_COUNT> landmarkArr;
int frameIndex;
bool noticeablyChanged = false;
};
class FaceLandmarkDetector
{
public:
FaceLandmarkDetector();
~FaceLandmarkDetector();
void StartTrackProcess();
void StopTrackProcess();
std::array<FaceLandmarkStruct, MAX_FACE_COUNT> GetFaceLandmarks(cv::Mat frame, int frameIndex);
protected:
cv::dnn::Net faceNet;
std::array<cv::dnn::Net, MAX_FACE_COUNT> landmarkNetArr;
bool started = false;
//Sync variables - shared between threads:
cv::Mat syncLastFrame;
int syncLastFrameIndex;
std::array<FaceIntermediateStruct, MAX_FACE_COUNT> syncFaceRectArr;
std::array<FaceLandmarkStruct, MAX_FACE_COUNT> syncFaceLandmarkArr;
std::mutex syncMutex;
bool syncStop = false;
std::condition_variable syncFaceRectCond;
std::thread findFaceThread;
void FindFaceThreadProc();
std::array<std::thread, MAX_FACE_COUNT> landmarkThreadArr;
void FindLandmarkThreadProc(size_t threadIndex);
std::vector<cv::Rect> InnerFindFaces(cv::Mat frame);
cv::Mat InnerCutFaceFrame(cv::Mat frame, cv::Rect faceRect);
void InnerSeparateFacesToBuckets(std::vector<cv::Rect>& faceArr, std::vector<cv::Mat>& faceFrameArr, std::array<FaceIntermediateStruct, MAX_FACE_COUNT>& inOutBucketArr);
};
@@ -0,0 +1,98 @@
#include "ValueSmoother.h"
#include <array>
#include <chrono>
using namespace std;
using namespace std::chrono;
float snapCurve(float x)
{
float y = 1.0 / (x + 1.0);
y = (1.0 - y) * 2.0;
if (y > 1.0) {
return 1.0;
}
return y;
}
void ValueSmoother::reset()
{
inited = false;
}
float ValueSmoother::responsiveAnalogReadSimple(float newValue)
{
if (!inited)
{
inited = true;
smoothValue = newValue;
return smoothValue;
}
auto diff = abs(newValue - smoothValue);
float snap = snapCurve(diff * SNAP_MULTIPLIER_SIMPLE);
smoothValue += (newValue - smoothValue) * snap;
return smoothValue;
}
void ExtendedValueSmoother::reset()
{
inited = false;
}
float ExtendedValueSmoother::responsiveAnalogRead(float newValue)
{
using namespace std::chrono;
auto ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
auto diff = abs(newValue - smoothValue);
// measure the difference between the new value and current value over time
// to get a more reasonable indication of how far off the current smooth value is
// compared to the actual measurements
errorEMA += ((newValue - smoothValue) - errorEMA) * 0.4;
// if sleep has been enabled, keep track of when we're asleep or not by marking the time of last activity and testing to see how much time has passed since then
if (SLEEP_ENABLE) {
// recalculate sleeping status
// (asleep if last activity was over SLEEP_DELAY_MS ago)
sleeping = abs(errorEMA) < ACTIVITY_THRESHOLD;
}
if (SLEEP_ENABLE && sleeping) {
return smoothValue;
}
auto snap = snapCurve(diff * SNAP_MULTIPLIER);
// when sleep is enabled, the emphasis is stopping on a responsiveValue quickly, and it's less about easing into position. If sleep is enabled, add a small amount to snap so it'll tend to snap into a more accurate position before sleeping starts.
if (SLEEP_ENABLE) {
snap = snap * 0.5 + 0.5;
}
// calculate the exponential moving average based on the snap
smoothValue += (newValue - smoothValue) * snap;
return smoothValue;
}
Loaded 100 of 121 files, more files were not shown because too many files have changed in this diff. Show more