# HG changeset patch # User Sam # Date 1700670220 -25200 # Node ID 902735626b6698dc59605c050a6433f89c2bf73f # Parent e314407ea9db78472074977edc660a1232e489c2 add: missing material module, some functions for noise diff -r e314407ea9db -r 902735626b66 src/semicongine/material.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/semicongine/material.nim Wed Nov 22 23:23:40 2023 +0700 @@ -0,0 +1,113 @@ +import std/tables +import std/strformat +import std/strutils +import std/hashes + + +import ./core + +type + MaterialType* = object + name*: string + meshAttributes*: Table[string, DataType] + attributes*: Table[string, DataType] + MaterialData* = object + theType*: MaterialType + name*: string + attributes*: Table[string, DataList] + +proc hash*(materialType: MaterialType): Hash = + return hash(materialType.name) + +proc hash*(materialData: MaterialData): Hash = + return hash(materialData.name) + +proc `==`*(a, b: MaterialType): bool = + return a.name == b.name + +proc `==`*(a, b: MaterialData): bool = + return a.name == b.name + +let EMPTY_MATERIAL* = MaterialType( + name: "empty material", + meshAttributes: {"position": Vec3F32}.toTable, +) +let COLORED_MATERIAL* = MaterialType( + name: "single color material", + meshAttributes: {"position": Vec3F32}.toTable, + attributes: {"color": Vec4F32}.toTable, +) +let VERTEX_COLORED_MATERIAL* = MaterialType( + name: "vertex color material", + meshAttributes: { + "position": Vec3F32, + "color": Vec4F32, + }.toTable, +) +let SINGLE_COLOR_MATERIAL* = MaterialType( + name: "single color material", + meshAttributes: { + "position": Vec3F32, + }.toTable, + attributes: {"color": Vec4F32}.toTable +) +let SINGLE_TEXTURE_MATERIAL* = MaterialType( + name: "single texture material", + meshAttributes: { + "position": Vec3F32, + "uv": Vec2F32, + }.toTable, + attributes: {"baseTexture": TextureType}.toTable +) +let COLORED_SINGLE_TEXTURE_MATERIAL* = MaterialType( + name: "colored single texture material", + meshAttributes: { + "position": Vec3F32, + "uv": Vec2F32, + }.toTable, + attributes: {"baseTexture": TextureType, "color": Vec4F32}.toTable +) + +proc `$`*(materialType: MaterialType): string = + var attributes: seq[string] + for key, value in materialType.attributes.pairs: + attributes.add &"{key}: {value}" + return &"""MaterialType '{materialType.name}' | Attributes: {attributes.join(", ")}""" + +proc `$`*(material: MaterialData): string = + var attributes: seq[string] + for key, value in material.attributes.pairs: + attributes.add &"{key}: {value}" + return &"""Material '{material.name}' | Attributes: {attributes.join(", ")}""" + +proc initMaterialData*( + materialType: MaterialType, + name: string, + attributes: Table[string, DataList], +): MaterialData = + var theName = name + if theName == "": + theName = &"material instance of '{materialType}'" + for matName, theType in materialType.attributes.pairs: + assert attributes.contains(matName), &"missing material attribute '{matName}' for {materialType}" + assert attributes[matName].theType == theType + MaterialData( + theType: materialType, + name: theName, + attributes: attributes, + ) + +proc initMaterialData*( + materialType: MaterialType, + name: string = "", + attributes: seq[(string, DataList)] = @[], +): MaterialData = + var theName = name + if theName == "": + theName = &"material instance of '{materialType}'" + initMaterialData(materialType=materialType, name=theName, attributes=attributes.toTable) + +let DEFAULT_MATERIAL* = MaterialData( + name: "default material" +) + diff -r e314407ea9db -r 902735626b66 src/semicongine/noise.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/semicongine/noise.nim Wed Nov 22 23:23:40 2023 +0700 @@ -0,0 +1,34 @@ +import hashes +import math + +import ./core/vector + + +proc randomGradient(pos: Vec2f, seed: int32 = 0): Vec2f = + let randomAngle: float32 = TAU * (float32(int(hash((pos.x, pos.y, seed)))) / float32(high(int))) + return newVec2f(cos(randomAngle), sin(randomAngle)) + +proc interpolate(a: float32, b: float32, weight: float32): float32 = + # with Smootherstep + (b - a) * ((weight * (weight * 6.0 - 15.0) + 10.0) * weight * weight * weight) + a; + +proc perlin*(pos: Vec2f, seed: int32 = 0): float32 = + let + # grid coordinates around target point + topleft = newVec2f(trunc(pos.x), trunc(pos.y)) + topright = topleft + newVec2f(1, 0) + bottomleft = topleft + newVec2f(0, 1) + bottomright = topleft + newVec2f(1, 1) + # products for weights + topleft_dot = topleft.randomGradient(seed).dot((pos - topleft)) + topright_dot = topright.randomGradient(seed).dot((pos - topright)) + bottomleft_dot = bottomleft.randomGradient(seed).dot((pos - bottomleft)) + bottomright_dot = bottomright.randomGradient(seed).dot((pos - bottomright)) + xinterpol = pos.x - topleft.x + yinterpol = pos.y - topleft.y + + return interpolate( + interpolate(topleft_dot, bottomleft_dot, yinterpol), + interpolate(topright_dot, bottomright_dot, yinterpol), + xinterpol + ) diff -r e314407ea9db -r 902735626b66 tests/test_noise.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test_noise.nim Wed Nov 22 23:23:40 2023 +0700 @@ -0,0 +1,17 @@ +import semicongine + +const w = 500 +const h = 500 + +var o = "P2\n" & $ w & " " & $ h & "\n255\n" + +for y in 0 ..< h: + for x in 0 ..< w: + let v = ( + perlin(newVec2f(float(x) * 0.01, float(y) * 0.01)) * 0.7 + + perlin(newVec2f(float(x) * 0.05, float(y) * 0.05)) * 0.25 + + perlin(newVec2f(float(x) * 0.2, float(y) * 0.2)) * 0.05 + ) + o = o & $(int((v * 0.5 + 0.5) * 255)) & " " + o = o & "\n" +echo o