Browse Source

Add Funky Blending layer support

pull/250/merge^2
Darryl Pogue 4 years ago
parent
commit
78d1c1f05a
No known key found for this signature in database
GPG Key ID: CB824715C3E6FD41
  1. 44
      korlib/bumpmap.cpp
  2. 1
      korlib/bumpmap.h
  3. 1
      korlib/module.cpp
  4. 92
      korman/exporter/material.py
  5. 24
      korman/korlib/__init__.py
  6. 21
      korman/properties/prop_texture.py
  7. 22
      korman/ui/ui_texture.py

44
korlib/bumpmap.cpp

@ -26,6 +26,50 @@ static uint32_t MakeUInt32Color(float r, float g, float b, float a) {
(uint32_t(b * 255.9f) << 0);
}
PyObject* create_funky_ramp(PyObject*, PyObject* args) {
static const int kLUTHeight = 16;
static const int kLUTWidth = 16;
static const int kBufSz = kLUTWidth * kLUTHeight * sizeof(uint32_t);
pyMipmap* pymipmap;
int additive = 0;
if (!PyArg_ParseTuple(args, "O|i", &pymipmap, &additive)) {
PyErr_SetString(PyExc_TypeError, "create_funky_ramp expects a plMipmap and an optional boolean");
return NULL;
}
plMipmap* texture = plMipmap::Convert(pymipmap->fThis, false);
if (!texture) {
PyErr_SetString(PyExc_TypeError, "create_funky_ramp expects a plMipmap");
return NULL;
}
texture->Create(kLUTWidth, kLUTHeight, 1, plBitmap::kUncompressed, plBitmap::kRGB8888);
uint8_t data[kBufSz];
uint32_t* pix = (uint32_t*)data;
for (int i = 0; i < kLUTHeight; ++i) {
for (int j = 0; j < kLUTWidth; ++j) {
float x = float(j) / (kLUTWidth - 1);
float y = float(i) / (kLUTHeight - 1);
if (additive) {
if (x < y)
x = y;
*pix++ = MakeUInt32Color(1.0f, 1.0f, 1.0f, x);
} else {
*pix++ = MakeUInt32Color(1.0f, 1.0f, 1.0f, x*y);
}
}
}
texture->setImageData(data, kBufSz);
Py_RETURN_NONE;
}
PyObject* create_bump_LUT(PyObject*, PyObject* args) {
static const int kLUTHeight = 16;
static const int kLUTWidth = 16;

1
korlib/bumpmap.h

@ -19,6 +19,7 @@
#include "korlib.h"
PyObject* create_funky_ramp(PyObject*, PyObject* args);
PyObject* create_bump_LUT(PyObject*, PyObject* args);
#endif // _KORLIB_BUMPMAP_H

1
korlib/module.cpp

@ -22,6 +22,7 @@
#define KORLIB_API_VERSION 2
static PyMethodDef korlib_Methods[] = {
{ _pycs("create_funky_ramp"), (PyCFunction)create_funky_ramp, METH_VARARGS, NULL },
{ _pycs("create_bump_LUT"), (PyCFunction)create_bump_LUT, METH_VARARGS, NULL },
{ _pycs("inspect_vorbisfile"), (PyCFunction)inspect_vorbisfile, METH_VARARGS, NULL },
{ _pycs("scale_image"), (PyCFunction)scale_image, METH_KEYWORDS | METH_VARARGS, NULL },

92
korman/exporter/material.py

@ -253,6 +253,11 @@ class MaterialConverter:
if i+1 < curr_stencils:
stencil_layer.state.miscFlags |= hsGMatState.kMiscBindNext
hsgmat.addLayer(stencil_layer.key)
if slot.texture.plasma_layer.funky_type != "FunkyNone":
funky_ramp = self.export_funky_slot(bo, bm, hsgmat, slot, idx)
if funky_ramp:
tex_layer.state.miscFlags |= hsGMatState.kMiscBindNext
hsgmat.addLayer(funky_ramp.key)
# Plasma makes several assumptions that every hsGMaterial has at least one layer. If this
# material had no Textures, we will need to initialize a default layer
@ -357,6 +362,93 @@ class MaterialConverter:
# Wasn't that easy?
return hsgmat.key
def export_funky_slot(self, bo, bm, hsgmat, slot, idx):
name = "{}_{}_funkRamp".format(hsgmat.key.name, slot.name)
self._report.msg("Exporting Plasma Funky Ramp Layer '{}'", name, indent=2)
texture = slot.texture
layer_props = texture.plasma_layer
funky_type = layer_props.funky_type
tr0 = layer_props.funky_near_trans
op0 = layer_props.funky_near_opaq
tr1 = layer_props.funky_far_trans
op1 = layer_props.funky_far_opaq
if funky_type != "FunkyDist":
tr0 = max(min(tr0, 180.0), 0.0)
op0 = max(min(op0, 180.0), 0.0)
tr1 = max(min(tr1, 180.0), 0.0)
op1 = max(min(op1, 180.0), 0.0)
if tr0 > tr1:
tr0, tr1 = tr1, tr0
op0, op1 = op1, op0
if tr0 == op0 or op1 == tr1:
return None
additive = tr0 > op0 and op1 > tr1
if funky_type != "FunkyDist":
tr0 = math.cos(tr0 * (math.pi / 180.0))
op0 = math.cos(op0 * (math.pi / 180.0))
op1 = math.cos(op1 * (math.pi / 180.0))
tr1 = math.cos(tr1 * (math.pi / 180.0))
uvwXfm = hsMatrix44()
uvwXfm[0,0] = uvwXfm[1,1] = uvwXfm[2,2] = 0.0
if op0 != tr0:
uvwXfm[0,2] = -1.0 / (tr0 - op0)
uvwXfm[0,3] = uvwXfm[0,2] * -tr0
else:
uvwXfm[0,3] = 1.0
if op1 != tr1:
uvwXfm[1,2] = -1.0 / (tr1 - op1)
uvwXfm[1,3] = uvwXfm[1,2] * -tr1
else:
uvwXfm[1,3] = 1.0
ramp_layer = self._mgr.find_create_object(plLayer, name=name, bl=bo)
rampName = "FunkyRampAdd" if additive else "FunkyRampMult"
page = self._mgr.get_textures_page(ramp_layer.key)
ramp_key = self._mgr.find_key(plMipmap, loc=page, name=rampName)
if ramp_key is None:
funkRamp = plMipmap(rampName, 16, 16, 1, plBitmap.kUncompressed, plBitmap.kRGB8888)
create_funky_ramp(funkRamp, additive)
self._mgr.AddObject(page, funkRamp)
ramp_key = funkRamp.key
ramp_layer.texture = ramp_key
ramp_layer.ambient = hsColorRGBA(1.0, 1.0, 1.0, 1.0)
ramp_layer.preshade = hsColorRGBA(0.0, 0.0, 0.0, 1.0)
ramp_layer.runtime = hsColorRGBA(0.0, 0.0, 0.0, 1.0)
ramp_layer.specular = hsColorRGBA(0.0, 0.0, 0.0, 1.0)
ramp_layer.state.ZFlags = hsGMatState.kZNoZWrite
ramp_layer.state.clampFlags = hsGMatState.kClampTexture
ramp_layer.state.blendFlags = hsGMatState.kBlendAlpha | hsGMatState.kBlendNoTexColor | hsGMatState.kBlendAlphaMult
ramp_layer.transform = uvwXfm
if funky_type == "FunkyDist":
ramp_layer.UVWSrc = plLayerInterface.kUVWPosition
ramp_layer.state.miscFlags |= hsGMatState.kMiscNoShadowAlpha
elif funky_type == "FunkyNormal":
ramp_layer.UVWSrc = plLayerInterface.kUVWNormal
elif funky_type == "FunkyUp":
ramp_layer.UVWSrc = plLayerInterface.kUVWNormal
ramp_layer.state.miscFlags |= hsGMatState.kMiscOrthoProjection
elif funky_type == "FunkyReflect":
ramp_layer.UVWSrc = plLayerInterface.kUVWReflect
return ramp_layer
def export_bumpmap_slot(self, bo, bm, hsgmat, slot, idx):
name = "{}_{}".format(hsgmat.key.name, slot.name)
self._report.msg("Exporting Plasma Bumpmap Layers for '{}'", name, indent=2)

24
korman/korlib/__init__.py

@ -29,6 +29,30 @@ except ImportError as ex:
msg = "Korlib C Module did not load correctly."
print(msg, "Using PyKorlib :(", sep=' ')
def create_funky_ramp(mipmap, additive=False):
kLUTHeight = 16
kLUTWidth = 16
buf = bytearray(kLUTHeight * kLUTWidth * 4)
for i in range(kLUTHeight):
for j in range(kLUTWidth):
x = j / (kLUTWidth - 1);
y = i / (kLUTHeight - 1);
start = i*j*4
end = start + 4
if additive:
if x < y:
x = y
buf[start:end] = [b for b in (255, 255, 255, int(x * 255.9))]
else:
buf[start:end] = [b for b in (255, 255, 255, int((x * y) * 255.9))]
mipmap.setRawImage(bytes(buf))
def create_bump_LUT(mipmap):
kLUTHeight = 16
kLUTWidth = 16

21
korman/properties/prop_texture.py

@ -99,3 +99,24 @@ class PlasmaLayer(bpy.types.PropertyGroup):
description="Don't save the depth information, allowing rendering of layers behind this one",
default=False,
options=set())
funky_type = EnumProperty(name="Funky Blending Type",
description="Type of special funky layer blending",
items=[("FunkyNone", "None", "No funky layer blending"),
("FunkyDist", "Distance", "Distance-based funky layer blending"),
("FunkyNormal", "Normal", "Normal angle-based funky layer blending"),
("FunkyReflect", "Reflect", "Reflection angle-based funky layer blending"),
("FunkyUp", "Up", "Upwards angle-based funky layer blending")],
default="FunkyNone")
funky_near_trans = FloatProperty(name="Near Transparent",
description="Nearest distance at which the layer is fully transparent",
min=0.0, default=0.0, subtype="DISTANCE", unit="LENGTH")
funky_near_opaq = FloatProperty(name="Near Opaque",
description="Nearest distance at which the layer is fully opaque",
min=0.0, default=0.0, subtype="DISTANCE", unit="LENGTH")
funky_far_opaq = FloatProperty(name="Far Opaque",
description="Farthest distance at which the layer is fully opaque",
min=0.0, default=15.0, subtype="DISTANCE", unit="LENGTH")
funky_far_trans = FloatProperty(name="Far Transparent",
description="Farthest distance at which the layer is fully transparent",
min=0.0, default=20.0, subtype="DISTANCE", unit="LENGTH")

22
korman/ui/ui_texture.py

@ -119,3 +119,25 @@ class PlasmaLayerPanel(TextureButtonsPanel, bpy.types.Panel):
return True
return False
class PlasmaFunkyLayerPanel(TextureButtonsPanel, bpy.types.Panel):
bl_label = "Plasma Funky Layer"
def draw(self, context):
texture, slot = context.texture, getattr(context, "texture_slot", None)
use_stencil = slot.use_stencil if slot is not None else False
layer_props = texture.plasma_layer
layout = self.layout
layout.prop(layer_props, "funky_type")
if layer_props.funky_type != "FunkyNone":
col = layout.column(align=True)
col.prop(layer_props, "funky_near_trans")
col.prop(layer_props, "funky_near_opaq")
col.prop(layer_props, "funky_far_opaq")
col.prop(layer_props, "funky_far_trans")
if layer_props.funky_type != "FunkyDist":
# Mention that values are angles
layout.label("Values should be viewing angles in degrees between 0 and 180.", icon="RESTRICT_VIEW_OFF")

Loading…
Cancel
Save