Restore old grease pencil code
This commit is contained in:
parent
c6d74fc4ea
commit
c56fb4bbf1
9
Shaders/grease_pencil/grease_pencil.frag.glsl
Normal file
9
Shaders/grease_pencil/grease_pencil.frag.glsl
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
in vec4 color;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
fragColor = color;
|
||||||
|
}
|
25
Shaders/grease_pencil/grease_pencil.json
Normal file
25
Shaders/grease_pencil/grease_pencil.json
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"contexts": [
|
||||||
|
{
|
||||||
|
"name": "grease_pencil",
|
||||||
|
"depth_write": false,
|
||||||
|
"compare_mode": "always",
|
||||||
|
"cull_mode": "none",
|
||||||
|
"blend_source": "source_alpha",
|
||||||
|
"blend_destination": "inverse_source_alpha",
|
||||||
|
"blend_operation": "add",
|
||||||
|
"alpha_blend_source": "source_alpha",
|
||||||
|
"alpha_blend_destination": "inverse_source_alpha",
|
||||||
|
"alpha_blend_operation": "add",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"name": "VP",
|
||||||
|
"link": "_viewProjectionMatrix"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"texture_params": [],
|
||||||
|
"vertex_shader": "grease_pencil.vert.glsl",
|
||||||
|
"fragment_shader": "grease_pencil.frag.glsl"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
13
Shaders/grease_pencil/grease_pencil.vert.glsl
Normal file
13
Shaders/grease_pencil/grease_pencil.vert.glsl
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
in vec3 pos;
|
||||||
|
in vec4 col;
|
||||||
|
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
uniform mat4 VP;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
color = col;
|
||||||
|
gl_Position = VP * vec4(pos.xyz, 1.0);
|
||||||
|
}
|
178
Sources/armory/data/GreasePencilData.hx
Normal file
178
Sources/armory/data/GreasePencilData.hx
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
package armory.data;
|
||||||
|
|
||||||
|
import kha.graphics4.VertexBuffer;
|
||||||
|
import kha.graphics4.IndexBuffer;
|
||||||
|
import kha.graphics4.Usage;
|
||||||
|
import kha.graphics4.VertexStructure;
|
||||||
|
import kha.graphics4.VertexData;
|
||||||
|
import kha.graphics4.PipelineState;
|
||||||
|
import kha.graphics4.CompareMode;
|
||||||
|
import kha.graphics4.CullMode;
|
||||||
|
import kha.graphics4.ConstantLocation;
|
||||||
|
import iron.math.Vec4;
|
||||||
|
import iron.object.Transform;
|
||||||
|
import iron.data.SceneFormat;
|
||||||
|
import iron.data.ShaderData;
|
||||||
|
import iron.data.ShaderData.ShaderContext;
|
||||||
|
|
||||||
|
class GreasePencilData extends Data {
|
||||||
|
|
||||||
|
public var name:String;
|
||||||
|
public var raw:TGreasePencilData;
|
||||||
|
public var layers:Array<GreasePencilLayer>;
|
||||||
|
|
||||||
|
public static var shaderData:ShaderData = null;
|
||||||
|
public static var structure:VertexStructure = null;
|
||||||
|
public static var usage:Usage;
|
||||||
|
public static var frameEnd = 0;
|
||||||
|
static var first = true;
|
||||||
|
|
||||||
|
public function new(raw:TGreasePencilData, done:GreasePencilData->Void) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.raw = raw;
|
||||||
|
this.name = raw.name;
|
||||||
|
|
||||||
|
if (structure == null) {
|
||||||
|
structure = new VertexStructure();
|
||||||
|
structure.add("pos", VertexData.Float3);
|
||||||
|
structure.add("col", VertexData.Float4);
|
||||||
|
usage = Usage.StaticUsage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
var shaderName:Array<String> = raw.shader.split("/");
|
||||||
|
Data.getShader(shaderName[0], shaderName[1], null, function(b:ShaderData) {
|
||||||
|
shaderData = b;
|
||||||
|
makeLayers(done);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else makeLayers(done);
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeLayers(done:GreasePencilData->Void) {
|
||||||
|
layers = [];
|
||||||
|
for (l in raw.layers) {
|
||||||
|
layers.push(new GreasePencilLayer(l));
|
||||||
|
}
|
||||||
|
done(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function parse(name:String, id:String, done:GreasePencilData->Void) {
|
||||||
|
Data.getSceneRaw(name, function(format:TSceneFormat) {
|
||||||
|
var raw:TGreasePencilData = Data.getGreasePencilRawByName(format.grease_pencil_datas, id);
|
||||||
|
if (raw == null) {
|
||||||
|
trace('Grease pencil data "$id" not found!');
|
||||||
|
done(null);
|
||||||
|
}
|
||||||
|
new GreasePencilData(raw, done);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getContext(name:String):ShaderContext {
|
||||||
|
return shaderData.getContext(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GreasePencilLayer {
|
||||||
|
public var name:String;
|
||||||
|
public var frames:Array<GreasePencilFrame>;
|
||||||
|
public var currentFrame = 0;
|
||||||
|
|
||||||
|
public function new(l:TGreasePencilLayer) {
|
||||||
|
name = l.name;
|
||||||
|
frames = [];
|
||||||
|
for (f in l.frames) {
|
||||||
|
frames.push(new GreasePencilFrame(f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GreasePencilFrame {
|
||||||
|
public var vertexBuffer:VertexBuffer;
|
||||||
|
public var vertexStrokeBuffer:VertexBuffer;
|
||||||
|
public var indexBuffer:IndexBuffer;
|
||||||
|
public var raw:TGreasePencilFrame;
|
||||||
|
public var numVertices:Int;
|
||||||
|
|
||||||
|
public function new(f:TGreasePencilFrame) {
|
||||||
|
raw = f;
|
||||||
|
var va = f.vertex_array.values;
|
||||||
|
var cola = f.col_array.values;
|
||||||
|
var colfilla = f.colfill_array.values;
|
||||||
|
var indices = f.index_array.values;
|
||||||
|
|
||||||
|
numVertices = Std.int(va.length / 3);
|
||||||
|
|
||||||
|
// Fill
|
||||||
|
vertexBuffer = new VertexBuffer(numVertices, GreasePencilData.structure, GreasePencilData.usage);
|
||||||
|
var vertices = vertexBuffer.lock();
|
||||||
|
var di = -1;
|
||||||
|
for (i in 0...numVertices) {
|
||||||
|
vertices.set(++di, va[i * 3]); // Positions
|
||||||
|
vertices.set(++di, va[i * 3 + 1]);
|
||||||
|
vertices.set(++di, va[i * 3 + 2]);
|
||||||
|
vertices.set(++di, colfilla[i * 4]); // Fill color
|
||||||
|
vertices.set(++di, colfilla[i * 4 + 1]);
|
||||||
|
vertices.set(++di, colfilla[i * 4 + 2]);
|
||||||
|
vertices.set(++di, colfilla[i * 4 + 3]);
|
||||||
|
}
|
||||||
|
vertexBuffer.unlock();
|
||||||
|
|
||||||
|
indexBuffer = new IndexBuffer(indices.length, GreasePencilData.usage);
|
||||||
|
var indicesA = indexBuffer.lock();
|
||||||
|
for (i in 0...indicesA.length) indicesA[i] = indices[i];
|
||||||
|
indexBuffer.unlock();
|
||||||
|
|
||||||
|
// Stroke
|
||||||
|
vertexStrokeBuffer = new VertexBuffer(numVertices, GreasePencilData.structure, GreasePencilData.usage);
|
||||||
|
vertices = vertexStrokeBuffer.lock();
|
||||||
|
di = -1;
|
||||||
|
for (i in 0...numVertices) {
|
||||||
|
vertices.set(++di, va[i * 3]); // Positions
|
||||||
|
vertices.set(++di, va[i * 3 + 1]);
|
||||||
|
vertices.set(++di, va[i * 3 + 2]);
|
||||||
|
vertices.set(++di, cola[i * 4]); // Stroke color
|
||||||
|
vertices.set(++di, cola[i * 4 + 1]);
|
||||||
|
vertices.set(++di, cola[i * 4 + 2]);
|
||||||
|
vertices.set(++di, cola[i * 4 + 3]);
|
||||||
|
}
|
||||||
|
vertexStrokeBuffer.unlock();
|
||||||
|
|
||||||
|
// Store max frame number of all layers
|
||||||
|
if (GreasePencilData.frameEnd < raw.frame_number) {
|
||||||
|
GreasePencilData.frameEnd = raw.frame_number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete() {
|
||||||
|
vertexBuffer.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef TGreasePencilFormat = {
|
||||||
|
@:optional var grease_pencil_datas:Array<TGreasePencilData>;
|
||||||
|
@:optional var grease_pencil_ref:String;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef TGreasePencilData = {
|
||||||
|
var name:String;
|
||||||
|
var layers:Array<TGreasePencilLayer>;
|
||||||
|
var shader:String;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef TGreasePencilLayer = {
|
||||||
|
var name:String;
|
||||||
|
var opacity:Float;
|
||||||
|
var frames:Array<TGreasePencilFrame>;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef TGreasePencilFrame = {
|
||||||
|
var frame_number:Int;
|
||||||
|
var vertex_array:TVertexArray;
|
||||||
|
var col_array:TVertexArray;
|
||||||
|
var colfill_array:TVertexArray;
|
||||||
|
var index_array:TIndexArray;
|
||||||
|
var num_stroke_points:Uint32Array;
|
||||||
|
}
|
55
Sources/armory/object/GreasePencilObject.hx
Normal file
55
Sources/armory/object/GreasePencilObject.hx
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
package armory.object;
|
||||||
|
|
||||||
|
class GreasePencilObject {
|
||||||
|
|
||||||
|
static var gpFrame = 0;
|
||||||
|
|
||||||
|
public function drawGreasePencil(params:Array<String>, root:Object) {
|
||||||
|
var gp = Scene.active.greasePencil;
|
||||||
|
if (gp == null) return;
|
||||||
|
|
||||||
|
var g = currentRenderTarget;
|
||||||
|
var lamp = getLamp(currentLampIndex);
|
||||||
|
var context = GreasePencilData.getContext(params[0]);
|
||||||
|
g.setPipeline(context.pipeState);
|
||||||
|
Uniforms.setConstants(g, context, null, camera, lamp, null);
|
||||||
|
|
||||||
|
// Draw layers
|
||||||
|
for (layer in gp.layers) {
|
||||||
|
// Next frame
|
||||||
|
if (layer.frames.length - 1 > layer.currentFrame && gpFrame >= layer.frames[layer.currentFrame + 1].raw.frame_number) {
|
||||||
|
layer.currentFrame++;
|
||||||
|
}
|
||||||
|
var frame = layer.frames[layer.currentFrame];
|
||||||
|
if (frame.numVertices > 0) {
|
||||||
|
|
||||||
|
// Stroke
|
||||||
|
#if (js && kha_webgl)
|
||||||
|
// TODO: Construct triangulated lines from points instead
|
||||||
|
g.setVertexBuffer(frame.vertexStrokeBuffer);
|
||||||
|
kha.SystemImpl.gl.lineWidth(3);
|
||||||
|
var start = 0;
|
||||||
|
for (i in frame.raw.num_stroke_points) {
|
||||||
|
kha.SystemImpl.gl.drawArrays(js.html.webgl.GL.LINE_STRIP, start, i);
|
||||||
|
start += i;
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
|
||||||
|
// Fill
|
||||||
|
g.setVertexBuffer(frame.vertexBuffer);
|
||||||
|
g.setIndexBuffer(frame.indexBuffer);
|
||||||
|
g.drawIndexedVertices();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gpFrame++;
|
||||||
|
|
||||||
|
// Reset timeline
|
||||||
|
if (gpFrame > GreasePencilData.frameEnd) {
|
||||||
|
gpFrame = 0;
|
||||||
|
for (layer in gp.layers) layer.currentFrame = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
end(g);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1062,7 +1062,7 @@ class ArmoryExporter:
|
||||||
cdata[i3 ] = col[0]
|
cdata[i3 ] = col[0]
|
||||||
cdata[i3 + 1] = col[1]
|
cdata[i3 + 1] = col[1]
|
||||||
cdata[i3 + 2] = col[2]
|
cdata[i3 + 2] = col[2]
|
||||||
|
|
||||||
mats = exportMesh.materials
|
mats = exportMesh.materials
|
||||||
poly_map = []
|
poly_map = []
|
||||||
for i in range(max(len(mats), 1)):
|
for i in range(max(len(mats), 1)):
|
||||||
|
@ -1071,14 +1071,14 @@ class ArmoryExporter:
|
||||||
poly_map[poly.material_index].append(poly)
|
poly_map[poly.material_index].append(poly)
|
||||||
|
|
||||||
o['index_arrays'] = []
|
o['index_arrays'] = []
|
||||||
|
|
||||||
# map polygon indices to triangle loops
|
# map polygon indices to triangle loops
|
||||||
tri_loops = {}
|
tri_loops = {}
|
||||||
for loop in exportMesh.loop_triangles:
|
for loop in exportMesh.loop_triangles:
|
||||||
if loop.polygon_index not in tri_loops:
|
if loop.polygon_index not in tri_loops:
|
||||||
tri_loops[loop.polygon_index] = []
|
tri_loops[loop.polygon_index] = []
|
||||||
tri_loops[loop.polygon_index].append(loop)
|
tri_loops[loop.polygon_index].append(loop)
|
||||||
|
|
||||||
for index, polys in enumerate(poly_map):
|
for index, polys in enumerate(poly_map):
|
||||||
tris = 0
|
tris = 0
|
||||||
for poly in polys:
|
for poly in polys:
|
||||||
|
@ -1736,6 +1736,17 @@ class ArmoryExporter:
|
||||||
self.post_export_world(w, o)
|
self.post_export_world(w, o)
|
||||||
self.output['world_datas'].append(o)
|
self.output['world_datas'].append(o)
|
||||||
|
|
||||||
|
def export_grease_pencils(self):
|
||||||
|
for gpRef in bpy.data.grease_pencils:
|
||||||
|
fp = self.get_meshes_file_path('greasepencil_' + gpRef.name)
|
||||||
|
assets.add(fp)
|
||||||
|
self.output['grease_pencil_ref'] = 'greasepencil_' + gpRef.name + '/' + gpRef.name
|
||||||
|
assets.add_shader_pass('grease_pencil')
|
||||||
|
gpo = self.post_export_grease_pencil(gpRef)
|
||||||
|
gp_obj = {}
|
||||||
|
gp_obj['grease_pencil_datas'] = [gpo]
|
||||||
|
arm.utils.write_arm(fp, gp_obj)
|
||||||
|
|
||||||
def is_compress(self):
|
def is_compress(self):
|
||||||
return ArmoryExporter.compress_enabled
|
return ArmoryExporter.compress_enabled
|
||||||
|
|
||||||
|
@ -1971,6 +1982,7 @@ class ArmoryExporter:
|
||||||
self.export_particle_systems()
|
self.export_particle_systems()
|
||||||
self.output['world_datas'] = []
|
self.output['world_datas'] = []
|
||||||
self.export_worlds()
|
self.export_worlds()
|
||||||
|
self.export_grease_pencils()
|
||||||
self.export_tilesheets()
|
self.export_tilesheets()
|
||||||
|
|
||||||
if self.scene.world is not None:
|
if self.scene.world is not None:
|
||||||
|
@ -2246,7 +2258,7 @@ class ArmoryExporter:
|
||||||
col_mask = ''
|
col_mask = ''
|
||||||
for b in bobject.arm_rb_collision_filter_mask:
|
for b in bobject.arm_rb_collision_filter_mask:
|
||||||
col_mask = ('1' if b else '0') + col_mask
|
col_mask = ('1' if b else '0') + col_mask
|
||||||
|
|
||||||
x['parameters'] = [str(shape), str(body_mass), str(rb.friction), str(rb.restitution), str(int(col_group, 2)), str(int(col_mask, 2)) ]
|
x['parameters'] = [str(shape), str(body_mass), str(rb.friction), str(rb.restitution), str(int(col_group, 2)), str(int(col_mask, 2)) ]
|
||||||
lx = bobject.arm_rb_linear_factor[0]
|
lx = bobject.arm_rb_linear_factor[0]
|
||||||
ly = bobject.arm_rb_linear_factor[1]
|
ly = bobject.arm_rb_linear_factor[1]
|
||||||
|
@ -2423,7 +2435,7 @@ class ArmoryExporter:
|
||||||
|
|
||||||
bobject_eval = bobject.evaluated_get(self.depsgraph) if apply_modifiers else bobject
|
bobject_eval = bobject.evaluated_get(self.depsgraph) if apply_modifiers else bobject
|
||||||
exportMesh = bobject_eval.to_mesh()
|
exportMesh = bobject_eval.to_mesh()
|
||||||
|
|
||||||
with open(nav_filepath, 'w') as f:
|
with open(nav_filepath, 'w') as f:
|
||||||
for v in exportMesh.vertices:
|
for v in exportMesh.vertices:
|
||||||
f.write("v %.4f " % (v.co[0] * bobject_eval.scale.x))
|
f.write("v %.4f " % (v.co[0] * bobject_eval.scale.x))
|
||||||
|
@ -2585,6 +2597,85 @@ class ArmoryExporter:
|
||||||
po['strength'] = strength
|
po['strength'] = strength
|
||||||
o['probe'] = po
|
o['probe'] = po
|
||||||
|
|
||||||
|
def post_export_grease_pencil(self, gp):
|
||||||
|
o = {}
|
||||||
|
o['name'] = gp.name
|
||||||
|
o['layers'] = []
|
||||||
|
for layer in gp.layers:
|
||||||
|
o['layers'].append(self.export_grease_pencil_layer(layer))
|
||||||
|
o['shader'] = 'grease_pencil/grease_pencil'
|
||||||
|
return o
|
||||||
|
|
||||||
|
def export_grease_pencil_layer(self, layer):
|
||||||
|
lo = {}
|
||||||
|
lo['name'] = layer.info
|
||||||
|
lo['opacity'] = layer.opacity
|
||||||
|
lo['frames'] = []
|
||||||
|
for frame in layer.frames:
|
||||||
|
if frame.frame_number > self.scene.frame_end:
|
||||||
|
break
|
||||||
|
lo['frames'].append(self.export_grease_pencil_frame(frame))
|
||||||
|
return lo
|
||||||
|
|
||||||
|
def export_grease_pencil_frame(self, frame):
|
||||||
|
va = []
|
||||||
|
cola = []
|
||||||
|
colfilla = []
|
||||||
|
indices = []
|
||||||
|
num_stroke_points = []
|
||||||
|
index_offset = 0
|
||||||
|
for stroke in frame.strokes:
|
||||||
|
for point in stroke.points:
|
||||||
|
va.append(point.co[0])
|
||||||
|
va.append(point.co[1])
|
||||||
|
va.append(point.co[2])
|
||||||
|
# TODO: store index to color pallete only, this is wasteful
|
||||||
|
if stroke.color != None:
|
||||||
|
cola.append(stroke.color.color[0])
|
||||||
|
cola.append(stroke.color.color[1])
|
||||||
|
cola.append(stroke.color.color[2])
|
||||||
|
cola.append(stroke.color.alpha)
|
||||||
|
colfilla.append(stroke.color.fill_color[0])
|
||||||
|
colfilla.append(stroke.color.fill_color[1])
|
||||||
|
colfilla.append(stroke.color.fill_color[2])
|
||||||
|
colfilla.append(stroke.color.fill_alpha)
|
||||||
|
else:
|
||||||
|
cola.append(0.0)
|
||||||
|
cola.append(0.0)
|
||||||
|
cola.append(0.0)
|
||||||
|
cola.append(0.0)
|
||||||
|
colfilla.append(0.0)
|
||||||
|
colfilla.append(0.0)
|
||||||
|
colfilla.append(0.0)
|
||||||
|
colfilla.append(0.0)
|
||||||
|
for triangle in stroke.triangles:
|
||||||
|
indices.append(triangle.v1 + index_offset)
|
||||||
|
indices.append(triangle.v2 + index_offset)
|
||||||
|
indices.append(triangle.v3 + index_offset)
|
||||||
|
num_stroke_points.append(len(stroke.points))
|
||||||
|
index_offset += len(stroke.points)
|
||||||
|
fo = {}
|
||||||
|
# TODO: merge into array of vertex arrays
|
||||||
|
fo['vertex_array'] = {}
|
||||||
|
fo['vertex_array']['attrib'] = 'pos'
|
||||||
|
fo['vertex_array']['size'] = 3
|
||||||
|
fo['vertex_array']['values'] = va
|
||||||
|
fo['col_array'] = {}
|
||||||
|
fo['col_array']['attrib'] = 'col'
|
||||||
|
fo['col_array']['size'] = 4
|
||||||
|
fo['col_array']['values'] = cola
|
||||||
|
fo['colfill_array'] = {}
|
||||||
|
fo['colfill_array']['attrib'] = 'colfill'
|
||||||
|
fo['colfill_array']['size'] = 4
|
||||||
|
fo['colfill_array']['values'] = colfilla
|
||||||
|
fo['index_array'] = {}
|
||||||
|
fo['index_array']['material'] = 0
|
||||||
|
fo['index_array']['size'] = 3
|
||||||
|
fo['index_array']['values'] = indices
|
||||||
|
fo['num_stroke_points'] = num_stroke_points
|
||||||
|
fo['frame_number'] = frame.frame_number
|
||||||
|
return fo
|
||||||
|
|
||||||
# https://blender.stackexchange.com/questions/70629
|
# https://blender.stackexchange.com/questions/70629
|
||||||
def mod_equal(self, mod1, mod2):
|
def mod_equal(self, mod1, mod2):
|
||||||
return all([getattr(mod1, prop, True) == getattr(mod2, prop, False) for prop in mod1.bl_rna.properties.keys()])
|
return all([getattr(mod1, prop, True) == getattr(mod2, prop, False) for prop in mod1.bl_rna.properties.keys()])
|
||||||
|
|
Loading…
Reference in a new issue