Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/polyform/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import (
_ "github.com/EliCDavis/polyform/modeling/voxelize"

_ "github.com/EliCDavis/polyform/nodes/experimental"
_ "github.com/EliCDavis/polyform/nodes/opearations"
)

func main() {
Expand Down
6 changes: 6 additions & 0 deletions drawing/texturing/pattern/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,11 @@ func init() {
refutil.RegisterType[nodes.Struct[CircleNode[bool]]](factory)
refutil.RegisterType[nodes.Struct[CircleNode[coloring.Color]]](factory)

refutil.RegisterType[nodes.Struct[RectanglesNode[float64]]](factory)
refutil.RegisterType[nodes.Struct[RectanglesNode[vector2.Float64]]](factory)
refutil.RegisterType[nodes.Struct[RectanglesNode[vector3.Float64]]](factory)
refutil.RegisterType[nodes.Struct[RectanglesNode[bool]]](factory)
refutil.RegisterType[nodes.Struct[RectanglesNode[coloring.Color]]](factory)

generator.RegisterTypes(factory)
}
56 changes: 56 additions & 0 deletions drawing/texturing/pattern/rectangle.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package pattern

import (
"github.com/EliCDavis/polyform/drawing/texturing"
"github.com/EliCDavis/polyform/nodes"
"github.com/EliCDavis/vector/vector2"
)

type RectanglesNode[T any] struct {
Positions nodes.Output[[]vector2.Float64]
Value nodes.Output[T]
Size nodes.Output[vector2.Float64]
In nodes.Output[texturing.Texture[T]]
}

func (node RectanglesNode[T]) Out(out *nodes.StructOutput[texturing.Texture[T]]) {
if node.In == nil {
out.CaptureError(nodes.UnsetInputError{
Input: node.In,
})
return
}

inputTex := nodes.GetOutputValue(out, node.In)
imgSize := vector2.New(inputTex.Width()-1, inputTex.Height()-1).ToFloat64()
size := nodes.TryGetOutputValue(out, node.Size, vector2.New(0.5, 0.5)).Scale(0.5)

var val T
if node.Value != nil {
val = nodes.GetOutputValue(out, node.Value)
}

outputTex := inputTex.Copy()
positions := nodes.GetOutputValue(out, node.Positions)
for _, pos := range positions {
start := pos.
Sub(size).
Clamp(0, 1).
MultByVector(imgSize).
RoundToInt()

end := pos.
Add(size).
Clamp(0, 1).
MultByVector(imgSize).
RoundToInt()

for y := start.Y(); y < end.Y(); y++ {
for x := start.X(); x < end.X(); x++ {
outputTex.Set(x, y, val)
}
}
}

out.Set(outputTex)
}
10 changes: 10 additions & 0 deletions formats/gltf/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ type MaterialNode struct {
MetallicFactor nodes.Output[float64] `description:"The factor for the metalness of the material. This value defines a linear multiplier for the sampled metalness values of the metallic-roughness texture."`
RoughnessFactor nodes.Output[float64] `description:"The factor for the roughness of the material. This value defines a linear multiplier for the sampled roughness values of the metallic-roughness texture."`
MetallicRoughnessTexture nodes.Output[PolyformTexture] `description:"The metallic-roughness texture. The metalness values are sampled from the B channel. The roughness values are sampled from the G channel. These values MUST be encoded with a linear transfer function. If other channels are present (R or A), they MUST be ignored for metallic-roughness calculations. When undefined, the texture MUST be sampled as having 1.0 in G and B components."`
EmissiveTexture nodes.Output[PolyformTexture] `description:"The emissive texture. It controls the color and intensity of the light being emitted by the material. This texture contains RGB components encoded with the sRGB transfer function. If a fourth component (A) is present, it MUST be ignored. When undefined, the texture MUST be sampled as having 1.0 in RGB components."`
EmissiveFactor nodes.Output[coloring.Color] `description:"The factors for the emissive color of the material. This value defines linear multipliers for the sampled texels of the emissive texture."`
NormalTexture nodes.Output[PolyformNormal] `description:"The tangent space normal texture. The texture encodes RGB components with linear transfer function. Each texel represents the XYZ components of a normal vector in tangent space. The normal vectors use the convention +X is right and +Y is up. +Z points toward the viewer. If a fourth component (A) is present, it **MUST** be ignored. When undefined, the material does not have a tangent space normal texture."`

Expand Down Expand Up @@ -360,6 +361,14 @@ func (gmnd MaterialNode) Out(out *nodes.StructOutput[PolyformMaterial]) {
}
}

var emissiveTexture *PolyformTexture
if gmnd.EmissiveTexture != nil {
tex := nodes.GetOutputReference(out, gmnd.EmissiveTexture)
if tex.canAddToGLTF() {
emissiveTexture = tex
}
}

if gmnd.MetallicRoughnessTexture != nil {
tex := nodes.GetOutputReference(out, gmnd.MetallicRoughnessTexture)
if tex.canAddToGLTF() {
Expand Down Expand Up @@ -431,6 +440,7 @@ func (gmnd MaterialNode) Out(out *nodes.StructOutput[PolyformMaterial]) {
Extensions: extensions,
EmissiveFactor: emissiveFactor,
NormalTexture: normalTex,
EmissiveTexture: emissiveTexture,
})
}

Expand Down
5 changes: 5 additions & 0 deletions math/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,11 @@ func (cn SquareNode) Out(out *nodes.StructOutput[float64]) {
out.Set(v * v)
}

func (cn SquareNode) Int(out *nodes.StructOutput[int]) {
v := nodes.TryGetOutputValue(out, cn.In, 0)
out.Set(int(math.Round(v * v)))
}

type SquareRootNode struct {
In nodes.Output[float64]
}
Expand Down
5 changes: 5 additions & 0 deletions math/sdf/rounded_cone.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ func RoundedCone(a, b vector3.Float64, r1, r2 float64) sample.Vec3ToFloat {
// sampling independent computations (only depend on shape)
ba := b.Sub(a)
l2 := ba.Dot(ba)

if l2 == 0 {
return Sphere(a, max(r1, r2))
}

rr := r1 - r2
rrr := rr * rr
signRRR := sign(rr) * rrr
Expand Down
2 changes: 2 additions & 0 deletions math/sequence/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ func init() {
factory := &refutil.TypeFactory{}

refutil.RegisterType[nodes.Struct[LinearNode]](factory)
refutil.RegisterType[nodes.Struct[RandomFloatNode]](factory)
refutil.RegisterType[nodes.Struct[RandomBoolNode]](factory)

generator.RegisterTypes(factory)
}
50 changes: 50 additions & 0 deletions math/sequence/random.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package sequence

import (
"math/rand/v2"

"github.com/EliCDavis/polyform/nodes"
)

type RandomFloatNode struct {
Min nodes.Output[float64]
Max nodes.Output[float64]
Samples nodes.Output[int]
}

func (snd RandomFloatNode) Out(out *nodes.StructOutput[[]float64]) {
minV := nodes.TryGetOutputValue(out, snd.Min, 0.)
maxV := nodes.TryGetOutputValue(out, snd.Max, 1.)
rangeV := maxV - minV

samples := max(nodes.TryGetOutputValue(out, snd.Samples, 0), 0)

seed1 := uint64(12345)
seed2 := uint64(67890)
rnd := rand.New(rand.NewPCG(seed1, seed2))
arr := make([]float64, samples)
for i := range samples {
v := minV + (rnd.Float64() * rangeV)
arr[i] = v
}

out.Set(arr)
}

type RandomBoolNode struct {
Samples nodes.Output[int]
}

func (snd RandomBoolNode) Out(out *nodes.StructOutput[[]bool]) {
samples := max(nodes.TryGetOutputValue(out, snd.Samples, 0), 0)

seed1 := uint64(12345)
seed2 := uint64(67890)
rnd := rand.New(rand.NewPCG(seed1, seed2))
arr := make([]bool, samples)
for i := range samples {
arr[i] = rnd.Float64() > 0.5
}

out.Set(arr)
}
8 changes: 8 additions & 0 deletions math/vector2/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,13 @@ func init() {
refutil.RegisterType[nodes.Struct[SelectArray[int]]](factory)
refutil.RegisterType[nodes.Struct[SelectArray[float64]]](factory)

refutil.RegisterType[nodes.Struct[Subtract[int]]](factory)
refutil.RegisterType[nodes.Struct[Subtract[float64]]](factory)
refutil.RegisterType[nodes.Struct[SubtractToArrayNode[int]]](factory)
refutil.RegisterType[nodes.Struct[SubtractToArrayNode[float64]]](factory)

refutil.RegisterType[nodes.Struct[Scale[int]]](factory)
refutil.RegisterType[nodes.Struct[Scale[float64]]](factory)

generator.RegisterTypes(factory)
}
22 changes: 22 additions & 0 deletions math/vector2/scale.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package vector2

import (
"github.com/EliCDavis/polyform/nodes"
"github.com/EliCDavis/vector"
"github.com/EliCDavis/vector/vector2"
)

type Scale[T vector.Number] struct {
Vector nodes.Output[vector2.Vector[T]] `description:"The vector to scale"`
Amount nodes.Output[float64] `description:"The amount the scale by (defaults to 1.0)"`
}

func (cn Scale[T]) Float64(out *nodes.StructOutput[vector2.Float64]) {
vec := nodes.TryGetOutputValue(out, cn.Vector, vector2.Zero[T]())
out.Set(vec.ToFloat64().Scale(nodes.TryGetOutputValue(out, cn.Amount, 1)))
}

func (cn Scale[T]) Int(out *nodes.StructOutput[vector2.Int]) {
vec := nodes.TryGetOutputValue(out, cn.Vector, vector2.Zero[T]())
out.Set(vec.ToFloat64().Scale(nodes.TryGetOutputValue(out, cn.Amount, 1)).RoundToInt())
}
42 changes: 42 additions & 0 deletions math/vector2/sub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package vector2

import (
"github.com/EliCDavis/polyform/nodes"
"github.com/EliCDavis/vector"
"github.com/EliCDavis/vector/vector2"
)

type Subtract[T vector.Number] struct {
A nodes.Output[vector2.Vector[T]]
B nodes.Output[vector2.Vector[T]]
}

func (d Subtract[T]) Out(out *nodes.StructOutput[vector2.Vector[T]]) {
a := nodes.TryGetOutputValue(out, d.A, vector2.Zero[T]())
b := nodes.TryGetOutputValue(out, d.B, vector2.Zero[T]())
out.Set(a.Sub(b))
}

type SubtractToArrayNode[T vector.Number] struct {
Amount nodes.Output[vector2.Vector[T]]
Array nodes.Output[[]vector2.Vector[T]]
}

func (cn SubtractToArrayNode[T]) Out(out *nodes.StructOutput[[]vector2.Vector[T]]) {
if cn.Array == nil {
return
}

original := nodes.GetOutputValue(out, cn.Array)
if cn.Amount == nil {
out.Set(original)
return
}

amount := nodes.GetOutputValue(out, cn.Amount)
total := make([]vector2.Vector[T], len(original))
for i, v := range original {
total[i] = v.Sub(amount)
}
out.Set(total)
}
2 changes: 1 addition & 1 deletion modeling/marching/march.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ func marchRecurse(field sample.Vec3ToFloat, bounds geometry.AABB, cubeSize, surf

// TODO: WE THIS IS OUR BIGGEST SPEEDUP, FIGURE OUT HOW TO PRUNE HARDER
// The closest surface is not within the bounds
if math.Abs(fieldResult) > (diagonal/2)+(cubeSize)+center.Distance(recentered) {
if math.Abs(fieldResult) > (diagonal*2)+(cubeSize)+center.Distance(recentered) {
return
}

Expand Down
6 changes: 5 additions & 1 deletion modeling/primitives/circle.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,12 @@ func (c Circle) ToMesh() modeling.Mesh {
uvs := make([]vector2.Float64, c.Sides+1)
for sideIndex := 0; sideIndex < c.Sides; sideIndex++ {
angle := angleIncrement * float64(sideIndex)
uvs[sideIndex] = vector2.New(math.Cos(angle), math.Sin(angle)).Normalized().Scale(c.UVs.Radius)
uvs[sideIndex] = vector2.New(math.Cos(angle), math.Sin(angle)).
Normalized().
Scale(c.UVs.Radius).
Add(c.UVs.Center)
}
uvs[topMiddleVert] = c.UVs.Center
meshV2Data[modeling.TexCoordAttribute] = uvs
}

Expand Down
37 changes: 28 additions & 9 deletions modeling/primitives/cube.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func (c Cube) UnweldedQuads() modeling.Mesh {
halfW := c.Width / 2
halfH := c.Height / 2
halfD := c.Depth / 2
var topUV, bottomUV, leftUV, rightUV, frontUV, backUV EuclideanUVSpace
var topUV, bottomUV, leftUV, rightUV, frontUV, backUV EuclideanUVSpace = nil, nil, nil, nil, nil, nil
if c.UVs != nil {
topUV = c.UVs.Top
bottomUV = c.UVs.Bottom
Expand Down Expand Up @@ -321,12 +321,31 @@ type CubeUVsNode struct {
}

func (cnd CubeUVsNode) Uv(out *nodes.StructOutput[CubeUVs]) {
out.Set(CubeUVs{
Top: nodes.TryGetOutputReference(out, cnd.Top, nil),
Bottom: nodes.TryGetOutputReference(out, cnd.Bottom, nil),
Left: nodes.TryGetOutputReference(out, cnd.Left, nil),
Right: nodes.TryGetOutputReference(out, cnd.Right, nil),
Front: nodes.TryGetOutputReference(out, cnd.Front, nil),
Back: nodes.TryGetOutputReference(out, cnd.Back, nil),
})
uvs := CubeUVs{}

if cnd.Top != nil {
uvs.Top = nodes.GetOutputValue(out, cnd.Top)
}

if cnd.Bottom != nil {
uvs.Bottom = nodes.GetOutputValue(out, cnd.Bottom)
}

if cnd.Left != nil {
uvs.Left = nodes.GetOutputValue(out, cnd.Left)
}

if cnd.Right != nil {
uvs.Right = nodes.GetOutputValue(out, cnd.Right)
}

if cnd.Front != nil {
uvs.Front = nodes.GetOutputValue(out, cnd.Front)
}

if cnd.Back != nil {
uvs.Back = nodes.GetOutputValue(out, cnd.Back)
}

out.Set(uvs)
}
23 changes: 23 additions & 0 deletions nodes/opearations/nodes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package opearations

import (
"github.com/EliCDavis/polyform/generator"
"github.com/EliCDavis/polyform/math/quaternion"
"github.com/EliCDavis/polyform/math/trs"
"github.com/EliCDavis/polyform/nodes"
"github.com/EliCDavis/polyform/refutil"
"github.com/EliCDavis/vector/vector2"
"github.com/EliCDavis/vector/vector3"
)

func init() {
factory := &refutil.TypeFactory{}

refutil.RegisterType[nodes.Struct[SeperateNode[float64]]](factory)
refutil.RegisterType[nodes.Struct[SeperateNode[vector2.Float64]]](factory)
refutil.RegisterType[nodes.Struct[SeperateNode[vector3.Float64]]](factory)
refutil.RegisterType[nodes.Struct[SeperateNode[trs.TRS]]](factory)
refutil.RegisterType[nodes.Struct[SeperateNode[quaternion.Quaternion]]](factory)

generator.RegisterTypes(factory)
}
Loading
Loading