tetra3d

package module
v0.9.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 21, 2022 License: MIT Imports: 23 Imported by: 1

README

Tetra3D

Ebiten Discord

Tetra3D Logo

It Breeds Fear - Construction Worker

Dark exploration

Tetra3D Docs / Tetra3D Wiki

Quickstart Project Repo

Support

If you want to support development, feel free to check out my itch.io / Steam / Patreon. I also have a Discord server here. Thanks~!

What is Tetra3D?

Tetra3D is a 3D hybrid software / hardware renderer written in Go by means of Ebiten, primarily for video games. Compared to a professional 3D rendering system like OpenGL or Vulkan, it's slow and buggy, but it's also janky, and I love it for that. Tetra3D is largely implemented in software, but uses the GPU a bit for rendering triangles and for depth testing (by use of shaders to compare and write depth and composite the result onto the finished texture). Depth testing can be turned off for a performance increase in exchange for no visual inter-object intersection.

Tetra's rendering evokes a similar feeling to primitive 3D game consoles like the PS1, N64, or DS. Being that a largely-software renderer is not nearly fast enough for big, modern 3D titles, the best you're going to get out of Tetra is drawing some 3D elements for your primarily 2D Ebiten game, or a relatively simple fully 3D game (i.e. something on the level of a PS1 or N64 game). That said, limitation breeds creativity, and I am intrigued at the thought of what people could make with Tetra.

In general, Tetra3D's just a renderer, so you can target higher resolutions (like 1080p or 4K) or lower resolutions. Anything's fine as long as the target GPU can handle generating the color and depth textures at your desired resolution (assuming you have depth texture rendering on).

Tetra3D also gives you a Blender add-on to make the Blender > Tetra3D development process flow a bit smoother. See the Releases section for the add-on, and this wiki page for more information.

Why did I make it?

Because there's not really too much of an ability to do 3D for gamedev in Go apart from g3n, go-gl and Raylib-go. I like Go, I like janky 3D, and so, here we are.

It's also interesting to have the ability to spontaneously do things in 3D sometimes. For example, if you were making a 2D game with Ebiten but wanted to display just a few GUI elements or objects in 3D, Tetra3D should work well for you.

Finally, while this hybrid renderer is not by any means fast, it is relatively simple and easy to use. Any platforms that Ebiten supports should also work for Tetra3D automatically.

Why Tetra3D? Why is it named that?

Because it's like a tetrahedron, a relatively primitive (but visually interesting) 3D shape made of 4 triangles. Otherwise, I had other names, but I didn't really like them very much. "Jank3D" was the second-best one, haha.

How do you get it?

go get github.com/xackery/tetra3d

Tetra depends on kvartborg's vector package, and Ebiten itself for rendering. Tetra3D requires Go v1.16 or above. This minimum required version is somewhat arbitrary, as it could run on an older Go version if a couple of functions (primarily the ones that loads data from a file directly) were changed.

The Blender add-on is not required, but is provided as well, and can be downloaded from the releases page or from the repo directly (i.e. click on the file and download it). The add-on provides some useful helper functionality that makes using Tetra3D simpler - for more information, check the Wiki.

How do you use it?

Load a scene, render it. A simple 3D framework means a simple 3D API.

Here's an example:


package main

import (
	"errors"
	"fmt"
	"image/color"

	"github.com/xackery/tetra3d"
	"github.com/hajimehoshi/ebiten/v2"
)

const ScreenWidth = 786
const ScreenHeight = 448

type Game struct {
	GameScene    *tetra3d.Scene
	Camera       *tetra3d.Camera
}

func NewGame() *Game {

	g := &Game{}

	// First, we load a scene from a .gltf or .glb file. LoadGLTFFile takes a filepath and
	// any loading options (nil is taken as a default), and returns a *Library 
	// and an error if it was unsuccessful. We can also use tetra3d.LoadGLTFData() if we don't
	// have access to the host OS's filesystem (like on web, or if the assets are embedded).

	options := tetra3d.DefaultGLTFLoadOptions()
	options.CameraWidth = ScreenWidth
	options.CameraHeight = ScreenHeight

	library, err := tetra3d.LoadGLTFFile("example.gltf", options) 

	if err != nil {
		panic(err)
	}

	// A Library is essentially everything that got exported from your 3D modeler - 
	// all of the scenes, meshes, materials, and animations.

	// The ExportedScene of a Library is the scene that was active when the file was exported.

	// We'll clone the ExportedScene so we don't edit it irreversibly.
	g.GameScene = library.ExportedScene.Clone()

	// Tetra3D uses OpenGL's coordinate system (+X = Right, +Y = Up, +Z = Back), 
	// in comparison to Blender's coordinate system (+X = Right, +Y = Forward, 
	// +Z = Up). Note that when loading models in via GLTF or DAE, models are
	// converted automatically (so up is +Z in Blender and +Y in Tetra3D automatically).

	// We could create a new Camera as below - we would pass the size of the screen to the 
	// Camera so it can create its own buffer textures (which are *ebiten.Images).

	// g.Camera = tetra3d.NewCamera(ScreenWidth, ScreenHeight)

	// However, we can also just grab an existing camera from the scene if it 
	// were exported from the GLTF file. The loading options struct would 
	// specify the camera's backing texture size (defaulting to 1920x1080 if either
	// no loading options are passed, or the default loading options struct is used
	// unaltered).

	g.Camera = g.GameScene.Root.Get("Camera").(*tetra3d.Camera)

	// A Camera implements the tetra3d.INode interface, which means it can be placed
	// in 3D space and can be parented to another Node somewhere in the scene tree.
	// Models, Lights, and Nodes (which are essentially "empties" one can
	// use for positioning and parenting) can, as well.

	// We can place Models, Cameras, and other Nodes with Node.SetWorldPosition() or 
	// Node.SetLocalPosition(). Both functions take a 3D vector.Vector from kvartborg's 
	// vector package.

	// The *World variants position Nodes in absolute space; the Local variants
	// position Nodes relative to their parents' positioning and transforms.
	// You can also move Nodes using Node.Move(x, y, z) / Node.MoveVec(vector).

	// Each Scene has a tree that starts with the Root Node. To add Nodes to the Scene, 
	// parent them to the Scene's base, like so:

	// g.GameScene.Root.AddChildren(object)

	// For Cameras, we don't actually need to have them in the scene to view it, since
	// the presence of the Camera in the Scene node tree doesn't impact what it would see.

	// We can see the tree "visually" by printing out the hierarchy:
	fmt.Println(g.GameScene.Root.HierarchyAsString())

	return g
}

func (g *Game) Update() error { return nil }

func (g *Game) Draw(screen *ebiten.Image) {

	// Call Camera.Clear() to clear its internal backing texture. This
	// should be called once per frame before drawing your Scene.
	g.Camera.Clear()

	// Now we'll render the Scene from the camera. The Camera's ColorTexture will then 
	// hold the result. 

	// Below, we'll pass both the Scene and the scene root because 1) the Scene influences
	// how Models draw (fog, for example), and 2) we may not want to render all Models. 

	// Camera.RenderNodes() renders all Nodes in a tree, starting with the 
	// Node specified. You can also use Camera.Render() to simply render a selection of
	// individual Models.
	g.Camera.RenderNodes(g.GameScene, g.GameScene.Root) 

	// Before drawing the result, clear the screen first; in this case, with a color.
	screen.Fill(color.RGBA{20, 30, 40, 255})

	// Draw the resulting texture to the screen, and you're done! You can 
	// also visualize the depth texture with g.Camera.DepthTexture.
	screen.DrawImage(g.Camera.ColorTexture, nil) 

}

func (g *Game) Layout(w, h int) (int, int) {
	// This is the size of the window; note that we set it
	// to be the same as the size of the backing camera texture. However,
	// you could use a much larger backing texture size, thereby reducing 
	// certain visual glitches from triangles not drawing tightly enough.
	return ScreenWidth, ScreenHeight
}

func main() {

	game := NewGame()

	if err := ebiten.RunGame(game); err != nil {
		panic(err)
	}

}


You can also do collision testing between BoundingObjects, a category of nodes designed for this purpose. As a simplified example:


type Game struct {

	Cube *tetra3d.BoundingAABB
	Capsule *tetra3d.BoundingCapsule

}

func NewGame() *Game {

	g := &Game{}

	// Create a new BoundingCapsule, 1 unit tall with a 0.25 unit radius for the caps at the ends.
	g.Capsule = tetra3d.NewBoundingCapsule("player", 1, 0.25)

	// Create a new BoundingAABB, of 0.5 width, height, and depth (in that order).
	g.Cube = tetra3d.NewBoundingAABB("block", 0.5, 0.5, 0.5)

	// Move it over on the X axis by 4 units.
	g.Cube.Move(4, 0, 0)

	return g

}

func (g *Game) Update() {

	// Move the capsule 0.2 units to the right every frame.
	g.Capsule.Move(0.2, 0, 0)

	// Will print the result of the Collision, or nil, if there was no intersection.
	fmt.Println(g.Capsule.Collision(g.Cube))

}

That's basically it.

Note that Tetra3D is, indeed, a work-in-progress and so will require time to get to a good state. But I feel like it works pretty well as is. Feel free to examine the examples folder for some examples showing how Tetra3D works. Calling go run . from within their directories should work.

There's a quick start project repo available here, as well to help with getting started.

For more information, check out the Wiki for tips and tricks.

What's missing?

The following is a rough to-do list (tasks with checks have been implemented):

  • 3D rendering
  • -- Perspective projection
  • -- Orthographic projection (it's kinda jank, but it works)
  • -- Automatic billboarding (not sure?)
  • -- Sprites (a way to draw 2D images with no perspective changes (if desired), but within 3D space) (not sure?)
  • -- Basic depth sorting (sorting vertices in a model according to distance, sorting models according to distance)
  • -- A depth buffer and depth testing - This is now implemented by means of a depth texture and Kage shader, though the downside is that it requires rendering and compositing the scene into textures twice. Also, it doesn't work on triangles from the same object (as we can't render to the depth texture while reading it for existing depth).
  • -- A more advanced / accurate depth buffer
  • -- Writing depth through some other means than vertex colors for precision
  • -- Depth testing within the same object - I'm unsure if I will be able to implement this.
  • -- Offscreen Rendering
  • -- Mesh merging - Meshes can be merged together to lessen individual object draw calls.
  • -- Render batching - We can avoid calling Image.DrawTriangles between objects if they share properties (blend mode, material, etc) and it's not too many triangles to push before flushing to the GPU. Perhaps these Materials can have a flag that you can toggle to enable this behavior? (EDIT: This has been partially added by dynamic batching of Models.)
  • -- Texture wrapping (will require rendering with shaders) - This is kind of implemented, but I don't believe it's been implemented for alpha clip materials.
  • -- Draw triangle in 3D space (could be useful for 3D lines, for example)
  • -- Easy dynamic 3D Text (the current idea is to render the text to texture from a font, and then map it to a plane)
  • -- Lighting Probes - general idea is to be able to specify a space that has basic (optionally continuously updated) AO and lighting information, so standing a character in this spot makes him greener, that spot redder, that spot darker because he's in the shadows, etc.
  • Culling
  • -- Backface culling
  • -- Frustum culling
  • -- Far triangle culling
  • -- Triangle clipping to view (this isn't implemented, but not having it doesn't seem to be too much of a problem for now)
  • Debug
  • -- Debug text: overall render time, FPS, render call count, vertex count, triangle count, skipped triangle count
  • -- Wireframe debug rendering
  • -- Normal debug rendering
  • Materials
  • -- Basic Texturing
  • -- Multitexturing / Per-triangle Materials
  • -- Perspective-corrected texturing (currently it's affine, see Wikipedia)
  • Animations
  • -- Armature-based animations
  • -- Object transform-based animations
  • -- Blending between animations
  • -- Linear keyframe interpolation
  • -- Constant keyframe interpolation
  • -- Bezier keyframe interpolation
  • -- Morph (mesh-based) animations
  • Scenes
  • -- Fog
  • -- A node or scenegraph for parenting and simple visibility culling
  • -- Ambient vertex coloring?
  • -- Multiple vertex color channels
  • GLTF / GLB model loading
  • -- Vertex colors loading
  • -- UV map loading
  • -- Normal loading
  • -- Transform / full scene loading
  • -- Animation loading
  • -- Camera loading
  • -- Loading world color in as ambient lighting
  • -- Separate .bin loading
  • Blender Add-on
  • -- Export GLTF on save / on command via button
  • -- Bounds node creation
  • -- Game property export (less clunky version of Blender's vanilla custom properties)
  • -- Collection / group substitution
  • -- -- Overwriting properties through collection instance
  • -- Optional camera size export
  • -- Linking collections from external files
  • -- Material data export
  • -- Option to pack textures or leave them as a path
  • -- Path / 3D Curve support
  • DAE model loading
  • -- Vertex colors loading
  • -- UV map loading
  • -- Normal loading
  • -- Transform / full scene loading
  • Lighting
  • -- Ambient lights
  • -- Point lights
  • -- Directional lights
  • -- Smooth shading
  • -- Take into account view normal (seems most useful for seeing a dark side if looking at a non-backface-culled triangle that is lit) - This is now done for point lights, but not sun lights
  • -- Per-fragment lighting (by pushing it to the GPU, it would be more efficient and look better, of course)
  • Shaders
  • -- Custom fragment shaders
  • -- Normal rendering (useful for, say, screen-space shaders)
  • Collision Testing
  • -- Normal reporting
  • -- Slope reporting
  • -- Contact point reporting
  • -- Varying collision shapes
  • -- Checking multiple collisions at the same time
Collision Type Sphere AABB Triangle Capsule Ray (not implemented yet)
Sphere
AABB ⛔ (buggy)
Triangle ⛔ (buggy) ⛔ (buggy)
Capsule
Ray
  • 3D Sound (adjusting panning of sound sources based on 3D location)
  • Optimization
  • -- Multithreading (particularly for vertex transformations)
  • -- Armature animation improvements?
  • -- Replace vector.Vector usage with struct-based custom vectors (that aren't allocated to the heap or reallocated unnecessarily, ideally)
  • -- Vector pools
  • -- Matrix pools?
  • -- Lighting speed improvements
  • -- Prefer Discrete GPU for computers with both discrete and integrated graphics cards

Again, it's incomplete and jank. However, it's also pretty cool!

Shout-out time~

Huge shout-out to the open-source community:

... For sharing the information and code to make this possible; I would definitely have never been able to create this otherwise.

Documentation

Index

Constants

View Source
const (
	TrackTypePosition = "Pos"
	TrackTypeScale    = "Sca"
	TrackTypeRotation = "Rot"

	InterpolationLinear = iota
	InterpolationConstant
	InterpolationCubic // Unimplemented
)
View Source
const (
	FinishModeLoop     = iota // Loop on animation completion
	FinishModePingPong        // Reverse on animation completion; if this is the case, the OnFinish() callback is called after two loops (one reversal)
	FinishModeStop            // Stop on animation completion
)
View Source
const (
	AccumlateColorModeNone            = iota // No accumulation buffer rendering
	AccumlateColorModeBelow                  // Accumulation buffer is on and applies over time, renders ColorTexture after the accumulation result (which is, then, below)
	AccumlateColorModeAbove                  // Accumulation buffer is on and applies over time, renders ColorTexture before the accumulation result (which is on top)
	AccumlateColorModeSingleLastFrame        // Accumulation buffer is on and renders just the previous frame's ColorTexture result
)
View Source
const (
	TriangleSortModeBackToFront = iota // TriangleSortBackToFront sorts the triangles from back to front (naturally). This is the default.
	TriangleSortModeFrontToBack        // TriangleSortFrontToBack sorts the triangles in reverse order.
	TriangleSortModeNone               // TriangleSortNone doesn't sort the triangles at all; this is the fastest triangle sorting mode, while also being the most graphically inaccurate. Usable if triangles don't visually intersect.
)
View Source
const (
	// TransparencyModeAuto means it will be opaque if the object or material's alpha >= 1, and transparent otherwise.
	TransparencyModeAuto = iota

	// TransparencyModeOpaque means the triangles are rendered to the color and depth buffer as normal.
	TransparencyModeOpaque

	// TransparencyModeAlphaClip means the triangles are rendered to the color and depth buffer, using the alpha of the triangles' texture to "cut out" the triangles.
	TransparencyModeAlphaClip

	// TransparencyModeTransparent means the triangles are not rendered to the depth buffer, but are rendered in a second pass after opaque and alpha-clip triangles. They are automatically sorted from back-to-front.
	TransparencyModeTransparent
)
View Source
const (
	BillboardModeNone = iota
	BillboardModeXZ   // Billboards on just X and Z (so the tilt stays the same)
	BillboardModeAll  // Billboards on all axes
)
View Source
const (
	FogOff       = iota // No fog
	FogAdd              // Additive blended fog
	FogMultiply         // Multiplicative blended fog
	FogOverwrite        // Color overwriting fog (mixing base with fog color over depth distance)
)

Variables

This section is empty.

Functions

func ToDegrees

func ToDegrees(radians float64) float64

ToDegrees is a helper function to easily convert radians to degrees for human readability.

func ToRadians

func ToRadians(degrees float64) float64

ToRadians is a helper function to easily convert degrees to radians (which is what the rotation-oriented functions in Tetra3D use).

Types

type AmbientLight

type AmbientLight struct {
	*Node
	Color *Color // Color is the color of the PointLight.
	// Energy is the overall energy of the Light. Internally, technically there's no difference between a brighter color and a
	// higher energy, but this is here for convenience / adherance to GLTF / 3D modelers.
	Energy float32
	On     bool // If the light is on and contributing to the scene.
}

AmbientLight represents an ambient light that colors the entire Scene.

func NewAmbientLight

func NewAmbientLight(name string, r, g, b, energy float32) *AmbientLight

NewAmbientLight returns a new AmbientLight.

func (*AmbientLight) AddChildren

func (amb *AmbientLight) AddChildren(children ...INode)

AddChildren parents the provided children Nodes to the passed parent Node, inheriting its transformations and being under it in the scenegraph hierarchy. If the children are already parented to other Nodes, they are unparented before doing so.

func (*AmbientLight) Clone

func (amb *AmbientLight) Clone() INode

func (*AmbientLight) Light

func (amb *AmbientLight) Light(triIndex int, model *Model) [9]float32

Light returns the light level for the ambient light. It doesn't use the provided Triangle; it takes it as an argument to simply adhere to the Light interface.

func (*AmbientLight) Type

func (amb *AmbientLight) Type() NodeType

Type returns the NodeType for this object.

func (*AmbientLight) Unparent

func (amb *AmbientLight) Unparent()

Unparent unparents the AmbientLight from its parent, removing it from the scenegraph.

type Animation

type Animation struct {
	Name     string
	Channels map[string]*AnimationChannel
	Length   float64  // Length of the animation in seconds
	Markers  []Marker // Markers as specified in the Animation from the modeler
	// contains filtered or unexported fields
}

Animation represents an animation of some description; it can have multiple channels, indicating movement, scale, or rotational change of one or more Nodes in the Animation.

func NewAnimation

func NewAnimation(name string) *Animation

NewAnimation creates a new Animation of the name specified.

func (*Animation) AddChannel

func (animation *Animation) AddChannel(name string) *AnimationChannel

func (*Animation) Library

func (animation *Animation) Library() *Library

Library returns the Library from which this Animation was loaded. If it was created in code, this function would return nil.

type AnimationChannel

type AnimationChannel struct {
	Name   string
	Tracks map[string]*AnimationTrack
}

func NewAnimationChannel

func NewAnimationChannel(name string) *AnimationChannel

func (*AnimationChannel) AddTrack

func (channel *AnimationChannel) AddTrack(trackType string) *AnimationTrack

type AnimationPlayer

type AnimationPlayer struct {
	RootNode           INode
	ChannelsToNodes    map[*AnimationChannel]INode
	ChannelsUpdated    bool
	Animation          *Animation
	Playhead           float64                                   // Playhead of the animation. Setting this to 0 restarts the animation.
	PlaySpeed          float64                                   // Playback speed in percentage - defaults to 1 (100%)
	Playing            bool                                      // Whether the player is playing back or not.
	FinishMode         int                                       // What to do when the player finishes playback. Defaults to looping.
	OnFinish           func()                                    // Callback indicating the Animation has completed
	OnMarkerTouch      func(marker Marker, animation *Animation) // Callback indicating when the AnimationPlayer has entered a marker
	AnimatedProperties map[INode]*AnimationValues                // The properties that have been animated

	BlendTime float64 // How much time in seconds to blend between two animations

	// If the AnimationPlayer should play the last frame or not. For example, if you have an animation that starts on frame 1 and goes to frame 10,
	// then if PlayLastFrame is on, it will play all frames, INCLUDING frame 10, and only then repeat (if it's set to repeat).
	// Otherwise, it will only play frames 1 - 9, which can be good if your last frame is a repeat of the first to make a cyclical animation.
	// The default for PlayLastFrame is false.
	PlayLastFrame bool
	// contains filtered or unexported fields
}

AnimationPlayer is an object that allows you to play back an animation on a Node.

func NewAnimationPlayer

func NewAnimationPlayer(node INode) *AnimationPlayer

NewAnimationPlayer returns a new AnimationPlayer for the Node.

func (*AnimationPlayer) Clone

func (ap *AnimationPlayer) Clone() *AnimationPlayer

Clone returns a clone of the specified AnimationPlayer.

func (*AnimationPlayer) Play

func (ap *AnimationPlayer) Play(animation *Animation)

Play plays the specified animation back, resetting the playhead if the specified animation is not currently playing. If the animation is already playing, Play() does nothing.

func (*AnimationPlayer) SetRoot

func (ap *AnimationPlayer) SetRoot(node INode)

SetRoot sets the root node of the animation player to act on. Note that this should be the root node.

func (*AnimationPlayer) Update

func (ap *AnimationPlayer) Update(dt float64)

Update updates the animation player by the delta specified in seconds (usually 1/FPS or 1/TARGET FPS), animating the transformation properties of the root node's tree.

type AnimationTrack

type AnimationTrack struct {
	Type          string
	Keyframes     []*Keyframe
	Interpolation int
}

func (*AnimationTrack) AddKeyframe

func (track *AnimationTrack) AddKeyframe(time float64, data interface{})

func (*AnimationTrack) ValueAsQuaternion

func (track *AnimationTrack) ValueAsQuaternion(time float64) *Quaternion

func (*AnimationTrack) ValueAsVector

func (track *AnimationTrack) ValueAsVector(time float64) vector.Vector

type AnimationValues

type AnimationValues struct {
	Position vector.Vector
	Scale    vector.Vector
	Rotation *Quaternion
}

AnimationValues indicate the current position, scale, and rotation for a Node.

type BoundingAABB

type BoundingAABB struct {
	*Node

	Size vector.Vector
	// contains filtered or unexported fields
}

BoundingAABB represents a 3D AABB (Axis-Aligned Bounding Box), a 3D cube of varying width, height, and depth that cannot rotate. The primary purpose of a BoundingAABB is, like the other Bounding* Nodes, to perform intersection testing between itself and other BoundingObject Nodes.

func NewBoundingAABB

func NewBoundingAABB(name string, width, height, depth float64) *BoundingAABB

NewBoundingAABB returns a new BoundingAABB Node.

func (*BoundingAABB) AddChildren

func (box *BoundingAABB) AddChildren(children ...INode)

AddChildren parents the provided children Nodes to the passed parent Node, inheriting its transformations and being under it in the scenegraph hierarchy. If the children are already parented to other Nodes, they are unparented before doing so.

func (*BoundingAABB) Clone

func (box *BoundingAABB) Clone() INode

Clone returns a new BoundingAABB.

func (*BoundingAABB) ClosestPoint

func (box *BoundingAABB) ClosestPoint(point vector.Vector) vector.Vector

ClosestPoint returns the closest point, to the point given, on the inside or surface of the BoundingAABB.

func (*BoundingAABB) Colliding

func (box *BoundingAABB) Colliding(other BoundingObject) bool

Colliding returns true if the BoundingAABB is colliding with another BoundingObject.

func (*BoundingAABB) Collision

func (box *BoundingAABB) Collision(other BoundingObject) *Collision

Collision returns the Collision between the BoundingAABB and the other BoundingObject. If there is no intersection, the function returns nil. (Note that BoundingAABB > BoundingTriangles collision is buggy at the moment.)

func (*BoundingAABB) CollisionTest

func (box *BoundingAABB) CollisionTest(dx, dy, dz float64, others ...BoundingObject) []*Collision

CollisionTest performs an collision test if the bounding object were to move in the given direction in world space. It returns all valid Collisions across all BoundingObjects passed in as others. Collisions will be sorted in order of distance. If no Collisions occurred, it will return an empty slice.

func (*BoundingAABB) CollisionTestVec

func (box *BoundingAABB) CollisionTestVec(moveVec vector.Vector, others ...BoundingObject) []*Collision

CollisionTestVec performs an collision test if the bounding object were to move in the given direction in world space using a vector. It returns all valid Collisions across all BoundingObjects passed in as others. Collisions will be sorted in order of distance. If no Collisions occurred, it will return an empty slice.

func (*BoundingAABB) SetDimensions

func (box *BoundingAABB) SetDimensions(newWidth, newHeight, newDepth float64)

SetDimensions sets the BoundingAABB's internal dimensions (prior to resizing or rotating the Node).

func (*BoundingAABB) Transform

func (box *BoundingAABB) Transform() Matrix4

func (*BoundingAABB) Type

func (box *BoundingAABB) Type() NodeType

Type returns the NodeType for this object.

type BoundingCapsule

type BoundingCapsule struct {
	*Node
	Height float64
	Radius float64
	// contains filtered or unexported fields
}

BoundingCapsule represents a 3D capsule, whose primary purpose is to perform intersection testing between itself and other Bounding Nodes.

func NewBoundingCapsule

func NewBoundingCapsule(name string, height, radius float64) *BoundingCapsule

NewBoundingCapsule returns a new BoundingCapsule instance. Name is the name of the underlying Node for the Capsule, height is the total height of the Capsule, and radius is how big around the capsule is. Height has to be at least radius (otherwise, it would no longer be a capsule).

func (*BoundingCapsule) AddChildren

func (capsule *BoundingCapsule) AddChildren(children ...INode)

AddChildren parents the provided children Nodes to the passed parent Node, inheriting its transformations and being under it in the scenegraph hierarchy. If the children are already parented to other Nodes, they are unparented before doing so.

func (*BoundingCapsule) Bottom

func (capsule *BoundingCapsule) Bottom() vector.Vector

Bottom returns the world position of the bottom of the BoundingCapsule.

func (*BoundingCapsule) Clone

func (capsule *BoundingCapsule) Clone() INode

Clone returns a new BoundingCapsule.

func (*BoundingCapsule) ClosestPoint

func (capsule *BoundingCapsule) ClosestPoint(point vector.Vector) vector.Vector

ClosestPoint returns the closest point on the capsule's "central line" to the point provided. Essentially, ClosestPoint returns a point along the capsule's line in world coordinates, capped between its bottom and top.

func (*BoundingCapsule) Colliding

func (capsule *BoundingCapsule) Colliding(other BoundingObject) bool

Colliding returns true if the BoundingCapsule is intersecting the other BoundingObject.

func (*BoundingCapsule) Collision

func (capsule *BoundingCapsule) Collision(other BoundingObject) *Collision

Collision returns a Collision struct if the BoundingCapsule is intersecting another BoundingObject. If no intersection is reported, Collision returns nil.

func (*BoundingCapsule) CollisionTest

func (capsule *BoundingCapsule) CollisionTest(dx, dy, dz float64, others ...BoundingObject) []*Collision

CollisionTest performs an collision test if the bounding object were to move in the given direction in world space. It returns all valid Collisions across all BoundingObjects passed in as others. Collisions will be sorted in order of distance. If no Collisions occurred, it will return an empty slice.

func (*BoundingCapsule) CollisionTestVec

func (capsule *BoundingCapsule) CollisionTestVec(moveVec vector.Vector, others ...BoundingObject) []*Collision

CollisionTestVec performs an collision test if the bounding object were to move in the given direction in world space using a vector. It returns all valid Collisions across all BoundingObjects passed in as others. Collisions will be sorted in order of distance. If no Collisions occurred, it will return an empty slice.

func (*BoundingCapsule) PointInside

func (capsule *BoundingCapsule) PointInside(point vector.Vector) bool

PointInside returns true if the point provided is within the capsule.

func (*BoundingCapsule) Top

func (capsule *BoundingCapsule) Top() vector.Vector

Top returns the world position of the top of the BoundingCapsule.

func (*BoundingCapsule) Type

func (capsule *BoundingCapsule) Type() NodeType

Type returns the NodeType for this object.

func (*BoundingCapsule) WorldRadius

func (capsule *BoundingCapsule) WorldRadius() float64

WorldRadius is the radius of the Capsule in world units, after taking into account its scale.

type BoundingObject

type BoundingObject interface {
	// Colliding returns true if the BoundingObject is intersecting the other BoundingObject.
	Colliding(other BoundingObject) bool
	// Collision returns a Collision if the BoundingObject is intersecting another BoundingObject. If
	// no intersection is reported, Collision returns nil.
	Collision(other BoundingObject) *Collision
	// CollisionTest performs an collision test if the bounding object were to move in the given direction in world space.
	// It returns all valid Collisions across all BoundingObjects passed in as others. Collisions will be sorted in order of
	// distance. If no Collisions occurred, it will return an empty slice.
	CollisionTest(dx, dy, dz float64, others ...BoundingObject) []*Collision
	// CollisionTestVec performs an collision test if the bounding object were to move in the given direction in world space
	// using a vector. It returns all valid Collisions across all BoundingObjects passed in as others. Collisions will be sorted in order of
	// distance. If no Collisions occurred, it will return an empty slice.
	CollisionTestVec(moveVec vector.Vector, others ...BoundingObject) []*Collision
}

BoundingObject represents a Node type that can be tested for collision. The exposed functions are essentially just concerning whether an object that implements BoundingObject is colliding with another BoundingObject, and if so, by how much.

type BoundingSphere

type BoundingSphere struct {
	*Node
	Radius float64
}

BoundingSphere represents a 3D sphere.

func NewBoundingSphere

func NewBoundingSphere(name string, radius float64) *BoundingSphere

NewBoundingSphere returns a new BoundingSphere instance.

func (*BoundingSphere) AddChildren

func (sphere *BoundingSphere) AddChildren(children ...INode)

AddChildren parents the provided children Nodes to the passed parent Node, inheriting its transformations and being under it in the scenegraph hierarchy. If the children are already parented to other Nodes, they are unparented before doing so.

func (*BoundingSphere) Clone

func (sphere *BoundingSphere) Clone() INode

Clone returns a new BoundingSphere instance.

func (*BoundingSphere) Colliding

func (sphere *BoundingSphere) Colliding(other BoundingObject) bool

Colliding returns true if the BoundingSphere is intersecting the other BoundingObject.

func (*BoundingSphere) Collision

func (sphere *BoundingSphere) Collision(other BoundingObject) *Collision

Collision returns a Collision if the BoundingSphere is intersecting another BoundingObject. If no intersection is reported, Collision returns nil.

func (*BoundingSphere) CollisionTest

func (sphere *BoundingSphere) CollisionTest(dx, dy, dz float64, others ...BoundingObject) []*Collision

CollisionTest performs an collision test if the bounding object were to move in the given direction in world space. It returns all valid Collisions across all BoundingObjects passed in as others. Collisions will be sorted in order of distance. If no Collisions occurred, it will return an empty slice.

func (*BoundingSphere) CollisionTestVec

func (sphere *BoundingSphere) CollisionTestVec(moveVec vector.Vector, others ...BoundingObject) []*Collision

CollisionTestVec performs an collision test if the bounding object were to move in the given direction in world space using a vector. It returns all valid Collisions across all BoundingObjects passed in as others. Collisions will be sorted in order of distance. If no Collisions occurred, it will return an empty slice.

func (*BoundingSphere) PointInside

func (sphere *BoundingSphere) PointInside(point vector.Vector) bool

PointInside returns whether the given point is inside of the sphere or not.

func (*BoundingSphere) Type

func (sphere *BoundingSphere) Type() NodeType

Type returns the NodeType for this object.

func (*BoundingSphere) WorldRadius

func (sphere *BoundingSphere) WorldRadius() float64

WorldRadius returns the radius of the BoundingSphere in world units, after taking into account its scale.

type BoundingTriangles

type BoundingTriangles struct {
	*Node
	BoundingAABB *BoundingAABB
	Mesh         *Mesh
}

BoundingTriangles is a Node specifically for detecting a collision between any of the triangles from a mesh instance and another BoundingObject.

func NewBoundingTriangles

func NewBoundingTriangles(name string, mesh *Mesh) *BoundingTriangles

NewBoundingTriangles returns a new BoundingTriangles object.

func (*BoundingTriangles) AddChildren

func (bt *BoundingTriangles) AddChildren(children ...INode)

AddChildren parents the provided children Nodes to the passed parent Node, inheriting its transformations and being under it in the scenegraph hierarchy. If the children are already parented to other Nodes, they are unparented before doing so.

func (*BoundingTriangles) Clone

func (bt *BoundingTriangles) Clone() INode

func (*BoundingTriangles) Colliding

func (bt *BoundingTriangles) Colliding(other BoundingObject) bool

Colliding returns true if the BoundingTriangles object is intersecting the other specified BoundingObject.

func (*BoundingTriangles) Collision

func (bt *BoundingTriangles) Collision(other BoundingObject) *Collision

Collision returns a Collision if the BoundingTriangles object is intersecting another BoundingObject. If no intersection is reported, Collision returns nil. (Note that BoundingTriangles > AABB collision is buggy at the moment.)

func (*BoundingTriangles) CollisionTest

func (bt *BoundingTriangles) CollisionTest(dx, dy, dz float64, others ...BoundingObject) []*Collision

CollisionTest performs an collision test if the bounding object were to move in the given direction in world space. It returns all valid Collisions across all BoundingObjects passed in as others. Collisions will be sorted in order of distance. If no Collisions occurred, it will return an empty slice.

func (*BoundingTriangles) CollisionTestVec

func (bt *BoundingTriangles) CollisionTestVec(moveVec vector.Vector, others ...BoundingObject) []*Collision

CollisionTestVec performs an collision test if the bounding object were to move in the given direction in world space using a vector. It returns all valid Collisions across all BoundingObjects passed in as others. Collisions will be sorted in order of distance. If no Collisions occurred, it will return an empty slice.

func (*BoundingTriangles) Transform

func (bt *BoundingTriangles) Transform() Matrix4

func (*BoundingTriangles) Type

func (bt *BoundingTriangles) Type() NodeType

Type returns the NodeType for this object.

type Camera

type Camera struct {
	*Node

	RenderDepth bool // If the Camera should attempt to render a depth texture; if this is true, then DepthTexture will hold the depth texture render results.

	AccumulateColorMode   int                      // The mode to use when rendering previous frames to the accumulation buffer. Defaults to AccumulateColorModeNone.
	AccumulateDrawOptions *ebiten.DrawImageOptions // Draw image options to use when rendering frames to the accumulation buffer; use this to fade out or color previous frames.

	Near, Far   float64 // The near and far clipping plane.
	Perspective bool    // If the Camera has a perspective projection. If not, it would be orthographic
	FieldOfView float64 // Vertical field of view in degrees for a perspective projection camera
	OrthoScale  float64 // Scale of the view for an orthographic projection camera in units horizontally

	DebugInfo DebugInfo
	// contains filtered or unexported fields
}

Camera represents a camera (where you look from) in Tetra3D.

func NewCamera

func NewCamera(w, h int) *Camera

NewCamera creates a new Camera with the specified width and height.

func (*Camera) AccumulationColorTexture

func (camera *Camera) AccumulationColorTexture() *ebiten.Image

AccumulationColorTexture returns the camera's final result accumulation color texture from previous renders. If the Camera's AccumulateColorMode property is set to AccumulateColorModeNone, the function will return nil instead.

func (*Camera) AddChildren

func (camera *Camera) AddChildren(children ...INode)

AddChildren parents the provided children Nodes to the passed parent Node, inheriting its transformations and being under it in the scenegraph hierarchy. If the children are already parented to other Nodes, they are unparented before doing so.

func (*Camera) AspectRatio

func (camera *Camera) AspectRatio() float64

AspectRatio returns the camera's aspect ratio (width / height).

func (*Camera) Clear

func (camera *Camera) Clear()

Clear should be called at the beginning of a single rendered frame and clears the Camera's backing textures before rendering. It also resets the debug values.

func (*Camera) ClipToScreen

func (camera *Camera) ClipToScreen(vert vector.Vector) vector.Vector

ClipToScreen projects the pre-transformed vertex in View space and remaps it to screen coordinates.

func (*Camera) Clone

func (camera *Camera) Clone() INode

func (*Camera) ColorTexture

func (camera *Camera) ColorTexture() *ebiten.Image

ColorTexture returns the camera's final result color texture from any previous Render() or RenderNodes() calls.

func (*Camera) DebugDrawText

func (camera *Camera) DebugDrawText(screen *ebiten.Image, txtStr string, posX, posY, textScale float64, color *Color)

func (*Camera) DepthTexture

func (camera *Camera) DepthTexture() *ebiten.Image

DepthTexture returns the camera's final result depth texture from any previous Render() or RenderNodes() calls. If Camera.RenderDepth is set to false, the function will return nil instead.

func (*Camera) DrawDebugBounds

func (camera *Camera) DrawDebugBounds(screen *ebiten.Image, rootNode INode, color *Color)

DrawDebugBounds will draw shapes approximating the shapes and positions of BoundingObjects underneath the rootNode. The shapes will be drawn in the color provided to the screen image provided.

func (*Camera) DrawDebugBoundsColored

func (camera *Camera) DrawDebugBoundsColored(screen *ebiten.Image, rootNode INode, aabbColor, sphereColor, capsuleColor, trianglesColor *Color)

DrawDebugBoundsColored will draw shapes approximating the shapes and positions of BoundingObjects underneath the rootNode. The shapes will be drawn in the color provided for each kind of bounding object to the screen image provided.

func (*Camera) DrawDebugCenters

func (camera *Camera) DrawDebugCenters(screen *ebiten.Image, rootNode INode, color *Color)

DrawDebugCenters draws the center positions of nodes under the rootNode using the color given to the screen image provided.

func (*Camera) DrawDebugDrawCallCount

func (camera *Camera) DrawDebugDrawCallCount(screen *ebiten.Image, rootNode INode, textScale float64, color *Color)

DrawDebugDrawCallCount draws the draw call count of all visible Models underneath the rootNode in the color provided to the screen image provided.

func (*Camera) DrawDebugDrawOrder

func (camera *Camera) DrawDebugDrawOrder(screen *ebiten.Image, rootNode INode, textScale float64, color *Color)

DrawDebugDrawOrder draws the drawing order of all triangles of all visible Models underneath the rootNode in the color provided to the screen image provided.

func (*Camera) DrawDebugFrustums

func (camera *Camera) DrawDebugFrustums(screen *ebiten.Image, rootNode INode, color *Color)

DrawDebugFrustums will draw shapes approximating the frustum spheres for objects underneath the rootNode. The shapes will be drawn in the color provided to the screen image provided.

func (*Camera) DrawDebugNormals

func (camera *Camera) DrawDebugNormals(screen *ebiten.Image, rootNode INode, normalLength float64, color *Color)

DrawDebugNormals draws the normals of visible models underneath the rootNode given to the screen. NormalLength is the length of the normal lines in units. Color is the color to draw the normals.

func (*Camera) DrawDebugRenderInfo

func (camera *Camera) DrawDebugRenderInfo(screen *ebiten.Image, textScale float64, color *Color)

DrawDebugRenderInfo draws render debug information (like number of drawn objects, number of drawn triangles, frame time, etc) at the top-left of the provided screen *ebiten.Image, using the textScale and color provided.

func (*Camera) DrawDebugWireframe

func (camera *Camera) DrawDebugWireframe(screen *ebiten.Image, rootNode INode, color *Color)

DrawDebugWireframe draws the wireframe triangles of all visible Models underneath the rootNode in the color provided to the screen image provided.

func (*Camera) PointInFrustum

func (camera *Camera) PointInFrustum(point vector.Vector) bool

PointInFrustum returns true if the point is visible through the camera frustum.

func (*Camera) Projection

func (camera *Camera) Projection() Matrix4

Projection returns the Camera's projection matrix.

func (*Camera) Render

func (camera *Camera) Render(scene *Scene, models ...*Model)

Render renders all of the models passed using the provided Scene's properties (fog, for example). Note that if Camera.RenderDepth is false, scenes rendered one after another in multiple Render() calls will be rendered on top of each other in the Camera's texture buffers. Note that for Models, each MeshPart of a Model has a maximum renderable triangle count of 21845.

func (*Camera) RenderNodes

func (camera *Camera) RenderNodes(scene *Scene, rootNode INode)

RenderNodes renders all nodes starting with the provided rootNode using the Scene's properties (fog, for example). Note that if Camera.RenderDepth is false, scenes rendered one after another in multiple RenderNodes() calls will be rendered on top of each other in the Camera's texture buffers. Note that for Models, each MeshPart of a Model has a maximum renderable triangle count of 21845.

func (*Camera) Resize

func (camera *Camera) Resize(w, h int)

func (*Camera) SetOrthographic

func (camera *Camera) SetOrthographic(orthoScale float64)

SetOrthographic sets the Camera's projection to be an orthographic projection. orthoScale indicates the scale of the camera in units horizontally.

func (*Camera) SetPerspective

func (camera *Camera) SetPerspective(fovY float64)

SetPerspective sets the Camera's projection to be a perspective projection. fovY indicates the vertical field of view (in degrees) for the camera's aperture.

func (*Camera) SphereInFrustum

func (camera *Camera) SphereInFrustum(sphere *BoundingSphere) bool

SphereInFrustum returns true if the sphere would be visible through the camera frustum.

func (*Camera) Type

func (camera *Camera) Type() NodeType

Type returns the NodeType for this object.

func (*Camera) Unparent

func (camera *Camera) Unparent()

Unparent unparents the Camera from its parent, removing it from the scenegraph.

func (*Camera) ViewMatrix

func (camera *Camera) ViewMatrix() Matrix4

ViewMatrix returns the Camera's view matrix.

func (*Camera) WorldToClip

func (camera *Camera) WorldToClip(vert vector.Vector) vector.Vector

WorldToClip transforms a 3D position in the world to clip coordinates (before screen normalization).

func (*Camera) WorldToScreen

func (camera *Camera) WorldToScreen(vert vector.Vector) vector.Vector

WorldToScreen transforms a 3D position in the world to screen coordinates.

type Collision

type Collision struct {
	CollidedObject BoundingObject  // The BoundingObject collided with
	Intersections  []*Intersection // The slice of Intersections, one for each object or triangle intersected with, arranged in order of distance (far to close).
}

Collision represents the result of a collision test. A Collision test may result in multiple intersections, and so an Collision holds each of these individual intersections in its Intersections slice. The intersections are sorted in order of distance from the starting point of the intersection (the center of the colliding sphere / aabb, the closest point in the capsule, the center of the closest triangle, etc) to the contact point.

func (*Collision) AverageContactPoint

func (result *Collision) AverageContactPoint() vector.Vector

AverageContactPoint returns the average contact point out of the contact points of all Intersections contained within the Collision.

func (*Collision) AverageMTV

func (col *Collision) AverageMTV() vector.Vector

AverageMTV returns the average MTV (minimum translation vector) from all Intersections contained within the Collision. To be specific, this isn't actually the pure average, but rather is the result of adding together all MTVs from Intersections in the Collision for the direction, and using the greatest MTV's magnitude for the distance of the returned vector. In other words, AverageMTV returns the MTV to move in that should resolve all intersections from the Collision.

func (*Collision) AverageSlope

func (result *Collision) AverageSlope() float64

AverageSlope returns the average slope of the Collision (ranging from 0, pointing straight up, to pi pointing straight down). This average is spread across all intersections contained within the Collision.

type Color

type Color struct {
	R, G, B, A float32
}

Color represents a color, containing R, G, B, and A components, each expected to range from 0 to 1.

func NewColor

func NewColor(r, g, b, a float32) *Color

NewColor returns a new Color, with the provided R, G, B, and A components expected to range from 0 to 1.

func NewColorFromHSV

func NewColorFromHSV(h, s, v float64) *Color

NewColorFromHSV returns a new color, using hue, saturation, and value numbers, each ranging from 0 to 1. A hue of 0 is red, while 1 is also red, but on the other end of the spectrum. Cribbed from: https://github.com/lucasb-eyer/go-colorful/blob/master/colors.go

func (*Color) Add

func (color *Color) Add(other *Color)

Add adds the provided Color to the existing Color.

func (*Color) AddRGBA

func (color *Color) AddRGBA(r, g, b, a float32)

AddRGBA adds the provided R, G, B, and A values to the color as provided. The components are expected to range from 0 to 1.

func (*Color) Clone

func (color *Color) Clone() *Color

Clone returns a clone of the Color instance.

func (*Color) ConvertTosRGB

func (color *Color) ConvertTosRGB()

ConvertTosRGB() converts the color's R, G, and B components to the sRGB color space. This is used to convert colors from their values in GLTF to how they should appear on the screen. See: https://en.wikipedia.org/wiki/SRGB

func (*Color) HSV

func (color *Color) HSV() (float64, float64, float64)

HSV returns a color as a hue, saturation, and value (each ranging from 0 to 1). Also cribbed from: https://github.com/lucasb-eyer/go-colorful/blob/master/colors.go

func (*Color) Multiply

func (color *Color) Multiply(other *Color)

Multiply multiplies the existing Color by the provided Color.

func (*Color) MultiplyRGBA

func (color *Color) MultiplyRGBA(scalarR, scalarG, scalarB, scalarA float32)

MultiplyRGBA multiplies the color's RGBA channels by the provided R, G, B, and A scalar values.

func (*Color) Set

func (color *Color) Set(r, g, b, a float32)

Set sets the RGBA components of the Color to the r, g, b, and a arguments provided. The components are expected to range from 0 to 1.

func (*Color) ToFloat32s

func (color *Color) ToFloat32s() (float32, float32, float32, float32)

ToFloat32s returns the Color as four float32 in the order R, G, B, and A.

func (*Color) ToFloat64s

func (color *Color) ToFloat64s() (float64, float64, float64, float64)

ToFloat64s returns four float64 values for each channel in the Color in the order R, G, B, and A.

func (*Color) ToRGBA64

func (c *Color) ToRGBA64() color.RGBA64

ToRGBA64 converts a color to a color.RGBA64 instance.

type DaeLoadOptions

type DaeLoadOptions struct {
	CorrectYUp bool // Whether to correct Z being up for Blender importing.
}

DaeLoadOptions represents options one can use to tweak how .dae files are loaded into Tetra3D.

func DefaultDaeLoadOptions

func DefaultDaeLoadOptions() *DaeLoadOptions

DefaultDaeLoadOptions returns a default instance of DaeLoadOptions.

type Data

type Data struct {
	// contains filtered or unexported fields
}

func (*Data) AsQuaternion

func (data *Data) AsQuaternion() *Quaternion

func (*Data) AsVector

func (data *Data) AsVector() vector.Vector

type DebugInfo

type DebugInfo struct {
	AvgFrameTime     time.Duration // Amount of CPU frame time spent transforming vertices. Doesn't necessarily include CPU time spent sending data to the GPU.
	AvgAnimationTime time.Duration // Amount of CPU frame time spent animating vertices.
	AvgLightTime     time.Duration // Amount of CPU frame time spent lighting vertices.

	DrawnParts       int // Number of draw calls, excluding those invisible or culled based on distance
	TotalParts       int // Total number of objects
	DrawnTris        int // Number of drawn triangles, excluding those hidden from backface culling
	TotalTris        int // Total number of triangles
	LightCount       int // Total number of lights
	ActiveLightCount int // Total active number of lights
	// contains filtered or unexported fields
}

DebugInfo is a struct that holds debugging information for a Camera's render pass. These values are reset when Camera.Clear() is called.

type Dimensions

type Dimensions []vector.Vector

Dimensions represents the minimum and maximum spatial dimensions of a Mesh arranged in a 2-space Vector slice.

func (Dimensions) Center

func (dim Dimensions) Center() vector.Vector

Center returns the center point inbetween the two corners of the dimension set.

func (Dimensions) Clone

func (dim Dimensions) Clone() Dimensions

func (Dimensions) Depth

func (dim Dimensions) Depth() float64

Depth returns the total difference between the minimum and maximum Z values.

func (Dimensions) Height

func (dim Dimensions) Height() float64

Height returns the total difference between the minimum and maximum Y values.

func (Dimensions) MaxDimension

func (dim Dimensions) MaxDimension() float64

MaxDimension returns the maximum value from all of the axes in the Dimensions. For example, if the Dimensions have a min of [-1, -2, -2], and a max of [6, 1.5, 1], Max() will return 7 for the X axis, as it's the largest distance between all axes.

func (Dimensions) MaxSpan

func (dim Dimensions) MaxSpan() float64

MaxSpan returns the maximum span between the corners of the dimension set.

func (Dimensions) Width

func (dim Dimensions) Width() float64

Width returns the total difference between the minimum and maximum X values.

type DirectionalLight

type DirectionalLight struct {
	*Node
	Color *Color // Color is the color of the PointLight.
	// Energy is the overall energy of the Light. Internally, technically there's no difference between a brighter color and a
	// higher energy, but this is here for convenience / adherance to GLTF / 3D modelers.
	Energy float32
	On     bool // If the light is on and contributing to the scene.
	// contains filtered or unexported fields
}

DirectionalLight represents a directional light of infinite distance.

func NewDirectionalLight

func NewDirectionalLight(name string, r, g, b, energy float32) *DirectionalLight

NewDirectionalLight creates a new Directional Light with the specified RGB color and energy (assuming 1.0 energy is standard / "100%" lighting).

func (*DirectionalLight) AddChildren

func (sun *DirectionalLight) AddChildren(children ...INode)

AddChildren parents the provided children Nodes to the passed parent Node, inheriting its transformations and being under it in the scenegraph hierarchy. If the children are already parented to other Nodes, they are unparented before doing so.

func (*DirectionalLight) Clone

func (sun *DirectionalLight) Clone() INode

Clone returns a new DirectionalLight clone from the given DirectionalLight.

func (*DirectionalLight) Light

func (sun *DirectionalLight) Light(triIndex int, model *Model) [9]float32

Light returns the R, G, and B values for the DirectionalLight for each vertex of the provided Triangle.

func (*DirectionalLight) Type

func (sun *DirectionalLight) Type() NodeType

Type returns the NodeType for this object.

func (*DirectionalLight) Unparent

func (sun *DirectionalLight) Unparent()

Unparent unparents the DirectionalLight from its parent, removing it from the scenegraph.

type FogMode

type FogMode int

type GLTFLoadOptions

type GLTFLoadOptions struct {
	CameraWidth, CameraHeight int  // Width and height of loaded Cameras. Defaults to 1920x1080.
	CameraDepth               bool // If cameras should render depth or not
	DefaultToAutoTransparency bool // If DefaultToAutoTransparency is true, then opaque materials become Auto transparent materials in Tetra3D.
	// DependentLibraryResolver is a function that takes a relative path (string) to the blend file representing the dependent Library that the loading
	// Library requires. This function should return a reference to the dependent Library; if it returns nil, the linked objects from the dependent Library
	// will not be instantiated in the loading Library.
	// An example would be loading a level (level.gltf) composed of assets from another file (a GLTF file exported from assets.blend, which is a directory up).
	// In this example, loading level.gltf would require the dependent library, found in assets.gltf. Loading level.gltf will refer to objects linked from the assets
	// blend file, known as "../assets.blend".
	// You could then simply load the assets library first and then code the DependentLibraryResolver function to take the assets library, or code the
	// function to use the path to load the library on demand. You could then store the loaded result as necessary if multiple levels use this assets Library.
	DependentLibraryResolver func(blendPath string) *Library
}

func DefaultGLTFLoadOptions

func DefaultGLTFLoadOptions() *GLTFLoadOptions

DefaultGLTFLoadOptions creates an instance of GLTFLoadOptions with some sensible defaults.

type INode

type INode interface {
	// Name returns the object's name.
	Name() string
	// SetName sets the object's name.
	SetName(name string)
	// Clone returns a clone of the specified INode implementer.
	Clone() INode
	// SetData sets user-customizeable data that could be usefully stored on this node.
	SetData(data interface{})
	// Data returns a pointer to user-customizeable data that could be usefully stored on this node.
	Data() interface{}
	// Type returns the NodeType for this object.
	Type() NodeType

	// Library returns the source Library from which this Node was instantiated. If it was created through code, this will be nil.
	Library() *Library

	// Parent returns the Node's parent. If the Node has no parent, this will return nil.
	Parent() INode
	// Unparent unparents the Node from its parent, removing it from the scenegraph.
	Unparent()
	// Scene looks for the Node's parents recursively to return what scene it exists in.
	// If the node is not within a tree (i.e. unparented), this will return nil.
	Scene() *Scene
	// Root returns the root node in this tree by recursively traversing this node's hierarchy of
	// parents upwards.
	Root() INode

	// Children() returns the Node's children as a NodeFilter.
	Children() NodeFilter
	// ChildrenRecursive() returns the Node's recursive children (i.e. children, grandchildren, etc)
	// as a NodeFilter.
	ChildrenRecursive() NodeFilter

	// AddChildren parents the provided children Nodes to the passed parent Node, inheriting its transformations and being under it in the scenegraph
	// hierarchy. If the children are already parented to other Nodes, they are unparented before doing so.
	AddChildren(...INode)
	// RemoveChildren removes the provided children from this object.
	RemoveChildren(...INode)

	// ResetLocalTransform resets the local transform properties (position, scale, and rotation) for the Node. This can be useful because
	// by default, when you parent one Node to another, the local transform properties (position, scale, and rotation) are altered to keep the
	// object in the same absolute location, even though the origin changes.
	ResetLocalTransform()
	// SetWorldTransform sets the Node's global (world) transform to the full 4x4 transformation matrix provided.
	SetWorldTransform(transform Matrix4)

	// LocalRotation returns the object's local rotation Matrix4.
	LocalRotation() Matrix4
	// SetLocalRotation sets the object's local rotation Matrix4 (relative to any parent).
	SetLocalRotation(rotation Matrix4)
	LocalPosition() vector.Vector
	// SetLocalPosition sets the object's local position (position relative to its parent). If this object has no parent, the position should be
	// relative to world origin (0, 0, 0). position should be a 3D vector (i.e. X, Y, and Z components).
	SetLocalPosition(position vector.Vector)
	// LocalScale returns the object's local scale (scale relative to its parent). If this object has no parent, the scale will be absolute.
	LocalScale() vector.Vector
	// SetLocalScale sets the object's local scale (scale relative to its parent). If this object has no parent, the scale would be absolute.
	// scale should be a 3D vector (i.e. X, Y, and Z components).
	SetLocalScale(scale vector.Vector)

	// WorldRotation returns an absolute rotation Matrix4 representing the object's rotation.
	WorldRotation() Matrix4
	// SetWorldRotation sets an object's global, world rotation to the provided rotation Matrix4.
	SetWorldRotation(rotation Matrix4)
	WorldPosition() vector.Vector
	SetWorldPosition(position vector.Vector)
	// WorldScale returns the object's absolute world scale as a 3D vector (i.e. X, Y, and Z components).
	WorldScale() vector.Vector
	// SetWorldScale sets the object's absolute world scale. scale should be a 3D vector (i.e. X, Y, and Z components).
	SetWorldScale(scale vector.Vector)

	// Move moves a Node in local space by the x, y, and z values provided.
	Move(x, y, z float64)
	// MoveVec moves a Node in local space using the vector provided.
	MoveVec(moveVec vector.Vector)
	// Rotate rotates a Node locally on the given vector, by the angle provided in radians.
	Rotate(x, y, z, angle float64)
	// Grow scales the object additively (i.e. calling Node.Grow(1, 0, 0) will scale it +1 on the X-axis).
	Grow(x, y, z float64)

	// Transform returns a Matrix4 indicating the global position, rotation, and scale of the object, transforming it by any parents'.
	// If there's no change between the previous Transform() call and this one, Transform() will return a cached version of the
	// transform for efficiency.
	Transform() Matrix4

	// Visible returns whether the Object is visible.
	Visible() bool
	// SetVisible sets the object's visibility. If recursive is true, all recursive children of this Node will have their visibility set the same way.
	SetVisible(visible, recursive bool)

	// Get searches a node's hierarchy using a string to find a specified node. The path is in the format of names of nodes, separated by forward
	// slashes ('/'), and is relative to the node you use to call Get. As an example of Get, if you had a cup parented to a desk, which was
	// parented to a room, that was finally parented to the root of the scene, it would be found at "Room/Desk/Cup". Note also that you can use "../" to
	// "go up one" in the hierarchy (so cup.Get("../") would return the Desk node).
	// Since Get uses forward slashes as path separation, it would be good to avoid using forward slashes in your Node names. Also note that Get()
	// trims the extra spaces from the beginning and end of Node Names, so avoid using spaces at the beginning or end of your Nodes' names.
	Get(path string) INode

	// HierarchyAsString returns a string displaying the hierarchy of this Node, and all recursive children.
	// Nodes will have a "+" next to their name, Models an "M", and Cameras a "C".
	// BoundingSpheres will have BS, BoundingAABB AABB, BoundingCapsule CAP, and BoundingTriangles TRI.
	// Lights will have an L next to their name.
	// This is a useful function to debug the layout of a node tree, for example.
	HierarchyAsString() string

	// Path returns a string indicating the hierarchical path to get this Node from the root. The path returned will be absolute, such that
	// passing it to Get() called on the scene root node will return this node. The path returned will not contain the root node's name ("Root").
	Path() string

	// Tags represents an unordered set of string tags that can be used to identify this object.
	Tags() *Tags

	// IsBone returns if the Node is a "bone" (a node that was a part of an armature and so can play animations back to influence a skinned mesh).
	IsBone() bool

	// AnimationPlayer returns the object's animation player - every object has an AnimationPlayer by default.
	AnimationPlayer() *AnimationPlayer
	// contains filtered or unexported methods
}

INode represents an object that exists in 3D space and can be positioned relative to an origin point. By default, this origin point is {0, 0, 0} (or world origin), but Nodes can be parented to other Nodes to change this origin (making their movements relative and their transforms successive). Models and Cameras are two examples of objects that fully implement the INode interface by means of embedding Node.

type Intersection

type Intersection struct {
	// The contact point between the two intersecting objects. Note that this may be the average
	// between the two overlapping shapes, rather than the point of contact specifically.
	StartingPoint vector.Vector // The starting point for the intersection; either the center of the object for sphere / aabb, the center of the closest point for capsules, or the triangle position for triangless.
	ContactPoint  vector.Vector // The contact point for the intersection.
	MTV           vector.Vector // MTV represents the minimum translation vector to remove the calling object from the intersecting object.
	Triangle      *Triangle     // Triangle represents the triangle that was intersected in intersection tests that involve triangle meshes; if no triangle mesh was tested against, then this will be nil.
	Normal        vector.Vector
}

func (*Intersection) Slope

func (intersection *Intersection) Slope() float64

Slope returns the slope of the intersection's normal, in radians. This ranges from 0 (straight up) to pi (straight down).

type Keyframe

type Keyframe struct {
	Time float64
	Data Data
}

type Library

type Library struct {
	Scenes        []*Scene              // A slice of Scenes
	ExportedScene *Scene                // The scene that was open when the library was exported from the modeler
	Meshes        map[string]*Mesh      // A Map of Meshes to their names
	Animations    map[string]*Animation // A Map of Animations to their names
	Materials     map[string]*Material  // A Map of Materials to their names
}

Library represents a collection of Scenes, Meshes, and Animations, as loaded from an intermediary file format (.dae or .gltf / .glb).

func LoadDAEData

func LoadDAEData(data []byte, options *DaeLoadOptions) (*Library, error)

LoadDAEData takes a []byte consisting of the contents of a DAE file, and returns a *Library populated with the .dae file's objects and meshes. Animations will not be loaded from DAE files, as DAE exports through Blender only support one animation per object (so it's generally advised to use the GLTF or GLB format instead). Cameras exported in the DAE file will be turned into simple Nodes in Tetra3D, as there's not enough information to instantiate a tetra3d.Camera. If the call couldn't complete for any reason, like due to a malformed DAE file, it will return an error.

func LoadDAEFile

func LoadDAEFile(path string, options *DaeLoadOptions) (*Library, error)

LoadDAEFile takes a filepath to a .dae model file, and returns a *Library populated with the .dae file's objects and meshes. Animations will not be loaded from DAE files, as DAE exports through Blender only support one animation per object (so it's generally advised to use the GLTF or GLB format instead). Cameras exported in the DAE file will be turned into simple Nodes in Tetra3D, as there's not enough information to instantiate a tetra3d.Camera. If the call couldn't complete for any reason, like due to a malformed DAE file, it will return an error.

func LoadGLTFData

func LoadGLTFData(data []byte, gltfLoadOptions *GLTFLoadOptions) (*Library, error)

LoadGLTFData loads a .gltf or .glb file from the byte data given, using a provided GLTFLoadOptions struct to alter how the file is loaded. Passing nil for loadOptions will load the file using default load options. Unlike with DAE files, Animations (including armature-based animations) and Cameras (assuming they are exported in the GLTF file) will be parsed properly. LoadGLTFFile will return a Library, and an error if the process fails.

func LoadGLTFFile

func LoadGLTFFile(path string, loadOptions *GLTFLoadOptions) (*Library, error)

LoadGLTFFile loads a .gltf or .glb file from the filepath given, using a provided GLTFLoadOptions struct to alter how the file is loaded. Passing nil for loadOptions will load the file using default load options. Unlike with DAE files, Animations (including armature-based animations) and Cameras (assuming they are exported in the GLTF file) will be parsed properly. LoadGLTFFile will return a Library, and an error if the process fails.

func NewLibrary

func NewLibrary() *Library

func (*Library) AddScene

func (lib *Library) AddScene(sceneName string) *Scene

func (*Library) FindNode

func (lib *Library) FindNode(objectName string) INode

FindNode allows you to find a node by name by searching through each of a Library's scenes. If the Node with the given name isn't found, FindNode will return nil.

func (*Library) FindScene

func (lib *Library) FindScene(name string) *Scene

FindScene searches all scenes in a Library to find the one with the provided name. If a scene with the given name isn't found, FindScene will return nil.

type Light

type Light interface {
	Light(triIndex int, model *Model) [9]float32 // Light() returns the R, G, and B colors used to light the vertices of the given triangle.
	// contains filtered or unexported methods
}

Light represents an interface that is fulfilled by an object that emits light, returning the color a vertex should be given that Vertex and its model matrix.

type Marker

type Marker struct {
	Time float64 // Time of the marker in seconds in the Animation.
	Name string  // Name of the marker.
}

Marker represents a tag as placed in an Animation in a 3D modeler.

type Material

type Material struct {
	Name              string               // Name is the name of the Material.
	Color             *Color               // The overall color of the Material.
	Texture           *ebiten.Image        // The texture applied to the Material.
	TexturePath       string               // The path to the texture, if it was not packed into the exporter.
	TextureFilterMode ebiten.Filter        // Texture filtering mode
	TextureWrapMode   ebiten.Address       // Texture wrapping mode
	Tags              *Tags                // Tags is a Tags object, allowing you to specify auxiliary data on the Material. This is loaded from GLTF files if / Blender's Custom Properties if the setting is enabled on the export menu.
	BackfaceCulling   bool                 // If backface culling is enabled (which it is by default), faces turned away from the camera aren't rendered.
	TriangleSortMode  int                  // TriangleSortMode influences how triangles with this Material are sorted.
	Shadeless         bool                 // If the material should be shadeless (unlit) or not
	CompositeMode     ebiten.CompositeMode // Blend mode to use when rendering the material (i.e. additive, multiplicative, etc)
	BillboardMode     int                  // Billboard mode

	// VertexTransformFunction is a function that runs on the world position of each vertex position rendered with the material.
	// It accepts the vertex position as an argument, along with the index of the vertex in the mesh.
	// One can use this to simply transform vertices of the mesh on CPU (note that this is, of course, not as performant as
	// a traditional GPU vertex shader, but is fine for simple / low-poly mesh transformations).
	// This function is run after skinning the vertex if the material belongs to a mesh that is skinned by an armature.
	// Note that the VertexTransformFunction must return the vector passed.
	VertexTransformFunction func(vertexPosition vector.Vector, vertexIndex int) vector.Vector

	// VertexClipFunction is a function that runs on the clipped result of each vertex position rendered with the material.
	// The function takes the vertex position along with the vertex index in the mesh.
	// This program runs after the vertex position is clipped to screen coordinates.
	// Note that the VertexClipFunction must return the vector passed.
	VertexClipFunction func(vertexPosition vector.Vector, vertexIndex int) vector.Vector

	// FragmentShaderOn is an easy boolean toggle to control whether the shader is activated or not (it defaults to on).
	FragmentShaderOn bool
	// FragmentShaderOptions allows you to customize the custom fragment shader with uniforms or images. It does NOT take the
	// CompositeMode property from the Material's CompositeMode. By default, it's an empty DrawTrianglesShaderOptions struct.
	FragmentShaderOptions *ebiten.DrawTrianglesShaderOptions

	// If a material is tagged as transparent, it's rendered in a separate render pass.
	// Objects with transparent materials don't render to the depth texture and are sorted and rendered back-to-front, AFTER
	// all non-transparent materials.
	TransparencyMode int
	// contains filtered or unexported fields
}

func NewMaterial

func NewMaterial(name string) *Material

NewMaterial creates a new Material with the name given.

func (*Material) Clone

func (material *Material) Clone() *Material

Clone creates a clone of the specified Material. Note that Clone() cannot clone the Material's fragment shader or shader options.

func (*Material) DisposeShader

func (material *Material) DisposeShader()

DisposeShader disposes the custom fragment Shader for the Material (assuming it has one). If it does not have a Shader, nothing happens.

func (*Material) Library

func (material *Material) Library() *Library

Library returns the Library from which this Material was loaded. If it was created through code, this function will return nil.

func (*Material) SetShader

func (material *Material) SetShader(src []byte) (*ebiten.Shader, error)

SetShader creates a new custom Kage fragment shader for the Material if provided the shader's source code, provided as a []byte. This custom shader would be used to render the mesh utilizing the material after rendering to the depth texture, but before compositing the finished render to the screen after fog. If the shader is nil, the Material will render using the default Tetra3D render setup (e.g. texture, UV values, vertex colors, and vertex lighting). SetShader will return the Shader, and an error if the Shader failed to compile.

func (*Material) Shader

func (material *Material) Shader() *ebiten.Shader

Shader returns the custom Kage fragment shader for the Material.

type Matrix4

type Matrix4 [4][4]float64

Matrix4 represents a 4x4 matrix for translation, scale, and rotation. A Matrix4 in Tetra3D is row-major (i.e. the X axis is matrix[0]).

func NewEmptyMatrix4

func NewEmptyMatrix4() Matrix4

func NewLookAtMatrix

func NewLookAtMatrix(target, center, up vector.Vector) Matrix4

NewLookAtMatrix generates a new Matrix4 to rotate an object to point towards another object. target is the target's world position, center is the world position of the object looking towards the target, and up is the upward vector ( usually +Y, or [0, 1, 0] ).

func NewMatrix4

func NewMatrix4() Matrix4

NewMatrix4 returns a new identity Matrix4. A Matrix4 in Tetra3D is row-major (i.e. the X axis for a rotation Matrix4 is matrix[0][0], matrix[0][1], matrix[0][2]).

func NewMatrix4Rotate

func NewMatrix4Rotate(x, y, z, angle float64) Matrix4

NewMatrix4Rotate returns a new Matrix4 designed to rotate by the angle given (in radians) along the axis given [x, y, z]. This rotation works as though you pierced the object utilizing the matrix through by the axis, and then rotated it counter-clockwise by the angle in radians.

func NewMatrix4RotateFromQuaternion

func NewMatrix4RotateFromQuaternion(quat *Quaternion) Matrix4

NewMatrix4RotateFromQuaternion, as might be expected, creates a rotation matrix from this Quaternion.

func NewMatrix4Scale

func NewMatrix4Scale(x, y, z float64) Matrix4

NewMatrix4Scale returns a new identity Matrix4, but with the scale components set as provided. 1, 1, 1 is the default.

func NewMatrix4Translate

func NewMatrix4Translate(x, y, z float64) Matrix4

NewMatrix4Scale returns a new identity Matrix4, but with the x, y, and z translation components set as provided.

func NewProjectionOrthographic

func NewProjectionOrthographic(near, far, right, left, top, bottom float64) Matrix4

NewProjectionOrthographic generates an orthographic frustum Matrix4. near and far are the near and far clipping plane. right, left, top, and bottom are the right, left, top, and bottom planes (usually 1 and -1 for right and left, and the aspect ratio of the window and negative for top and bottom). Generally, you won't need to use this directly.

func NewProjectionPerspective

func NewProjectionPerspective(fovy, near, far, viewWidth, viewHeight float64) Matrix4

NewProjectionPerspective generates a perspective frustum Matrix4. fovy is the vertical field of view in degrees, near and far are the near and far clipping plane, while viewWidth and viewHeight is the width and height of the backing texture / camera. Generally, you won't need to use this directly.

func (Matrix4) Add

func (matrix Matrix4) Add(other Matrix4) Matrix4

func (Matrix4) BlenderToTetra

func (matrix Matrix4) BlenderToTetra() Matrix4

BlenderToTetra returns a Matrix with the rows altered such that Blender's +Z is now Tetra's +Y and Blender's +Y is now Tetra's -Z.

func (*Matrix4) Clear

func (matrix *Matrix4) Clear()

func (Matrix4) Clone

func (matrix Matrix4) Clone() Matrix4

Clone clones the Matrix4, returning a new copy.

func (Matrix4) Column

func (matrix Matrix4) Column(columnIndex int) vector.Vector

Column returns the indiced column from the Matrix4 as a Vector.

func (Matrix4) Columns

func (matrix Matrix4) Columns() [][]float64

Columns returns the Matrix4 as a slice of []float64, in column-major order (so it's transposed from the row-major default).

func (Matrix4) Decompose

func (matrix Matrix4) Decompose() (vector.Vector, vector.Vector, Matrix4)

Decompose decomposes the Matrix4 and returns three components - the position (a 3D vector.Vector), scale (another 3D vector.Vector), and rotation (an AxisAngle) indicated by the Matrix4. Note that this is mainly used when loading a mesh from a 3D modeler - this being the case, it may not be the most precise, and negative scales are not supported.

func (Matrix4) Equals

func (matrix Matrix4) Equals(other Matrix4) bool

Equals returns true if the matrix equals the same values in the provided Other Matrix4.

func (Matrix4) Forward

func (matrix Matrix4) Forward() vector.Vector

Forward returns the forward rotational component of the Matrix4. For an identity matrix, this would be [0, 0, 1], or +Z (towards camera).

func (Matrix4) HasValidRotation

func (matrix Matrix4) HasValidRotation() bool

HasValidRotation returns if the first three vectors in the Matrix are non-zero

func (*Matrix4) Index

func (matrix *Matrix4) Index(index int) float64

func (Matrix4) Inverted

func (matrix Matrix4) Inverted() Matrix4

Inverted returns an inverted (reversed) clone of a Matrix4. See: https://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix

func (Matrix4) IsIdentity

func (matrix Matrix4) IsIdentity() bool

IsIdentity returns true if the matrix is an unmodified identity matrix.

func (Matrix4) IsZero

func (matrix Matrix4) IsZero() bool

IsZero returns true if the Matrix is zero'd out (all values are 0).

func (Matrix4) Mult

func (matrix Matrix4) Mult(other Matrix4) Matrix4

Mult multiplies a Matrix4 by another provided Matrix4 - this effectively combines them.

func (Matrix4) MultVec

func (matrix Matrix4) MultVec(vect vector.Vector) vector.Vector

MultVec multiplies the vector provided by the Matrix4, giving a vector that has been rotated, scaled, or translated as desired.

func (Matrix4) MultVecW

func (matrix Matrix4) MultVecW(vect vector.Vector) vector.Vector

MultVecW multiplies the vector provided by the Matrix4, including the fourth (W) component, giving a vector that has been rotated, scaled, or translated as desired.

func (Matrix4) Right

func (matrix Matrix4) Right() vector.Vector

Right returns the right-facing rotational component of the Matrix4. For an identity matrix, this would be [1, 0, 0], or +X.

func (Matrix4) Rotated

func (matrix Matrix4) Rotated(x, y, z, angle float64) Matrix4

Rotated returns a clone of the Matrix4 rotated along the local axis by the angle given (in radians). This rotation works as though you pierced the object through by the axis, and then rotated it counter-clockwise by the angle in radians. The axis is relative to any existing rotation contained in the matrix.

func (Matrix4) Row

func (matrix Matrix4) Row(rowIndex int) vector.Vector

Row returns the indiced row from the Matrix4 as a Vector.

func (Matrix4) ScaleByScalar

func (matrix Matrix4) ScaleByScalar(scalar float64) Matrix4

func (Matrix4) SetColumn

func (matrix Matrix4) SetColumn(columnIndex int, columnData vector.Vector) Matrix4

SetColumn returns a clone of the Matrix4 with the column in columnIndex set to the 4D vector passed.

func (Matrix4) SetRow

func (matrix Matrix4) SetRow(rowIndex int, vec vector.Vector) Matrix4

SetRow returns a clone of the Matrix4 with the row in rowIndex set to the 4D vector passed.

func (Matrix4) String

func (matrix Matrix4) String() string

func (Matrix4) Transposed

func (matrix Matrix4) Transposed() Matrix4

Transposed transposes a Matrix4, switching the Matrix from being Row Major to being Column Major. For orthonormalized Matrices (matrices that have rows that are normalized (having a length of 1), like rotation matrices), this is equivalent to inverting it.

func (Matrix4) Up

func (matrix Matrix4) Up() vector.Vector

Up returns the upward rotational component of the Matrix4. For an identity matrix, this would be [0, 1, 0], or +Y.

type Mesh

type Mesh struct {
	Name string

	MeshParts []*MeshPart // The various mesh parts (collections of triangles, rendered with a single material).
	Triangles []*Triangle // The various triangles composing the Mesh.

	VertexPositions []vector.Vector
	VertexNormals   []vector.Vector

	VertexUVs                []vector.Vector
	VertexColors             [][]*Color
	VertexActiveColorChannel []int
	VertexWeights            [][]float32
	VertexBones              [][]uint16
	VertexCount              int
	VertexMax                int

	VertexColorChannelNames map[string]int
	Dimensions              Dimensions

	Tags *Tags
	// contains filtered or unexported fields
}

Mesh represents a mesh that can be represented visually in different locations via Models. By default, a new Mesh has no MeshParts (so you would need to add one manually if you want to construct a Mesh via code).

func NewCube

func NewCube() *Mesh

NewCube creates a new Cube Mesh and gives it a new material (suitably named "Cube").

func NewMesh

func NewMesh(name string) *Mesh

NewMesh takes a name and a slice of *Vertex instances, and returns a new Mesh. If you provide *Vertex instances, the number must be divisible by 3, or NewMesh will panic.

func NewPlane

func NewPlane() *Mesh

NewPlane creates a new plane Mesh and gives it a new material (suitably named "Plane").

func NewWeirdDebuggingStatueThing

func NewWeirdDebuggingStatueThing() *Mesh

func (*Mesh) AddMeshPart

func (mesh *Mesh) AddMeshPart(material *Material) *MeshPart

AddMeshPart allows you to add a new MeshPart to the Mesh with the given Material (with a nil Material reference also being valid).

func (*Mesh) Clone

func (mesh *Mesh) Clone() *Mesh

Clone clones the Mesh, creating a new Mesh that has cloned MeshParts.

func (*Mesh) FindMeshPart

func (mesh *Mesh) FindMeshPart(materialName string) *MeshPart

FindMeshPart allows you to retrieve a MeshPart by its material's name. If no material with the provided name is given, the function returns nil.

func (*Mesh) GetVertexInfo

func (mesh *Mesh) GetVertexInfo(vertexIndex int) VertexInfo

GetVertexInfo returns a VertexInfo struct containing the vertex information for the vertex with the provided index.

func (*Mesh) Library

func (mesh *Mesh) Library() *Library

Library returns the Library from which this Mesh was loaded. If it was created through code, this function will return nil.

func (*Mesh) SelectVertices

func (mesh *Mesh) SelectVertices() *VertexSelection

SelectVertices generates a new vertex selection for the current Mesh.

func (*Mesh) UpdateBounds

func (mesh *Mesh) UpdateBounds()

UpdateBounds updates the mesh's dimensions; call this after manually changing vertex positions.

type MeshPart

type MeshPart struct {
	Mesh          *Mesh
	Material      *Material
	TriangleStart int
	TriangleEnd   int
	// contains filtered or unexported fields
}

MeshPart represents a collection of vertices and triangles, which are all rendered at once, as a single part, with a single material. Depth testing is done between mesh parts or objects, so splitting an object up into different materials can be effective to help with depth sorting.

func NewMeshPart

func NewMeshPart(mesh *Mesh, material *Material) *MeshPart

NewMeshPart creates a new MeshPart that renders using the specified Material.

func (*MeshPart) AddTriangles

func (part *MeshPart) AddTriangles(verts ...VertexInfo)

AddTriangles adds triangles to the MeshPart using the provided VertexInfo slice. Note that

func (*MeshPart) Clone

func (part *MeshPart) Clone() *MeshPart

Clone clones the MeshPart, returning the copy.

func (*MeshPart) TriangleCount

func (part *MeshPart) TriangleCount() int

TriangleCount returns the total number of triangles in the MeshPart, specifically.

type Model

type Model struct {
	*Node
	Mesh              *Mesh
	FrustumCulling    bool                                                 // Whether the Model is culled when it leaves the frustum.
	Color             *Color                                               // The overall multiplicative color of the Model.
	ColorBlendingFunc func(model *Model, meshPart *MeshPart) ebiten.ColorM // The blending function used to color the Model; by default, it basically modulates the model by the color.
	BoundingSphere    *BoundingSphere

	DynamicBatchModels []*Model // Models that are dynamically merged into this one.
	DynamicBatchOwner  *Model

	Skinned  bool  // If the model is skinned and this is enabled, the model will tranform its vertices to match the skinning armature (Model.SkinRoot).
	SkinRoot INode // The root node of the armature skinning this Model.
	// contains filtered or unexported fields
}

Model represents a singular visual instantiation of a Mesh. A Mesh contains the vertex information (what to draw); a Model references the Mesh to draw it with a specific Position, Rotation, and/or Scale (where and how to draw).

func NewModel

func NewModel(mesh *Mesh, name string) *Model

NewModel creates a new Model (or instance) of the Mesh and Name provided. A Model represents a singular visual instantiation of a Mesh.

func (*Model) AddChildren

func (model *Model) AddChildren(children ...INode)

AddChildren parents the provided children Nodes to the passed parent Node, inheriting its transformations and being under it in the scenegraph hierarchy. If the children are already parented to other Nodes, they are unparented before doing so.

func (*Model) Clone

func (model *Model) Clone() INode

Clone creates a clone of the Model.

func (*Model) DynamicBatchAdd

func (model *Model) DynamicBatchAdd(batchedModels ...*Model) error

DynamicBatchAdd adds the provided models to the calling Model's dynamic batch. Note that unlike StaticMerge(), DynamicBatchAdd works by simply rendering the batched models using the calling Model's first MeshPart's material. By dynamically batching models together, this allows us to not flush between rendering multiple Models, saving a lot of render time, particularly if rendering many low-poly, individual models that have very little variance (i.e. if they all share a single texture). For more information, see this Wiki page on batching / merging: https://github.com/xackery/tetra3d/wiki/Merging-and-Batching-Draw-Calls

func (*Model) DynamicBatchRemove

func (model *Model) DynamicBatchRemove(batched ...*Model)

DynamicBatchRemove removes the specified batched Models from the calling Model's dynamic batch slice.

func (*Model) DynamicBatchTriangleCount

func (model *Model) DynamicBatchTriangleCount() int

DynamicBatchTriangleCount returns the total number of triangles of Models in the calling Model's dynamic batch.

func (*Model) Merge

func (model *Model) Merge(models ...*Model)

Merge statically merges the provided models into the calling Model's mesh, such that their vertex properties (position, normal, UV, etc) are part of the calling Model's Mesh. You can use this to merge several objects initially dynamically placed into the calling Model's mesh, thereby pulling back to a single draw call. Note that models are merged into MeshParts (saving draw calls) based on maximum vertex count and shared materials (so to get any benefit from merging, ensure the merged models share materials; if they all have unique materials, they will be turned into individual MeshParts, thereby forcing multiple draw calls). Also note that as the name suggests, this is static merging, which means that after merging, the new vertices are static - part of the merging Model. For more information, see this Wiki page on batching / merging: https://github.com/xackery/tetra3d/wiki/Merging-and-Batching-Draw-Calls

func (*Model) ProcessVertices

func (model *Model) ProcessVertices(vpMatrix Matrix4, camera *Camera, meshPart *MeshPart, scene *Scene)

ProcessVertices processes the vertices a Model has in preparation for rendering, given a view-projection matrix, a camera, and the MeshPart being rendered.

func (*Model) ReassignBones

func (model *Model) ReassignBones(armatureRoot INode)

ReassignBones reassigns the model to point to a different armature. armatureNode should be a pointer to the starting object Node of the armature (not any of its bones).

func (*Model) Transform

func (model *Model) Transform() Matrix4

Transform returns the global transform of the Model, taking into account any transforms its parents or grandparents have that would impact the Model.

func (*Model) Type

func (model *Model) Type() NodeType

Type returns the NodeType for this object.

func (*Model) Unparent

func (model *Model) Unparent()

Unparent unparents the Model from its parent, removing it from the scenegraph.

type Node

type Node struct {
	// contains filtered or unexported fields
}

Node represents a minimal struct that fully implements the Node interface. Model and Camera embed Node into their structs to automatically easily implement Node.

func NewNode

func NewNode(name string) *Node

NewNode returns a new Node.

func (*Node) AddChildren

func (node *Node) AddChildren(children ...INode)

AddChildren parents the provided children Nodes to the passed parent Node, inheriting its transformations and being under it in the scenegraph hierarchy. If the children are already parented to other Nodes, they are unparented before doing so.

func (*Node) AnimationPlayer

func (node *Node) AnimationPlayer() *AnimationPlayer

AnimationPlayer returns the object's animation player - every object has an AnimationPlayer by default.

func (*Node) Children

func (node *Node) Children() NodeFilter

Children() returns the Node's children.

func (*Node) ChildrenRecursive

func (node *Node) ChildrenRecursive() NodeFilter

ChildrenRecursive() returns the Node's recursive children (i.e. children, grandchildren, etc) as a NodeFilter.

func (*Node) Clone

func (node *Node) Clone() INode

Clone returns a new Node.

func (*Node) Data

func (node *Node) Data() interface{}

Data returns a pointer to user-customizeable data that could be usefully stored on this node.

func (*Node) Get

func (node *Node) Get(path string) INode

Get searches a node's hierarchy using a string to find a specified node. The path is in the format of names of nodes, separated by forward slashes ('/'), and is relative to the node you use to call Get. As an example of Get, if you had a cup parented to a desk, which was parented to a room, that was finally parented to the root of the scene, it would be found at "Room/Desk/Cup". Note also that you can use "../" to "go up one" in the hierarchy (so cup.Get("../") would return the Desk node). Since Get uses forward slashes as path separation, it would be good to avoid using forward slashes in your Node names. Also note that Get() trims the extra spaces from the beginning and end of Node Names, so avoid using spaces at the beginning or end of your Nodes' names.

func (*Node) Grow

func (node *Node) Grow(x, y, z float64)

Grow scales the object additively (i.e. calling Node.Grow(1, 0, 0) will scale it +1 on the X-axis).

func (*Node) HierarchyAsString

func (node *Node) HierarchyAsString() string

HierarchyAsString returns a string displaying the hierarchy of this Node, and all recursive children. Nodes will have a "+" next to their name, Models an "M", and Cameras a "C". BoundingSpheres will have BS, BoundingAABB AABB, BoundingCapsule CAP, and BoundingTriangles TRI. Lights will have an L next to their name. This is a useful function to debug the layout of a node tree, for example.

func (*Node) IsBone

func (node *Node) IsBone() bool

IsBone returns if the Node is a "bone" (a node that was a part of an armature and so can play animations back to influence a skinned mesh).

func (*Node) Library

func (node *Node) Library() *Library

Library returns the Library from which this Node was instantiated. If it was created through code, this will be nil.

func (*Node) LocalPosition

func (node *Node) LocalPosition() vector.Vector

LocalPosition returns a 3D Vector consisting of the object's local position (position relative to its parent). If this object has no parent, the position will be relative to world origin (0, 0, 0).

func (*Node) LocalRotation

func (node *Node) LocalRotation() Matrix4

LocalRotation returns the object's local rotation Matrix4.

func (*Node) LocalScale

func (node *Node) LocalScale() vector.Vector

LocalScale returns the object's local scale (scale relative to its parent). If this object has no parent, the scale will be absolute.

func (*Node) Move

func (node *Node) Move(x, y, z float64)

Move moves a Node in local space by the x, y, and z values provided.

func (*Node) MoveVec

func (node *Node) MoveVec(vec vector.Vector)

MoveVec moves a Node in local space using the vector provided.

func (*Node) Name

func (node *Node) Name() string

Name returns the object's name.

func (*Node) Parent

func (node *Node) Parent() INode

Parent returns the Node's parent. If the Node has no parent, this will return nil.

func (*Node) Path

func (node *Node) Path() string

Path returns a string indicating the hierarchical path to get this Node from the root. The path returned will be absolute, such that passing it to Get() called on the scene root node will return this node. The path returned will not contain the root node's name ("Root").

func (*Node) RemoveChildren

func (node *Node) RemoveChildren(children ...INode)

RemoveChildren removes the provided children from this object.

func (*Node) ResetLocalTransform

func (node *Node) ResetLocalTransform()

ResetLocalTransform resets the local transform properties (position, scale, and rotation) for the Node. This can be useful because by default, when you parent one Node to another, the local transform properties (position, scale, and rotation) are altered to keep the object in the same absolute location, even though the origin changes.

func (*Node) Root

func (node *Node) Root() INode

Root returns the root node in this tree by recursively traversing this node's hierarchy of parents upwards.

func (*Node) Rotate

func (node *Node) Rotate(x, y, z, angle float64)

Rotate rotates a Node locally on the given vector, by the angle provided in radians.

func (*Node) Scene

func (node *Node) Scene() *Scene

Scene looks for the Node's parents recursively to return what scene it exists in. If the node is not within a tree (i.e. unparented), this will return nil.

func (*Node) SetData

func (node *Node) SetData(data interface{})

SetData sets user-customizeable data that could be usefully stored on this node.

func (*Node) SetLocalPosition

func (node *Node) SetLocalPosition(position vector.Vector)

SetLocalPosition sets the object's local position (position relative to its parent). If this object has no parent, the position should be relative to world origin (0, 0, 0). position should be a 3D vector (i.e. X, Y, and Z components).

func (*Node) SetLocalRotation

func (node *Node) SetLocalRotation(rotation Matrix4)

SetLocalRotation sets the object's local rotation Matrix4 (relative to any parent).

func (*Node) SetLocalScale

func (node *Node) SetLocalScale(scale vector.Vector)

SetLocalScale sets the object's local scale (scale relative to its parent). If this object has no parent, the scale would be absolute. scale should be a 3D vector (i.e. X, Y, and Z components).

func (*Node) SetName

func (node *Node) SetName(name string)

SetName sets the object's name.

func (*Node) SetVisible

func (node *Node) SetVisible(visible bool, recursive bool)

SetVisible sets the object's visibility. If recursive is true, all recursive children of this Node will have their visibility set the same way.

func (*Node) SetWorldPosition

func (node *Node) SetWorldPosition(position vector.Vector)

SetWorldPosition sets the object's world position (position relative to the world origin point of {0, 0, 0}). position needs to be a 3D vector (i.e. X, Y, and Z components).

func (*Node) SetWorldRotation

func (node *Node) SetWorldRotation(rotation Matrix4)

SetWorldRotation sets an object's rotation to the provided rotation Matrix4.

func (*Node) SetWorldScale

func (node *Node) SetWorldScale(scale vector.Vector)

SetWorldScale sets the object's absolute world scale. scale should be a 3D vector (i.e. X, Y, and Z components).

func (*Node) SetWorldTransform

func (node *Node) SetWorldTransform(transform Matrix4)

SetWorldTransform sets the Node's global (world) transform to the full 4x4 transformation matrix provided.

func (*Node) Tags

func (node *Node) Tags() *Tags

Tags represents an unordered set of string tags that can be used to identify this object.

func (*Node) Transform

func (node *Node) Transform() Matrix4

Transform returns a Matrix4 indicating the global position, rotation, and scale of the object, transforming it by any parents'. If there's no change between the previous Transform() call and this one, Transform() will return a cached version of the transform for efficiency.

func (*Node) Type

func (node *Node) Type() NodeType

Type returns the NodeType for this object.

func (*Node) Unparent

func (node *Node) Unparent()

Unparent unparents the Node from its parent, removing it from the scenegraph. Note that this needs to be overridden for objects that embed Node.

func (*Node) Visible

func (node *Node) Visible() bool

Visible returns whether the Object is visible.

func (*Node) WorldPosition

func (node *Node) WorldPosition() vector.Vector

WorldPosition returns a 3D Vector consisting of the object's world position (position relative to the world origin point of {0, 0, 0}).

func (*Node) WorldRotation

func (node *Node) WorldRotation() Matrix4

WorldRotation returns an absolute rotation Matrix4 representing the object's rotation.

func (*Node) WorldScale

func (node *Node) WorldScale() vector.Vector

WorldScale returns the object's absolute world scale as a 3D vector (i.e. X, Y, and Z components).

type NodeFilter

type NodeFilter []INode

NodeFilter represents a filterable selection of INodes. For example, ` filter := scene.Root.ChildrenRecursive()` returns a NodeFilter composed of all nodes underneath the root (excluding the root itself). From there, you can use additional functions on the NodeFilter to filter it down further: `filter = filter.ByName("player lamp", true).ByType(tetra3d.NodeTypeLight)`.

func (NodeFilter) AsBoundingObjects

func (nc NodeFilter) AsBoundingObjects() []BoundingObject

AsBoundingObjects returns the NodeFilter as a slice of BoundingObjects. This is particularly useful when you're using NodeFilters to filter down a selection of Nodes that you then need to pass into BoundingObject.CollisionTest().

func (NodeFilter) ByFunc

func (nf NodeFilter) ByFunc(filterFunc func(node INode) bool) NodeFilter

ByFunc allows you to filter a given selection of nodes by the provided filter function (which takes a Node and returns a boolean, indicating whether or not to add that Node to the resulting NodeFilter). If no matching Nodes are found, an empty NodeFilter is returned.

func (NodeFilter) ByName

func (nf NodeFilter) ByName(name string, exactMatch bool) NodeFilter

ByName allows you to filter a given selection of nodes by the given name. If wildcard is true, the nodes' names can contain the name provided; otherwise, they have to match exactly. If no matching Nodes are found, an empty NodeFilter is returned.

func (NodeFilter) ByTags

func (nf NodeFilter) ByTags(tagNames ...string) NodeFilter

ByTags allows you to filter a given selection of nodes by the provided set of tag names. If no matching Nodes are found, an empty NodeFilter is returned.

func (NodeFilter) ByType

func (nf NodeFilter) ByType(nodeType NodeType) NodeFilter

ByType allows you to filter a given selection of nodes by the provided NodeType. If no matching Nodes are found, an empty NodeFilter is returned.

func (NodeFilter) Children

func (nf NodeFilter) Children() NodeFilter

Children filters out a selection of Nodes, returning a NodeFilter composed strictly of that selection's children.

func (NodeFilter) ChildrenRecursive

func (nf NodeFilter) ChildrenRecursive() NodeFilter

ChildrenRecursive filters out a selection of Nodes, returning a NodeFilter composed strictly of that selection's recursive children.

func (NodeFilter) Empty

func (nf NodeFilter) Empty() bool

Empty returns true if the NodeFilter contains no Nodes.

func (NodeFilter) First

func (nf NodeFilter) First() INode

First returns the first Node in the NodeFilter; if the NodeFilter is empty, this function returns nil.

func (NodeFilter) Get

func (nf NodeFilter) Get(index int) INode

Get returns the Node at the given index in the NodeFilter; if index is invalid (<0 or >= len(nodes)), this function returns nil.

func (NodeFilter) Last

func (nf NodeFilter) Last() INode

First returns the last Node in the NodeFilter; if the NodeFilter is empty, this function returns nil.

type NodeType

type NodeType string

NodeType represents a Node's type. Node types are categorized, and can be said to extend or "be of" more general types. For example, a BoundingSphere has a type of NodeTypeBoundingSphere. That type can also be said to be NodeTypeBoundingObject (because it is a bounding object). However, it is not of type NodeTypeBoundingTriangles, as that is a different category.

const (
	NodeTypeNode   NodeType = "Node"       // NodeTypeNode represents any generic node
	NodeTypeModel  NodeType = "NodeModel"  // NodeTypeModel represents specifically a Model
	NodeTypeCamera NodeType = "NodeCamera" // NodeTypeCamera represents specifically a Camera
	NodeTypePath   NodeType = "NodePath"   // NodeTypePath represents specifically a Path

	NodeTypeBoundingObject    NodeType = "NodeBounding"          // NodeTypeBoundingObject represents any generic bounding object
	NodeTypeBoundingAABB      NodeType = "NodeBoundingAABB"      // NodeTypeBoundingAABB represents specifically a BoundingAABB
	NodeTypeBoundingCapsule   NodeType = "NodeBoundingCapsule"   // NodeTypeBoundingCapsule represents specifically a BoundingCapsule
	NodeTypeBoundingTriangles NodeType = "NodeBoundingTriangles" // NodeTypeBoundingTriangles represents specifically a BoundingTriangles object
	NodeTypeBoundingSphere    NodeType = "NodeBoundingSphere"    // NodeTypeBoundingSphere represents specifically a BoundingSphere BoundingObject

	NodeTypeLight            NodeType = "NodeLight"            // NodeTypeLight represents any generic light
	NodeTypeAmbientLight     NodeType = "NodeLightAmbient"     // NodeTypeAmbientLight represents specifically an ambient light
	NodeTypePointLight       NodeType = "NodeLightPoint"       // NodeTypePointLight represents specifically a point light
	NodeTypeDirectionalLight NodeType = "NodeLightDirectional" // NodeTypeDirectionalLight represents specifically a directional (sun) light
)

func (NodeType) Is

func (nt NodeType) Is(other NodeType) bool

Is returns true if a NodeType satisfies another NodeType category. A specific node type can be said to contain a more general one, but not vice-versa. For example, a Model (which has type NodeTypeModel) can be said to be a Node (NodeTypeNode), but the reverse is not true (a NodeTypeNode is not a NodeTypeModel).

type Path

type Path struct {
	*Node
	Closed bool // Closed indicates if a Path is closed (and so going to the end will return to the start) or not.
}

A Path represents a Node that represents a sequential path. All children of the Path are considered its points, in order.

func NewPath

func NewPath(name string, points ...vector.Vector) *Path

NewPath returns a new Path object. A Path is a Node whose children represent points on a path. A Path can be stepped through spatially using a PathFollower. The passed point vectors will become Nodes, children of the Path.

func (*Path) AddChildren

func (path *Path) AddChildren(children ...INode)

AddChildren parents the provided children Nodes to the passed parent Node, inheriting its transformations and being under it in the scenegraph hierarchy. If the children are already parented to other Nodes, they are unparented before doing so.

func (*Path) Clone

func (path *Path) Clone() INode

Clone creates a clone of the Path and its points.

func (*Path) Distance

func (path *Path) Distance() float64

Distance returns the total distance that a Path covers by stepping through all of the children under the Path.

func (*Path) Type

func (path *Path) Type() NodeType

Type returns the NodeType for this object.

func (*Path) Unparent

func (path *Path) Unparent()

Unparent unparents the Path from its parent, removing it from the scenegraph.

type PathFollower

type PathFollower struct {
	Percentage float64 // Percentage is how far along the Path the PathFollower is, ranging from 0 to 1.
	FinishMode int     // FinishMode indicates what should happen when the PathFollower finishes running across the given Path.
	Direction  int     // Direction indicates the playback direction.
	Path       *Path   // A Reference to the Path
	OnFinish   func()
	// contains filtered or unexported fields
}

PathFollower follows a Path, stepping through the Path spatially to completion. You can use this to make objects that follow a path's positions in space.

func NewPathFollower

func NewPathFollower(path *Path) *PathFollower

NewPathFollower returns a new PathFollower object.

func (*PathFollower) AdvanceDistance

func (follower *PathFollower) AdvanceDistance(distance float64)

AdvanceDistance advances the PathFollower by a certain distance in absolute movement units on the path.

func (*PathFollower) AdvancePercentage

func (follower *PathFollower) AdvancePercentage(percentage float64)

AdvancePercentage advances the PathFollower by a certain percentage of the path. This being a percentage, the larger the path, the further in space a percentage advances the PathFollower.

func (*PathFollower) Clone

func (follower *PathFollower) Clone() *PathFollower

Clone returns a clone of this PathFollower.

func (*PathFollower) Index

func (follower *PathFollower) Index() int

Index returns the index of the point / child that the PathFollower is on.

func (*PathFollower) WorldPosition

func (follower *PathFollower) WorldPosition() vector.Vector

WorldPosition returns the position of the PathFollower in world space.

type PointLight

type PointLight struct {
	*Node
	// Distance represents the distance after which the light fully attenuates. If this is 0 (the default),
	// it falls off using something akin to the inverse square law.
	Distance float64
	// Color is the color of the PointLight.
	Color *Color
	// Energy is the overall energy of the Light, with 1.0 being full brightness. Internally, technically there's no
	// difference between a brighter color and a higher energy, but this is here for convenience / adherance to the
	// GLTF spec and 3D modelers.
	Energy float32
	// If the light is on and contributing to the scene.
	On bool
	// contains filtered or unexported fields
}

PointLight represents a point light (naturally).

func NewPointLight

func NewPointLight(name string, r, g, b, energy float32) *PointLight

NewPointLight creates a new Point light.

func (*PointLight) AddChildren

func (point *PointLight) AddChildren(children ...INode)

AddChildren parents the provided children Nodes to the passed parent Node, inheriting its transformations and being under it in the scenegraph hierarchy. If the children are already parented to other Nodes, they are unparented before doing so.

func (*PointLight) Clone

func (point *PointLight) Clone() INode

Clone returns a new clone of the given point light.

func (*PointLight) Light

func (point *PointLight) Light(triIndex int, model *Model) [9]float32

Light returns the R, G, and B values for the PointLight for all vertices of a given Triangle.

func (*PointLight) Type

func (point *PointLight) Type() NodeType

Type returns the NodeType for this object.

func (*PointLight) Unparent

func (point *PointLight) Unparent()

Unparent unparents the PointLight from its parent, removing it from the scenegraph.

type Quaternion

type Quaternion struct {
	X, Y, Z, W float64
}

func NewQuaternion

func NewQuaternion(x, y, z, w float64) *Quaternion

func (*Quaternion) Clone

func (quat *Quaternion) Clone() *Quaternion

func (*Quaternion) Dot

func (quat *Quaternion) Dot(other *Quaternion) float64

func (*Quaternion) Lerp

func (quat *Quaternion) Lerp(end *Quaternion, percent float64) *Quaternion

func (*Quaternion) Magnitude

func (quat *Quaternion) Magnitude() float64

func (*Quaternion) Negated

func (quat *Quaternion) Negated() *Quaternion

func (*Quaternion) Normalized

func (quat *Quaternion) Normalized() *Quaternion

type Scene

type Scene struct {
	Name string // The name of the Scene. Set automatically to the scene name in your 3D modeler if the DAE file exports it.

	// Root indicates the root node for the scene hierarchy. For visual Models to be displayed, they must be added to the
	// scene graph by simply adding them into the tree via parenting anywhere under the Root. For them to be removed from rendering,
	// they simply need to be removed from the tree.
	// See this page for more information on how a scene graph works: https://webglfundamentals.org/webgl/lessons/webgl-scene-graph.html
	Root       INode
	ClearColor *Color // The clear color of the screen; note that this doesn't clear the color of the camera buffer or screen automatically;
	// this is just what the color is if the scene was exported using the Tetra3D addon from Blender. It's up to you as to how you'd like to
	// use it.
	FogColor *Color  // The Color of any fog present in the Scene.
	FogMode  FogMode // The FogMode, indicating how the fog color is blended if it's on (not FogOff).
	// FogRange is the depth range at which the fog is active. FogRange consists of two numbers,
	// ranging from 0 to 1. The first indicates the start of the fog, and the second the end, in
	// terms of total depth of the near / far clipping plane. The default is [0, 1].
	FogRange   []float32
	LightingOn bool // If lighting is enabled when rendering the scene.
	// contains filtered or unexported fields
}

Scene represents a world of sorts, and can contain a variety of Meshes and Nodes, which organize the scene into a graph of parents and children. Models (visual instances of Meshes), Cameras, and "empty" NodeBases all are kinds of Nodes.

func NewScene

func NewScene(name string) *Scene

NewScene creates a new Scene by the name given.

func (*Scene) Clone

func (scene *Scene) Clone() *Scene

Clone clones the Scene, returning a copy. Models and Meshes are shared between them.

func (*Scene) Library

func (scene *Scene) Library() *Library

Library returns the Library from which this Scene was loaded. If it was created through code and not associated with a Library, this function will return nil.

type Tags

type Tags struct {
	// contains filtered or unexported fields
}

Tags is an unordered set of string tags to values, representing a means of identifying Nodes or carrying data on Nodes.

func NewTags

func NewTags() *Tags

NewTags returns a new Tags object.

func (*Tags) Clear

func (tags *Tags) Clear()

Clear clears the Tags object of all tags.

func (*Tags) Clone

func (tags *Tags) Clone() *Tags

func (*Tags) Get

func (tags *Tags) Get(tagName string) interface{}

Get returns the value associated with the specified tag (key). Note that this does not sanity check to ensure the tag exists first.

func (*Tags) GetAsFloat

func (tags *Tags) GetAsFloat(tagName string) float64

GetAsFloat returns the value associated with the specified tag (key) as a float. Note that this does not sanity check to ensure the tag exists first.

func (*Tags) GetAsInt

func (tags *Tags) GetAsInt(tagName string) int

GetAsInt returns the value associated with the specified tag (key) as a float. Note that this does not sanity check to ensure the tag exists first.

func (*Tags) GetAsString

func (tags *Tags) GetAsString(tagName string) string

GetAsString returns the value associated with the specified tag (key) as a string. Note that this does not sanity check to ensure the tag exists first.

func (*Tags) Has

func (tags *Tags) Has(nodeTags ...string) bool

Has returns true if the Tags object has all of the tags specified, and false otherwise.

func (*Tags) IsFloat

func (tags *Tags) IsFloat(tagName string) bool

IsFloat returns true if the value associated with the specified tag is a float64. If the tag doesn't exist, this returns false.

func (*Tags) IsInt

func (tags *Tags) IsInt(tagName string) bool

IsInt returns true if the value associated with the specified tag is a float64. If the tag doesn't exist, this returns false.

func (*Tags) IsString

func (tags *Tags) IsString(tagName string) bool

IsString returns true if the value associated with the specified tag is a string. If the tag doesn't exist, this returns false.

func (*Tags) Remove

func (tags *Tags) Remove(tag string)

Remove removes the tag specified from the Tags object.

func (*Tags) Set

func (tags *Tags) Set(tagName string, value interface{})

Set sets all the tag specified to the Tags object.

type TextureAnimation

type TextureAnimation struct {
	FPS    float64         // The playback frame per second (or FPS) of the animation
	Frames []vector.Vector // A slice of vectors, with each indicating the offset of the frame from the original position for the mesh.
}

TextureAnimation is an animation struct. The TextureAnimation.Frames value is a []vector.Vector, with each Vector representing a frame of the animation (and the offset from the original, base position for all animated vertices).

func NewTextureAnimationPixels

func NewTextureAnimationPixels(fps float64, image *ebiten.Image, framePositions ...float64) *TextureAnimation

NewTextureAnimationPixels creates a new TextureAnimation using pixel positions instead of UV values. fps is the frames per second for the animation. image is the source texture used, and framePositions are the positions in pixels for each frame (i.e. 32, 32 instead of 0.25, 0.25 on a 128x128 spritesheet). NewTextureAnimationInPixels will panic if given less than 2 values for framePositions, or if it's an odd number of values (i.e. an X value for a frame, but no matching Y Value).

type TexturePlayer

type TexturePlayer struct {
	OriginalOffsets map[int]vector.Vector // OriginalOffsets is a map of vertex indices to their base UV offsets. All animating happens relative to these values.
	Animation       *TextureAnimation     // Animation is a pointer to the currently playing Animation.
	// Playhead increases as the TexturePlayer plays. The integer portion of Playhead is the frame that the TexturePlayer
	// resides in (so a Playhead of 1.2 indicates that it is in frame 1, the second frame).
	Playhead float64
	Speed    float64 // Speed indicates the playback speed and direction of the TexturePlayer, with a value of 1.0 being 100%.
	Playing  bool    // Playing indicates whether the TexturePlayer is currently playing or not.

	Mesh *Mesh
}

TexturePlayer is a struct that allows you to animate a collection of vertices' UV values using a TextureAnimation.

func NewTexturePlayer

func NewTexturePlayer(mesh *Mesh, vertexSelection *VertexSelection) *TexturePlayer

NewTexturePlayer returns a new TexturePlayer instance.

func (*TexturePlayer) ApplyUVOffset

func (player *TexturePlayer) ApplyUVOffset(offsetX, offsetY float64)

ApplyUVOffset applies a specified UV offset to all vertices a player is assigned to. This offset is not additive, but rather is set once, regardless of how many times ApplyUVOffset is called.

func (*TexturePlayer) Play

func (player *TexturePlayer) Play(animation *TextureAnimation)

Play plays the passed TextureAnimation, resetting the playhead if the TexturePlayer is not playing an animation. If the player is not playing, it will begin playing.

func (*TexturePlayer) Reset

func (player *TexturePlayer) Reset(vertexSelection *VertexSelection)

Reset resets a TexturePlayer to be ready to run on a new selection of vertices. Note that this also resets the base UV offsets to use the current values of the passed vertices in the slice.

func (*TexturePlayer) Update

func (player *TexturePlayer) Update(dt float64)

Update updates the TexturePlayer, using the passed delta time variable to animate the TexturePlayer's vertices.

type Triangle

type Triangle struct {
	ID int // Unique identifier number (index) in the Mesh. You can use the ID to find a triangle's vertices
	// using the formula: Mesh.VertexPositions[TriangleIndex*3+i], with i being the index of the vertex in the triangle
	// (so either 0, 1, or 2).
	MaxSpan  float64       // The maximum span from corner to corner of the triangle's dimensions; this is used in intersection testing.
	Center   vector.Vector // The untransformed center of the Triangle.
	Normal   vector.Vector // The physical normal of the triangle (i.e. the direction the triangle is facing). This is different from the visual normals of a triangle's vertices (i.e. a selection of vertices can have inverted normals to be see through, for example).
	MeshPart *MeshPart     // The specific MeshPart this Triangle belongs to.
}

A Triangle represents the smallest renderable object in Tetra3D. A triangle contains very little data, and is mainly used to help identify triads of vertices.

func NewTriangle

func NewTriangle(meshPart *MeshPart, id int) *Triangle

NewTriangle creates a new Triangle, and requires a reference to its owning MeshPart, along with its id within that MeshPart.

func (*Triangle) Clone

func (tri *Triangle) Clone() *Triangle

Clone clones the Triangle, keeping a reference to the same Material.

func (*Triangle) RecalculateCenter

func (tri *Triangle) RecalculateCenter()

RecalculateCenter recalculates the center for the Triangle. Note that this should only be called if you manually change a vertex's individual position.

func (*Triangle) RecalculateNormal

func (tri *Triangle) RecalculateNormal()

RecalculateNormal recalculates the physical normal for the Triangle. Note that this should only be called if you manually change a vertex's individual position. Also note that vertex normals (visual normals) are automatically set when loading Meshes from model files.

type VectorPool

type VectorPool struct {
	Vectors        []vector.Vector
	RetrievalIndex int
}

func NewVectorPool

func NewVectorPool(vectorCount int) *VectorPool

func (*VectorPool) Add

func (pool *VectorPool) Add(v0, v1 vector.Vector) vector.Vector

func (*VectorPool) Cross

func (pool *VectorPool) Cross(v0, v1 vector.Vector) vector.Vector

func (*VectorPool) Get

func (pool *VectorPool) Get() vector.Vector

func (*VectorPool) MultVec

func (pool *VectorPool) MultVec(matrix Matrix4, vect vector.Vector) vector.Vector

func (*VectorPool) MultVecW

func (pool *VectorPool) MultVecW(matrix Matrix4, vect vector.Vector) vector.Vector

func (*VectorPool) Reset

func (pool *VectorPool) Reset()

func (*VectorPool) Sub

func (pool *VectorPool) Sub(v0, v1 vector.Vector) vector.Vector

type VertexInfo

type VertexInfo struct {
	ID                        int
	X, Y, Z                   float64
	U, V                      float64
	NormalX, NormalY, NormalZ float64
	Weights                   []float32
	Colors                    []*Color
	ActiveColorChannel        int
	Bones                     []uint16
}

func NewVertex

func NewVertex(x, y, z, u, v float64) VertexInfo

NewVertex creates a new vertex information struct, which is used to create new Triangles. VertexInfo is purely for getting data into Meshes' vertex buffers, so after creating the Triangle, VertexInfos can be safely discarded (i.e. the VertexInfo doesn't hold "power" over the vertex it represents after creation).

type VertexSelection

type VertexSelection struct {
	Indices map[int]bool
	Mesh    *Mesh
}

VertexSelection represents a selection of vertices on a Mesh.

func NewVertexSelection

func NewVertexSelection(mesh *Mesh) *VertexSelection

NewVertexSelection creates a new VertexSelection instance for the specified Mesh.

func (*VertexSelection) ApplyMatrix

func (vs *VertexSelection) ApplyMatrix(matrix Matrix4)

ApplyMatrix applies a Matrix4 to the position of all vertices contained within the VertexSelection.

func (*VertexSelection) Move

func (vs *VertexSelection) Move(x, y, z float64)

Move moves all vertices contained within the VertexSelection by the provided x, y, and z values.

func (*VertexSelection) MoveVec

func (vs *VertexSelection) MoveVec(vec vector.Vector)

Move moves all vertices contained within the VertexSelection by the provided 3D vector.

func (*VertexSelection) SelectAll

func (vs *VertexSelection) SelectAll() *VertexSelection

SelectAll selects all vertices on the source Mesh.

func (*VertexSelection) SelectColorInChannel

func (vs *VertexSelection) SelectColorInChannel(channelName string) *VertexSelection

SelectColorInChannel selects all vertices in the Mesh that have a non-pure black color in a color channel with the specified name.

func (*VertexSelection) SelectMeshPart

func (vs *VertexSelection) SelectMeshPart(meshPart *MeshPart) *VertexSelection

SelectMeshPart selects all vertices in the Mesh belonging to the specified MeshPart.

func (*VertexSelection) SetActiveColorChannel

func (vs *VertexSelection) SetActiveColorChannel(channelName string)

SetActiveColorChannel sets the active color channel in all vertices contained within the VertexSelection to the named channel.

func (*VertexSelection) SetColor

func (vs *VertexSelection) SetColor(channelName string, color *Color)

SetColor sets the color of the specified channel in all vertices contained within the VertexSelection to the provided Color.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL