Merge branch 'develop' into mod

This commit is contained in:
davidmarr 2024-12-07 08:37:39 +01:00
commit f978ad1b53
48 changed files with 611 additions and 3013 deletions

View file

@ -6,15 +6,18 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
## Version 1.6 - xxxx-xx-xx
### Bug fixes
* Fixed engine performance around bridges.
* Fixed engine performance if weather or bubble effects are active.
* Significantly improved renderer performance.
* Improved engine performance around bridges.
* Improved engine performance if weather or bubble effects are active.
* Fixed silent crashes if loaded level is corrupted or in incorrect format.
* Fixed occasional crashes if there are static meshes placed within room border walls.
* Fixed incorrect clipping of scaled off-centered static meshes.
* Fixed incorrect collision detection for off-centered moveables.
* Fixed incorrect slide directions for sub-click geometry.
* Fixed stutter during jumps between cameras in a flyby sequence.
* Fixed uzi targeting issues after using flycheat.
* Fixed snow particles not always melting on the ground.
* Fixed enemies not damaging Lara if she is staying on the sector where enemies were triggered.
* Fixed enemy pickups dropping on death sectors.
* Fixed Sarcophagus and Search Object pickup triggers.
* Fixed vehicle transfer not happening for levels which were not previously visited.
@ -30,6 +33,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fixed original issue with deactivation of Dart Emitter.
* Fixed Lens Flare object not functioning properly.
* Fixed lens flares not being occluded by static meshes and moveables.
* Fixed spotlight shadows.
* Fixed Skeleton and Mummy not reacting to shotgun hits.
### New Features
@ -43,14 +47,20 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Added Moveable:GetCollidable() and Moveable:SetCollidable() functions.
* Added Flow.GetFreezeMode() and Flow.SetFreezeMode() functions.
* Added Flow.GetNextLevel() function to get script entry for incoming level, if it's about to start.
* Added Effects.EmitSpotLight() function for directional spotlights.
* Added optional cast shadow and name parameters for Effects.EmitLight() function.
* Added Effects.GetWind() function to get current wind speed vector.
* Added Rotation:Direction() method to get directional vector.
* Added support for transparency value in DisplayString class.
* Added extra argument for SetAmbientTrack() function to specify if new ambient track should play from the beginning.
* Use load camera instead of load screen by playing fixed camera from OnEnd() event and removing loadScreenFile field from level's gameflow entry.
* Fixed DisplayString class not supporting some Unicode characters and empty lines in multiline strings.
* Fixed DisplayString not being deallocated after showing.
* Fixed incorrect behaviour of Moveable:GetJointRotation() function.
* Fixed incorrect behaviour of Logic.EnableEvent() and Logic.DisableEvent() functions.
* Fixed Util.HasLineOfSight() not taking static meshes into consideration.
* Fixed collision callbacks not properly clearing after leveljump.
* Fixed SetIntroImagePath() not using the correct path
## [Version 1.5](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.7.2) - 2024-11-03

View file

@ -1,8 +1,11 @@
@echo off
setlocal
set DOC_DIR=.\doc
set LDOC_DIR=.\compiler\ldoc
set LUA_PATH=.\compiler\?.lua
set LUA_CPATH=.\compiler\?.dll
rmdir /s /q %DOC_DIR%
mkdir %DOC_DIR%
.\compiler\lua.exe %LDOC_DIR%\\ldoc.lua %*
del output.xml
exit /b %ERRORLEVEL%

View file

@ -125,10 +125,14 @@
<td class="summary">Emit a shockwave, similar to that seen when a harpy projectile hits something.</td>
</tr>
<tr>
<td class="name" ><a href="#EmitLight">EmitLight(pos, color, radius)</a></td>
<td class="name" ><a href="#EmitLight">EmitLight(pos[, color][, radius][, shadows][, name])</a></td>
<td class="summary">Emit dynamic light that lasts for a single frame.</td>
</tr>
<tr>
<td class="name" ><a href="#EmitSpotLight">EmitSpotLight(pos, dir[, color][, radius][, falloff][, distance][, shadows][, name])</a></td>
<td class="summary">Emit dynamic directional spotlight that lasts for a single frame.</td>
</tr>
<tr>
<td class="name" ><a href="#EmitBlood">EmitBlood(pos, count)</a></td>
<td class="summary">Emit blood.</td>
</tr>
@ -363,7 +367,7 @@
</dd>
<dt>
<a name = "EmitLight"></a>
<strong>EmitLight(pos, color, radius)</strong>
<strong>EmitLight(pos[, color][, radius][, shadows][, name])</strong>
</dt>
<dd>
Emit dynamic light that lasts for a single frame.
@ -375,17 +379,84 @@
<ul>
<li><span class="parameter">pos</span>
<span class="types"><a class="type" href="../3 primitive classes/Vec3.html#">Vec3</a></span>
position of the light
</li>
<li><span class="parameter">color</span>
<span class="types"><a class="type" href="../3 primitive classes/Color.html#">Color</a></span>
light color (default Color(255, 255, 255))
(<em>optional</em>)
</li>
<li><span class="parameter">radius</span>
<span class="types"><span class="type">int</span></span>
measured in "clicks" or 256 world units (default 20)
(<em>optional</em>)
</li>
<li><span class="parameter">shadows</span>
<span class="types"><span class="type">bool</span></span>
determines whether light should generate dynamic shadows for applicable moveables (default is false)
(<em>optional</em>)
</li>
<li><span class="parameter">name</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
if provided, engine will interpolate this light for high framerate mode (be careful not to use same name for different lights)
(<em>optional</em>)
</li>
</ul>
</dd>
<dt>
<a name = "EmitSpotLight"></a>
<strong>EmitSpotLight(pos, dir[, color][, radius][, falloff][, distance][, shadows][, name])</strong>
</dt>
<dd>
Emit dynamic directional spotlight that lasts for a single frame.
If you want a light that sticks around, you must call this each frame.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">pos</span>
<span class="types"><a class="type" href="../3 primitive classes/Vec3.html#">Vec3</a></span>
position of the light
</li>
<li><span class="parameter">dir</span>
<span class="types"><a class="type" href="../3 primitive classes/Vec3.html#">Vec3</a></span>
direction, or a point to which spotlight should be directed to
</li>
<li><span class="parameter">color</span>
<span class="types"><a class="type" href="../3 primitive classes/Color.html#">Color</a></span>
(default Color(255, 255, 255))
(<em>optional</em>)
</li>
<li><span class="parameter">radius</span>
<span class="types"><span class="type">int</span></span>
(default 20) corresponds loosely to both intensity and range
overall radius at the endpoint of a light cone, measured in "clicks" or 256 world units (default 10)
(<em>optional</em>)
</li>
<li><span class="parameter">falloff</span>
<span class="types"><span class="type">int</span></span>
radius, at which light starts to fade out, measured in "clicks" (default 5)
(<em>optional</em>)
</li>
<li><span class="parameter">distance</span>
<span class="types"><span class="type">int</span></span>
distance, at which light cone fades out, measured in "clicks" (default 20)
(<em>optional</em>)
</li>
<li><span class="parameter">shadows</span>
<span class="types"><span class="type">bool</span></span>
determines whether light should generate dynamic shadows for applicable moveables (default is false)
(<em>optional</em>)
</li>
<li><span class="parameter">name</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
if provided, engine will interpolate this light for high framerate mode (be careful not to use same name for different lights)
(<em>optional</em>)
</li>
</ul>

File diff suppressed because it is too large Load diff

View file

@ -160,7 +160,7 @@ Default: nil (i.e. infinite)
should be string automatically deleted after timeout is reached.
If not given, the string will remain allocated even after timeout is reached, and can be
shown again without re-initialization.
Default: false
Default: true
</li>
</ul>

View file

@ -1,529 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>TombEngine</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>1 Modules</h2>
<ul class="nowrap">
<li> <a href="../1 modules/Effects.html">Effects</a></li>
<li> <a href="../1 modules/Flow.html">Flow</a></li>
<li> <a href="../1 modules/Input.html">Input</a></li>
<li> <a href="../1 modules/Inventory.html">Inventory</a></li>
<li> <a href="../1 modules/Logic.html">Logic</a></li>
<li> <a href="../1 modules/Objects.html">Objects</a></li>
<li> <a href="../1 modules/Sound.html">Sound</a></li>
<li> <a href="../1 modules/Strings.html">Strings</a></li>
<li> <a href="../1 modules/Util.html">Util</a></li>
<li> <a href="../1 modules/View.html">View</a></li>
</ul>
<h2>2 Classes</h2>
<ul class="nowrap">
<li> <here>DisplaySprite</here></li>
<li> <a href="../2 classes/Flow.Animations.html">Flow.Animations</a></li>
<li> <a href="../2 classes/Flow.Fog.html">Flow.Fog</a></li>
<li> <a href="../2 classes/Flow.InventoryItem.html">Flow.InventoryItem</a></li>
<li> <a href="../2 classes/Flow.Level.html">Flow.Level</a></li>
<li> <a href="../2 classes/Flow.Mirror.html">Flow.Mirror</a></li>
<li> <a href="../2 classes/Flow.Settings.html">Flow.Settings</a></li>
<li> <a href="../2 classes/Flow.SkyLayer.html">Flow.SkyLayer</a></li>
<li> <a href="../2 classes/Objects.AIObject.html">Objects.AIObject</a></li>
<li> <a href="../2 classes/Objects.Camera.html">Objects.Camera</a></li>
<li> <a href="../2 classes/Objects.LaraObject.html">Objects.LaraObject</a></li>
<li> <a href="../2 classes/Objects.Moveable.html">Objects.Moveable</a></li>
<li> <a href="../2 classes/Objects.Room.html">Objects.Room</a></li>
<li> <a href="../2 classes/Objects.Sink.html">Objects.Sink</a></li>
<li> <a href="../2 classes/Objects.SoundSource.html">Objects.SoundSource</a></li>
<li> <a href="../2 classes/Objects.Static.html">Objects.Static</a></li>
<li> <a href="../2 classes/Objects.Volume.html">Objects.Volume</a></li>
<li> <a href="../2 classes/Strings.DisplayString.html">Strings.DisplayString</a></li>
</ul>
<h2>3 Primitive Classes</h2>
<ul class="nowrap">
<li> <a href="../3 primitive classes/Color.html">Color</a></li>
<li> <a href="../3 primitive classes/Rotation.html">Rotation</a></li>
<li> <a href="../3 primitive classes/Vec2.html">Vec2</a></li>
<li> <a href="../3 primitive classes/Vec3.html">Vec3</a></li>
</ul>
<h2>4 Enums</h2>
<ul class="nowrap">
<li> <a href="../4 enums/DisplaySprite.AlignMode.html">DisplaySprite.AlignMode</a></li>
<li> <a href="../4 enums/DisplaySprite.ScaleMode.html">DisplaySprite.ScaleMode</a></li>
<li> <a href="../4 enums/Effects.BlendID.html">Effects.BlendID</a></li>
<li> <a href="../4 enums/Effects.EffectID.html">Effects.EffectID</a></li>
<li> <a href="../4 enums/Input.ActionID.html">Input.ActionID</a></li>
<li> <a href="../4 enums/Objects.AmmoType.html">Objects.AmmoType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
<li> <a href="../4 enums/Sound.SoundTrackType.html">Sound.SoundTrackType</a></li>
<li> <a href="../4 enums/Util.LogLevel.html">Util.LogLevel</a></li>
<li> <a href="../4 enums/View.CameraType.html">View.CameraType</a></li>
</ul>
<h2>5 Lua utility modules</h2>
<ul class="nowrap">
<li> <a href="../5 lua utility modules/EventSequence.html">EventSequence</a></li>
<li> <a href="../5 lua utility modules/Timer.html">Timer</a></li>
</ul>
</div>
<div id="content">
<h1>Class <code>DisplaySprite</code></h1>
<p>Represents a screen-space display sprite.</p>
<p>
</p>
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" ><a href="#DisplaySprite">DisplaySprite(ID, int, pos, rot, scale[, color])</a></td>
<td class="summary">Create a DisplaySprite object.</td>
</tr>
<tr>
<td class="name" ><a href="#DisplaySprite:GetObjectID">DisplaySprite:GetObjectID()</a></td>
<td class="summary">Get the object ID of the sprite sequence object used by the display sprite.</td>
</tr>
<tr>
<td class="name" ><a href="#DisplaySprite:GetSpriteID">DisplaySprite:GetSpriteID()</a></td>
<td class="summary">Get the sprite ID in the sprite sequence object used by the display sprite.</td>
</tr>
<tr>
<td class="name" ><a href="#DisplaySprite:GetPosition">DisplaySprite:GetPosition()</a></td>
<td class="summary">Get the display position of the display sprite in percent.</td>
</tr>
<tr>
<td class="name" ><a href="#DisplaySprite:GetRotation">DisplaySprite:GetRotation()</a></td>
<td class="summary">Get the rotation of the display sprite in degrees.</td>
</tr>
<tr>
<td class="name" ><a href="#DisplaySprite:GetScale">DisplaySprite:GetScale()</a></td>
<td class="summary">Get the horizontal and vertical scale of the display sprite in percent.</td>
</tr>
<tr>
<td class="name" ><a href="#DisplaySprite:GetColor">DisplaySprite:GetColor()</a></td>
<td class="summary">Get the color of the display sprite.</td>
</tr>
<tr>
<td class="name" ><a href="#DisplaySprite:SetObjectID">DisplaySprite:SetObjectID(New)</a></td>
<td class="summary">Set the sprite sequence object ID used by the display sprite.</td>
</tr>
<tr>
<td class="name" ><a href="#DisplaySprite:SetSpriteID">DisplaySprite:SetSpriteID(New)</a></td>
<td class="summary">Set the sprite ID in the sprite sequence object used by the display sprite.</td>
</tr>
<tr>
<td class="name" ><a href="#DisplaySprite:SetPosition">DisplaySprite:SetPosition(New)</a></td>
<td class="summary">Set the display position of the display sprite in percent.</td>
</tr>
<tr>
<td class="name" ><a href="#DisplaySprite:SetRotation">DisplaySprite:SetRotation(New)</a></td>
<td class="summary">Set the rotation of the display sprite in degrees.</td>
</tr>
<tr>
<td class="name" ><a href="#DisplaySprite:SetScale">DisplaySprite:SetScale(New)</a></td>
<td class="summary">Set the horizontal and vertical scale of the display sprite in percent.</td>
</tr>
<tr>
<td class="name" ><a href="#DisplaySprite:SetColor">DisplaySprite:SetColor(New)</a></td>
<td class="summary">Set the color of the display sprite.</td>
</tr>
<tr>
<td class="name" ><a href="#DisplaySprite:Draw">DisplaySprite:Draw([priority][, alignMode][, scaleMode][, blendMode])</a></td>
<td class="summary">Draw the display sprite in display space for the current frame.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "DisplaySprite"></a>
<strong>DisplaySprite(ID, int, pos, rot, scale[, color])</strong>
</dt>
<dd>
Create a DisplaySprite object.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">ID</span>
<span class="types"><a class="type" href="../4 enums/Objects.ObjID.html#">ObjID</a></span>
of the sprite sequence object.
</li>
<li><span class="parameter">int</span>
<span class="types"><span class="type">int</span></span>
spriteID ID of the sprite in the sequence.
</li>
<li><span class="parameter">pos</span>
<span class="types"><a class="type" href="../3 primitive classes/Vec2.html#">Vec2</a></span>
Display position in percent.
</li>
<li><span class="parameter">rot</span>
<span class="types"><span class="type">float</span></span>
Rotation in degrees.
</li>
<li><span class="parameter">scale</span>
<span class="types"><a class="type" href="../3 primitive classes/Vec2.html#">Vec2</a></span>
Horizontal and vertical scale in percent. Scaling is interpreted by the DisplaySpriteEnum.ScaleMode passed to the Draw() function call.
</li>
<li><span class="parameter">color</span>
<span class="types"><a class="type" href="../3 primitive classes/Color.html#">Color</a></span>
Color. <strong>Default: Color(255, 255, 255, 255)</strong>
(<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../2 classes/DisplaySprite.html#">DisplaySprite</a></span>
A new DisplaySprite object.
</ol>
</dd>
<dt>
<a name = "DisplaySprite:GetObjectID"></a>
<strong>DisplaySprite:GetObjectID()</strong>
</dt>
<dd>
Get the object ID of the sprite sequence object used by the display sprite. ()
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../4 enums/Objects.ObjID.html#">ObjID</a></span>
Sprite sequence object ID.
</ol>
</dd>
<dt>
<a name = "DisplaySprite:GetSpriteID"></a>
<strong>DisplaySprite:GetSpriteID()</strong>
</dt>
<dd>
Get the sprite ID in the sprite sequence object used by the display sprite. ()
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">int</span></span>
Sprite ID in the sprite sequence object.
</ol>
</dd>
<dt>
<a name = "DisplaySprite:GetPosition"></a>
<strong>DisplaySprite:GetPosition()</strong>
</dt>
<dd>
Get the display position of the display sprite in percent. ()
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../3 primitive classes/Vec2.html#">Vec2</a></span>
Display position in percent.
</ol>
</dd>
<dt>
<a name = "DisplaySprite:GetRotation"></a>
<strong>DisplaySprite:GetRotation()</strong>
</dt>
<dd>
Get the rotation of the display sprite in degrees. ()
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">float</span></span>
Rotation in degrees.
</ol>
</dd>
<dt>
<a name = "DisplaySprite:GetScale"></a>
<strong>DisplaySprite:GetScale()</strong>
</dt>
<dd>
Get the horizontal and vertical scale of the display sprite in percent. ()
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../3 primitive classes/Vec2.html#">Vec2</a></span>
Horizontal and vertical scale in percent.
</ol>
</dd>
<dt>
<a name = "DisplaySprite:GetColor"></a>
<strong>DisplaySprite:GetColor()</strong>
</dt>
<dd>
Get the color of the display sprite. ()
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../3 primitive classes/Color.html#">Color</a></span>
Color.
</ol>
</dd>
<dt>
<a name = "DisplaySprite:SetObjectID"></a>
<strong>DisplaySprite:SetObjectID(New)</strong>
</dt>
<dd>
Set the sprite sequence object ID used by the display sprite. (Objects.ObjID)
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">New</span>
<span class="types"><a class="type" href="../4 enums/Objects.ObjID.html#">ObjID</a></span>
sprite sequence object ID.
</li>
</ul>
</dd>
<dt>
<a name = "DisplaySprite:SetSpriteID"></a>
<strong>DisplaySprite:SetSpriteID(New)</strong>
</dt>
<dd>
Set the sprite ID in the sprite sequence object used by the display sprite. (int)
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">New</span>
<span class="types"><span class="type">int</span></span>
sprite ID in the sprite sequence object.
</li>
</ul>
</dd>
<dt>
<a name = "DisplaySprite:SetPosition"></a>
<strong>DisplaySprite:SetPosition(New)</strong>
</dt>
<dd>
Set the display position of the display sprite in percent. (Vec2)
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">New</span>
<span class="types"><a class="type" href="../3 primitive classes/Vec2.html#">Vec2</a></span>
display position in percent.
</li>
</ul>
</dd>
<dt>
<a name = "DisplaySprite:SetRotation"></a>
<strong>DisplaySprite:SetRotation(New)</strong>
</dt>
<dd>
Set the rotation of the display sprite in degrees. (float)
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">New</span>
<span class="types"><span class="type">float</span></span>
rotation in degrees.
</li>
</ul>
</dd>
<dt>
<a name = "DisplaySprite:SetScale"></a>
<strong>DisplaySprite:SetScale(New)</strong>
</dt>
<dd>
Set the horizontal and vertical scale of the display sprite in percent. (Vec2)
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">New</span>
<span class="types"><span class="type">float</span></span>
horizontal and vertical scale in percent.
</li>
</ul>
</dd>
<dt>
<a name = "DisplaySprite:SetColor"></a>
<strong>DisplaySprite:SetColor(New)</strong>
</dt>
<dd>
Set the color of the display sprite. (Color)
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">New</span>
<span class="types"><span class="type">float</span></span>
color.
</li>
</ul>
</dd>
<dt>
<a name = "DisplaySprite:Draw"></a>
<strong>DisplaySprite:Draw([priority][, alignMode][, scaleMode][, blendMode])</strong>
</dt>
<dd>
Draw the display sprite in display space for the current frame.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">priority</span>
<span class="types"><a class="type" href="../4 enums/Objects.ObjID.html#">ObjID</a></span>
Draw priority. Can be thought of as a layer, with higher values having precedence. <strong>Default: 0</strong>
(<em>optional</em>)
</li>
<li><span class="parameter">alignMode</span>
<span class="types"><a class="type" href="../4 enums/DisplaySprite.AlignMode.html#">AlignMode</a></span>
Align mode interpreting an offset from the sprite's position. <strong>Default: DisplaySprite.AlignMode.CENTER</strong>
(<em>optional</em>)
</li>
<li><span class="parameter">scaleMode</span>
<span class="types"><a class="type" href="../4 enums/DisplaySprite.ScaleMode.html#">ScaleMode</a></span>
Scale mode interpreting the display sprite's horizontal and vertical scale. <strong>Default: DisplaySprite.ScaleMode.FIT</strong>
(<em>optional</em>)
</li>
<li><span class="parameter">blendMode</span>
<span class="types"><a class="type" href="../4 enums/Effects.BlendID.html#">BlendID</a></span>
Blend mode. <strong>Default: Effects.BlendID.ALPHABLEND</strong>
(<em>optional</em>)
</li>
</ul>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-11-09 18:25:22 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -110,6 +110,10 @@
<h2><a href="#Members">Members</a></h2>
<table class="function_list">
<tr>
<td class="name" ><a href="#nameKey">nameKey</a></td>
<td class="summary">(string) string key for the level's (localised) name.</td>
</tr>
<tr>
<td class="name" ><a href="#scriptFile">scriptFile</a></td>
<td class="summary">(string) Level-specific Lua script file.</td>
@ -206,6 +210,22 @@
<h2 class="section-header "><a name="Members"></a>Members</h2>
<dl class="function">
<dt>
<a name = "nameKey"></a>
<strong>nameKey</strong>
</dt>
<dd>
(string) string key for the level's (localised) name.
Corresponds to an entry in strings.lua.
</dd>
<dt>
<a name = "scriptFile"></a>
<strong>scriptFile</strong>

View file

@ -130,6 +130,10 @@
<td class="summary">
</td>
</tr>
<tr>
<td class="name" ><a href="#Direction">Direction()</a></td>
<td class="summary">Converts rotation to a direction normal.</td>
</tr>
<tr>
<td class="name" ><a href="#__tostring">__tostring(rotation)</a></td>
@ -232,6 +236,27 @@
</dd>
<dt>
<a name = "Direction"></a>
<strong>Direction()</strong>
</dt>
<dd>
Converts rotation to a direction normal.
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../3 primitive classes/Vec3.html#">Vec3</a></span>
resulting normal calculated from this rotation.
</ol>
</dd>
<dt>
<a name = "__tostring"></a>

View file

@ -1,166 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.5 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>TombEngine</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>1 Modules</h2>
<ul class="nowrap">
<li> <a href="../1 modules/Effects.html">Effects</a></li>
<li> <a href="../1 modules/Flow.html">Flow</a></li>
<li> <a href="../1 modules/Input.html">Input</a></li>
<li> <a href="../1 modules/Inventory.html">Inventory</a></li>
<li> <a href="../1 modules/Logic.html">Logic</a></li>
<li> <a href="../1 modules/Objects.html">Objects</a></li>
<li> <a href="../1 modules/Sound.html">Sound</a></li>
<li> <a href="../1 modules/Strings.html">Strings</a></li>
<li> <a href="../1 modules/Util.html">Util</a></li>
<li> <a href="../1 modules/View.html">View</a></li>
</ul>
<h2>2 Classes</h2>
<ul class="nowrap">
<li> <a href="../2 classes/View.DisplaySprite.html">View.DisplaySprite</a></li>
<li> <a href="../2 classes/Flow.Animations.html">Flow.Animations</a></li>
<li> <a href="../2 classes/Flow.Fog.html">Flow.Fog</a></li>
<li> <a href="../2 classes/Flow.InventoryItem.html">Flow.InventoryItem</a></li>
<li> <a href="../2 classes/Flow.LensFlare.html">Flow.LensFlare</a></li>
<li> <a href="../2 classes/Flow.Level.html">Flow.Level</a></li>
<li> <a href="../2 classes/Flow.Mirror.html">Flow.Mirror</a></li>
<li> <a href="../2 classes/Flow.Settings.html">Flow.Settings</a></li>
<li> <a href="../2 classes/Flow.SkyLayer.html">Flow.SkyLayer</a></li>
<li> <a href="../2 classes/Flow.Starfield.html">Flow.Starfield</a></li>
<li> <a href="../2 classes/Objects.AIObject.html">Objects.AIObject</a></li>
<li> <a href="../2 classes/Objects.Camera.html">Objects.Camera</a></li>
<li> <a href="../2 classes/Objects.LaraObject.html">Objects.LaraObject</a></li>
<li> <a href="../2 classes/Objects.Moveable.html">Objects.Moveable</a></li>
<li> <a href="../2 classes/Objects.Room.html">Objects.Room</a></li>
<li> <a href="../2 classes/Objects.Sink.html">Objects.Sink</a></li>
<li> <a href="../2 classes/Objects.SoundSource.html">Objects.SoundSource</a></li>
<li> <a href="../2 classes/Objects.Static.html">Objects.Static</a></li>
<li> <a href="../2 classes/Objects.Volume.html">Objects.Volume</a></li>
<li> <a href="../2 classes/Strings.DisplayString.html">Strings.DisplayString</a></li>
</ul>
<h2>3 Primitive Classes</h2>
<ul class="nowrap">
<li> <a href="../3 primitive classes/Color.html">Color</a></li>
<li> <a href="../3 primitive classes/Rotation.html">Rotation</a></li>
<li> <a href="../3 primitive classes/Vec2.html">Vec2</a></li>
<li> <a href="../3 primitive classes/Vec3.html">Vec3</a></li>
</ul>
<h2>4 Enums</h2>
<ul class="nowrap">
<li> <a href="../4 enums/Effects.BlendID.html">Effects.BlendID</a></li>
<li> <a href="../4 enums/Effects.EffectID.html">Effects.EffectID</a></li>
<li> <here>Flow.BreakMode</here></li>
<li> <a href="../4 enums/Flow.GameStatus.html">Flow.GameStatus</a></li>
<li> <a href="../4 enums/Input.ActionID.html">Input.ActionID</a></li>
<li> <a href="../4 enums/Objects.AmmoType.html">Objects.AmmoType</a></li>
<li> <a href="../4 enums/Objects.MoveableStatus.html">Objects.MoveableStatus</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
<li> <a href="../4 enums/Sound.SoundTrackType.html">Sound.SoundTrackType</a></li>
<li> <a href="../4 enums/Util.LogLevel.html">Util.LogLevel</a></li>
<li> <a href="../4 enums/View.AlignMode.html">View.AlignMode</a></li>
<li> <a href="../4 enums/View.CameraType.html">View.CameraType</a></li>
<li> <a href="../4 enums/View.PostProcessMode.html">View.PostProcessMode</a></li>
<li> <a href="../4 enums/View.ScaleMode.html">View.ScaleMode</a></li>
</ul>
<h2>5 Lua utility modules</h2>
<ul class="nowrap">
<li> <a href="../5 lua utility modules/EventSequence.html">EventSequence</a></li>
<li> <a href="../5 lua utility modules/Timer.html">Timer</a></li>
</ul>
</div>
<div id="content">
<h1>Enum <code>Flow.BreakMode</code></h1>
<p>Constants for break modes.</p>
<p>
</p>
<h2><a href="#Flow_BreakMode_constants">Flow.BreakMode constants </a></h2>
<table class="function_list">
<tr>
<td class="name" ><a href="#CONSTANT_STRING_HERE">CONSTANT_STRING_HERE</a></td>
<td class="summary">Table of break modes.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header has-description"><a name="Flow_BreakMode_constants"></a>Flow.BreakMode constants </h2>
<div class="section-description">
<p>The following constants are inside Flow.BreakMode.</p>
<pre><code>NONE
FULL
SPECTATOR
PLAYER
</code></pre>
</div>
<dl class="function">
<dt>
<a name = "CONSTANT_STRING_HERE"></a>
<strong>CONSTANT_STRING_HERE</strong>
</dt>
<dd>
Table of break modes.
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -1,165 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.5 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>TombEngine</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>1 Modules</h2>
<ul class="nowrap">
<li> <a href="../1 modules/Effects.html">Effects</a></li>
<li> <a href="../1 modules/Flow.html">Flow</a></li>
<li> <a href="../1 modules/Input.html">Input</a></li>
<li> <a href="../1 modules/Inventory.html">Inventory</a></li>
<li> <a href="../1 modules/Logic.html">Logic</a></li>
<li> <a href="../1 modules/Objects.html">Objects</a></li>
<li> <a href="../1 modules/Sound.html">Sound</a></li>
<li> <a href="../1 modules/Strings.html">Strings</a></li>
<li> <a href="../1 modules/Util.html">Util</a></li>
<li> <a href="../1 modules/View.html">View</a></li>
</ul>
<h2>2 Classes</h2>
<ul class="nowrap">
<li> <a href="../2 classes/View.DisplaySprite.html">View.DisplaySprite</a></li>
<li> <a href="../2 classes/Flow.Animations.html">Flow.Animations</a></li>
<li> <a href="../2 classes/Flow.Fog.html">Flow.Fog</a></li>
<li> <a href="../2 classes/Flow.InventoryItem.html">Flow.InventoryItem</a></li>
<li> <a href="../2 classes/Flow.LensFlare.html">Flow.LensFlare</a></li>
<li> <a href="../2 classes/Flow.Level.html">Flow.Level</a></li>
<li> <a href="../2 classes/Flow.Mirror.html">Flow.Mirror</a></li>
<li> <a href="../2 classes/Flow.Settings.html">Flow.Settings</a></li>
<li> <a href="../2 classes/Flow.SkyLayer.html">Flow.SkyLayer</a></li>
<li> <a href="../2 classes/Flow.Starfield.html">Flow.Starfield</a></li>
<li> <a href="../2 classes/Objects.AIObject.html">Objects.AIObject</a></li>
<li> <a href="../2 classes/Objects.Camera.html">Objects.Camera</a></li>
<li> <a href="../2 classes/Objects.LaraObject.html">Objects.LaraObject</a></li>
<li> <a href="../2 classes/Objects.Moveable.html">Objects.Moveable</a></li>
<li> <a href="../2 classes/Objects.Room.html">Objects.Room</a></li>
<li> <a href="../2 classes/Objects.Sink.html">Objects.Sink</a></li>
<li> <a href="../2 classes/Objects.SoundSource.html">Objects.SoundSource</a></li>
<li> <a href="../2 classes/Objects.Static.html">Objects.Static</a></li>
<li> <a href="../2 classes/Objects.Volume.html">Objects.Volume</a></li>
<li> <a href="../2 classes/Strings.DisplayString.html">Strings.DisplayString</a></li>
</ul>
<h2>3 Primitive Classes</h2>
<ul class="nowrap">
<li> <a href="../3 primitive classes/Color.html">Color</a></li>
<li> <a href="../3 primitive classes/Rotation.html">Rotation</a></li>
<li> <a href="../3 primitive classes/Vec2.html">Vec2</a></li>
<li> <a href="../3 primitive classes/Vec3.html">Vec3</a></li>
</ul>
<h2>4 Enums</h2>
<ul class="nowrap">
<li> <a href="../4 enums/Effects.BlendID.html">Effects.BlendID</a></li>
<li> <a href="../4 enums/Effects.EffectID.html">Effects.EffectID</a></li>
<li> <here>Flow.GameMode</here></li>
<li> <a href="../4 enums/Flow.GameStatus.html">Flow.GameStatus</a></li>
<li> <a href="../4 enums/Input.ActionID.html">Input.ActionID</a></li>
<li> <a href="../4 enums/Objects.AmmoType.html">Objects.AmmoType</a></li>
<li> <a href="../4 enums/Objects.MoveableStatus.html">Objects.MoveableStatus</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
<li> <a href="../4 enums/Sound.SoundTrackType.html">Sound.SoundTrackType</a></li>
<li> <a href="../4 enums/Util.LogLevel.html">Util.LogLevel</a></li>
<li> <a href="../4 enums/View.AlignMode.html">View.AlignMode</a></li>
<li> <a href="../4 enums/View.CameraType.html">View.CameraType</a></li>
<li> <a href="../4 enums/View.PostProcessMode.html">View.PostProcessMode</a></li>
<li> <a href="../4 enums/View.ScaleMode.html">View.ScaleMode</a></li>
</ul>
<h2>5 Lua utility modules</h2>
<ul class="nowrap">
<li> <a href="../5 lua utility modules/EventSequence.html">EventSequence</a></li>
<li> <a href="../5 lua utility modules/Timer.html">Timer</a></li>
</ul>
</div>
<div id="content">
<h1>Enum <code>Flow.GameMode</code></h1>
<p>Constants for game modes.</p>
<p>
</p>
<h2><a href="#Flow_GameMode_constants">Flow.GameMode constants </a></h2>
<table class="function_list">
<tr>
<td class="name" ><a href="#CONSTANT_STRING_HERE">CONSTANT_STRING_HERE</a></td>
<td class="summary">Table of game modes.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header has-description"><a name="Flow_GameMode_constants"></a>Flow.GameMode constants </h2>
<div class="section-description">
<p>The following constants are inside Flow.GameMode.</p>
<pre><code>NORMAL
FROZEN
MENU
</code></pre>
</div>
<dl class="function">
<dt>
<a name = "CONSTANT_STRING_HERE"></a>
<strong>CONSTANT_STRING_HERE</strong>
</dt>
<dd>
Table of game modes.
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -1,195 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>TombEngine</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>1 Modules</h2>
<ul class="nowrap">
<li> <a href="../1 modules/Effects.html">Effects</a></li>
<li> <a href="../1 modules/Flow.html">Flow</a></li>
<li> <a href="../1 modules/Inventory.html">Inventory</a></li>
<li> <a href="../1 modules/Logic.html">Logic</a></li>
<li> <a href="../1 modules/Misc.html">Misc</a></li>
<li> <a href="../1 modules/Objects.html">Objects</a></li>
<li> <a href="../1 modules/Strings.html">Strings</a></li>
</ul>
<h2>2 Classes</h2>
<ul class="nowrap">
<li> <a href="../2 classes/Flow.Animations.html">Flow.Animations</a></li>
<li> <a href="../2 classes/Flow.Fog.html">Flow.Fog</a></li>
<li> <a href="../2 classes/Flow.InventoryItem.html">Flow.InventoryItem</a></li>
<li> <a href="../2 classes/Flow.Level.html">Flow.Level</a></li>
<li> <a href="../2 classes/Flow.Mirror.html">Flow.Mirror</a></li>
<li> <a href="../2 classes/Flow.Settings.html">Flow.Settings</a></li>
<li> <a href="../2 classes/Flow.SkyLayer.html">Flow.SkyLayer</a></li>
<li> <a href="../2 classes/Objects.AIObject.html">Objects.AIObject</a></li>
<li> <a href="../2 classes/Objects.Camera.html">Objects.Camera</a></li>
<li> <a href="../2 classes/Objects.LaraObject.html">Objects.LaraObject</a></li>
<li> <a href="../2 classes/Objects.Moveable.html">Objects.Moveable</a></li>
<li> <a href="../2 classes/Objects.Room.html">Objects.Room</a></li>
<li> <a href="../2 classes/Objects.Sink.html">Objects.Sink</a></li>
<li> <a href="../2 classes/Objects.SoundSource.html">Objects.SoundSource</a></li>
<li> <a href="../2 classes/Objects.Static.html">Objects.Static</a></li>
<li> <a href="../2 classes/Objects.Volume.html">Objects.Volume</a></li>
<li> <a href="../2 classes/Strings.DisplayString.html">Strings.DisplayString</a></li>
</ul>
<h2>3 Primitive Classes</h2>
<ul class="nowrap">
<li> <a href="../3 primitive classes/Color.html">Color</a></li>
<li> <a href="../3 primitive classes/Rotation.html">Rotation</a></li>
<li> <a href="../3 primitive classes/Vec2.html">Vec2</a></li>
<li> <a href="../3 primitive classes/Vec3.html">Vec3</a></li>
</ul>
<h2>4 Enums</h2>
<ul class="nowrap">
<li> <a href="../4 enums/Effects.BlendID.html">Effects.BlendID</a></li>
<li> <a href="../4 enums/Effects.EffectID.html">Effects.EffectID</a></li>
<li> <here>Misc.ActionID</here></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.AmmoType.html">Objects.AmmoType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
</ul>
<h2>5 Lua utility modules</h2>
<ul class="nowrap">
<li> <a href="../5 lua utility modules/EventSequence.html">EventSequence</a></li>
<li> <a href="../5 lua utility modules/Timer.html">Timer</a></li>
</ul>
</div>
<div id="content">
<h1>Enum <code>Misc.ActionID</code></h1>
<p>Constants for action key IDs.</p>
<p>
</p>
<h2><a href="#Misc_ActionID_constants">Misc.ActionID constants </a></h2>
<table class="function_list">
<tr>
<td class="name" ><a href="#CONSTANT_STRING_HERE">CONSTANT_STRING_HERE</a></td>
<td class="summary">Table of action ID constants (for use with KeyIsHeld / KeyIsHit / etc commands).</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header has-description"><a name="Misc_ActionID_constants"></a>Misc.ActionID constants </h2>
<div class="section-description">
<p>The following constants are inside ActionID.</p>
<pre><code>FORWARD
BACK
LEFT
RIGHT
STEP_LEFT
STEP_RIGHT
WALK
SPRINT
CROUCH
JUMP
ROLL
ACTION
DRAW
LOOK
ACCELERATE
REVERSE
SPEED
SLOW
BRAKE
FIRE
FLARE
SMALL_MEDIPACK
LARGE_MEDIPACK
PREVIOUS_WEAPON
NEXT_WEAPON
WEAPON_1
WEAPON_2
WEAPON_3
WEAPON_4
WEAPON_5
WEAPON_6
WEAPON_7
WEAPON_8
WEAPON_9
WEAPON_10
SELECT
DESELECT
PAUSE
INVENTORY
SAVE
LOAD
</code></pre>
</div>
<dl class="function">
<dt>
<a name = "CONSTANT_STRING_HERE"></a>
<strong>CONSTANT_STRING_HERE</strong>
</dt>
<dd>
Table of action ID constants (for use with KeyIsHeld / KeyIsHit / etc commands).
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-09-30 13:48:57 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -1,157 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>TombEngine</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>1 Modules</h2>
<ul class="nowrap">
<li> <a href="../1 modules/Effects.html">Effects</a></li>
<li> <a href="../1 modules/Flow.html">Flow</a></li>
<li> <a href="../1 modules/Inventory.html">Inventory</a></li>
<li> <a href="../1 modules/Logic.html">Logic</a></li>
<li> <a href="../1 modules/Misc.html">Misc</a></li>
<li> <a href="../1 modules/Objects.html">Objects</a></li>
<li> <a href="../1 modules/Strings.html">Strings</a></li>
</ul>
<h2>2 Classes</h2>
<ul class="nowrap">
<li> <a href="../2 classes/Flow.Animations.html">Flow.Animations</a></li>
<li> <a href="../2 classes/Flow.Fog.html">Flow.Fog</a></li>
<li> <a href="../2 classes/Flow.InventoryItem.html">Flow.InventoryItem</a></li>
<li> <a href="../2 classes/Flow.Level.html">Flow.Level</a></li>
<li> <a href="../2 classes/Flow.Mirror.html">Flow.Mirror</a></li>
<li> <a href="../2 classes/Flow.Settings.html">Flow.Settings</a></li>
<li> <a href="../2 classes/Flow.SkyLayer.html">Flow.SkyLayer</a></li>
<li> <a href="../2 classes/Objects.AIObject.html">Objects.AIObject</a></li>
<li> <a href="../2 classes/Objects.Camera.html">Objects.Camera</a></li>
<li> <a href="../2 classes/Objects.LaraObject.html">Objects.LaraObject</a></li>
<li> <a href="../2 classes/Objects.Moveable.html">Objects.Moveable</a></li>
<li> <a href="../2 classes/Objects.Room.html">Objects.Room</a></li>
<li> <a href="../2 classes/Objects.Sink.html">Objects.Sink</a></li>
<li> <a href="../2 classes/Objects.SoundSource.html">Objects.SoundSource</a></li>
<li> <a href="../2 classes/Objects.Static.html">Objects.Static</a></li>
<li> <a href="../2 classes/Objects.Volume.html">Objects.Volume</a></li>
<li> <a href="../2 classes/Strings.DisplayString.html">Strings.DisplayString</a></li>
</ul>
<h2>3 Primitive Classes</h2>
<ul class="nowrap">
<li> <a href="../3 primitive classes/Color.html">Color</a></li>
<li> <a href="../3 primitive classes/Rotation.html">Rotation</a></li>
<li> <a href="../3 primitive classes/Vec2.html">Vec2</a></li>
<li> <a href="../3 primitive classes/Vec3.html">Vec3</a></li>
</ul>
<h2>4 Enums</h2>
<ul class="nowrap">
<li> <a href="../4 enums/Effects.BlendID.html">Effects.BlendID</a></li>
<li> <a href="../4 enums/Effects.EffectID.html">Effects.EffectID</a></li>
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <here>Misc.CameraType</here></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.AmmoType.html">Objects.AmmoType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
</ul>
<h2>5 Lua utility modules</h2>
<ul class="nowrap">
<li> <a href="../5 lua utility modules/EventSequence.html">EventSequence</a></li>
<li> <a href="../5 lua utility modules/Timer.html">Timer</a></li>
</ul>
</div>
<div id="content">
<h1>Enum <code>Misc.CameraType</code></h1>
<p>Constants for the type of the Camera.</p>
<p>
</p>
<h2><a href="#Misc_CameraType_constants">Misc.CameraType constants </a></h2>
<table class="function_list">
<tr>
<td class="name" ><a href="#CONSTANT_STRING_HERE">CONSTANT_STRING_HERE</a></td>
<td class="summary">Table of camera type constants (for use with GetCameraType() function).</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header has-description"><a name="Misc_CameraType_constants"></a>Misc.CameraType constants </h2>
<div class="section-description">
<p>The following constants are inside CameraType.</p>
<pre><code>CHASE
FIXED
LOOK
COMBAT
HEAVY
OBJECT
</code></pre>
</div>
<dl class="function">
<dt>
<a name = "CONSTANT_STRING_HERE"></a>
<strong>CONSTANT_STRING_HERE</strong>
</dt>
<dd>
Table of camera type constants (for use with GetCameraType() function).
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-09-30 13:48:57 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -1,153 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>TombEngine</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>1 Modules</h2>
<ul class="nowrap">
<li> <a href="../1 modules/Effects.html">Effects</a></li>
<li> <a href="../1 modules/Flow.html">Flow</a></li>
<li> <a href="../1 modules/Inventory.html">Inventory</a></li>
<li> <a href="../1 modules/Logic.html">Logic</a></li>
<li> <a href="../1 modules/Misc.html">Misc</a></li>
<li> <a href="../1 modules/Objects.html">Objects</a></li>
<li> <a href="../1 modules/Strings.html">Strings</a></li>
</ul>
<h2>2 Classes</h2>
<ul class="nowrap">
<li> <a href="../2 classes/Flow.Animations.html">Flow.Animations</a></li>
<li> <a href="../2 classes/Flow.Fog.html">Flow.Fog</a></li>
<li> <a href="../2 classes/Flow.InventoryItem.html">Flow.InventoryItem</a></li>
<li> <a href="../2 classes/Flow.Level.html">Flow.Level</a></li>
<li> <a href="../2 classes/Flow.Mirror.html">Flow.Mirror</a></li>
<li> <a href="../2 classes/Flow.Settings.html">Flow.Settings</a></li>
<li> <a href="../2 classes/Flow.SkyLayer.html">Flow.SkyLayer</a></li>
<li> <a href="../2 classes/Objects.AIObject.html">Objects.AIObject</a></li>
<li> <a href="../2 classes/Objects.Camera.html">Objects.Camera</a></li>
<li> <a href="../2 classes/Objects.LaraObject.html">Objects.LaraObject</a></li>
<li> <a href="../2 classes/Objects.Moveable.html">Objects.Moveable</a></li>
<li> <a href="../2 classes/Objects.Room.html">Objects.Room</a></li>
<li> <a href="../2 classes/Objects.Sink.html">Objects.Sink</a></li>
<li> <a href="../2 classes/Objects.SoundSource.html">Objects.SoundSource</a></li>
<li> <a href="../2 classes/Objects.Static.html">Objects.Static</a></li>
<li> <a href="../2 classes/Objects.Volume.html">Objects.Volume</a></li>
<li> <a href="../2 classes/Strings.DisplayString.html">Strings.DisplayString</a></li>
</ul>
<h2>3 Primitive Classes</h2>
<ul class="nowrap">
<li> <a href="../3 primitive classes/Color.html">Color</a></li>
<li> <a href="../3 primitive classes/Rotation.html">Rotation</a></li>
<li> <a href="../3 primitive classes/Vec2.html">Vec2</a></li>
<li> <a href="../3 primitive classes/Vec3.html">Vec3</a></li>
</ul>
<h2>4 Enums</h2>
<ul class="nowrap">
<li> <a href="../4 enums/Effects.BlendID.html">Effects.BlendID</a></li>
<li> <a href="../4 enums/Effects.EffectID.html">Effects.EffectID</a></li>
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <here>Misc.LogLevel</here></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.AmmoType.html">Objects.AmmoType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
</ul>
<h2>5 Lua utility modules</h2>
<ul class="nowrap">
<li> <a href="../5 lua utility modules/EventSequence.html">EventSequence</a></li>
<li> <a href="../5 lua utility modules/Timer.html">Timer</a></li>
</ul>
</div>
<div id="content">
<h1>Enum <code>Misc.LogLevel</code></h1>
<p>Constants for LogLevel IDs.</p>
<p>
</p>
<h2><a href="#Misc_LogLevel_constants">Misc.LogLevel constants </a></h2>
<table class="function_list">
<tr>
<td class="name" ><a href="#CONSTANT_STRING_HERE">CONSTANT_STRING_HERE</a></td>
<td class="summary">Table of LogLevel ID constants (for use with PrintLog() command).</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header has-description"><a name="Misc_LogLevel_constants"></a>Misc.LogLevel constants </h2>
<div class="section-description">
<p>The following constants are inside LogLevel.</p>
<pre><code>INFO
WARNING
ERROR
</code></pre>
</div>
<dl class="function">
<dt>
<a name = "CONSTANT_STRING_HERE"></a>
<strong>CONSTANT_STRING_HERE</strong>
</dt>
<dd>
Table of LogLevel ID constants (for use with PrintLog() command).
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-09-30 13:48:57 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -1,154 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>TombEngine</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>1 Modules</h2>
<ul class="nowrap">
<li> <a href="../1 modules/Effects.html">Effects</a></li>
<li> <a href="../1 modules/Flow.html">Flow</a></li>
<li> <a href="../1 modules/Inventory.html">Inventory</a></li>
<li> <a href="../1 modules/Logic.html">Logic</a></li>
<li> <a href="../1 modules/Misc.html">Misc</a></li>
<li> <a href="../1 modules/Objects.html">Objects</a></li>
<li> <a href="../1 modules/Strings.html">Strings</a></li>
</ul>
<h2>2 Classes</h2>
<ul class="nowrap">
<li> <a href="../2 classes/Flow.Animations.html">Flow.Animations</a></li>
<li> <a href="../2 classes/Flow.Fog.html">Flow.Fog</a></li>
<li> <a href="../2 classes/Flow.InventoryItem.html">Flow.InventoryItem</a></li>
<li> <a href="../2 classes/Flow.Level.html">Flow.Level</a></li>
<li> <a href="../2 classes/Flow.Mirror.html">Flow.Mirror</a></li>
<li> <a href="../2 classes/Flow.Settings.html">Flow.Settings</a></li>
<li> <a href="../2 classes/Flow.SkyLayer.html">Flow.SkyLayer</a></li>
<li> <a href="../2 classes/Objects.AIObject.html">Objects.AIObject</a></li>
<li> <a href="../2 classes/Objects.Camera.html">Objects.Camera</a></li>
<li> <a href="../2 classes/Objects.LaraObject.html">Objects.LaraObject</a></li>
<li> <a href="../2 classes/Objects.Moveable.html">Objects.Moveable</a></li>
<li> <a href="../2 classes/Objects.Room.html">Objects.Room</a></li>
<li> <a href="../2 classes/Objects.Sink.html">Objects.Sink</a></li>
<li> <a href="../2 classes/Objects.SoundSource.html">Objects.SoundSource</a></li>
<li> <a href="../2 classes/Objects.Static.html">Objects.Static</a></li>
<li> <a href="../2 classes/Objects.Volume.html">Objects.Volume</a></li>
<li> <a href="../2 classes/Strings.DisplayString.html">Strings.DisplayString</a></li>
</ul>
<h2>3 Primitive Classes</h2>
<ul class="nowrap">
<li> <a href="../3 primitive classes/Color.html">Color</a></li>
<li> <a href="../3 primitive classes/Rotation.html">Rotation</a></li>
<li> <a href="../3 primitive classes/Vec2.html">Vec2</a></li>
<li> <a href="../3 primitive classes/Vec3.html">Vec3</a></li>
</ul>
<h2>4 Enums</h2>
<ul class="nowrap">
<li> <a href="../4 enums/Effects.BlendID.html">Effects.BlendID</a></li>
<li> <a href="../4 enums/Effects.EffectID.html">Effects.EffectID</a></li>
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <here>Misc.SoundTrackType</here></li>
<li> <a href="../4 enums/Objects.AmmoType.html">Objects.AmmoType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
</ul>
<h2>5 Lua utility modules</h2>
<ul class="nowrap">
<li> <a href="../5 lua utility modules/EventSequence.html">EventSequence</a></li>
<li> <a href="../5 lua utility modules/Timer.html">Timer</a></li>
</ul>
</div>
<div id="content">
<h1>Enum <code>Misc.SoundTrackType</code></h1>
<p>Constants for the type of the audio tracks.</p>
<p>
</p>
<h2><a href="#Misc_SoundTrackType_constants">Misc.SoundTrackType constants </a></h2>
<table class="function_list">
<tr>
<td class="name" ><a href="#CONSTANT_STRING_HERE">CONSTANT_STRING_HERE</a></td>
<td class="summary">Table of sound track type constants (for use with sound track functions).</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header has-description"><a name="Misc_SoundTrackType_constants"></a>Misc.SoundTrackType constants </h2>
<div class="section-description">
<p>The following constants are inside SoundTrackType.</p>
<pre><code>ONESHOT
LOOPED
VOICE
</code></pre>
</div>
<dl class="function">
<dt>
<a name = "CONSTANT_STRING_HERE"></a>
<strong>CONSTANT_STRING_HERE</strong>
</dt>
<dd>
Table of sound track type constants (for use with sound track functions).
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-09-30 13:48:57 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -1778,7 +1778,7 @@ bool TestLaraPoleCollision(ItemInfo* item, CollisionInfo* coll, bool goingUp, fl
bool atLeastOnePoleCollided = false;
auto collObjects = GetCollidedObjects(*item, true, false, BLOCK(1), ObjectCollectionMode::Items);
auto collObjects = GetCollidedObjects(*item, true, false, BLOCK(2), ObjectCollectionMode::Items);
if (!collObjects.IsEmpty())
{
auto laraBox = GameBoundingBox(item).ToBoundingOrientedBox(item->Pose);

View file

@ -118,7 +118,10 @@ CollidedObjectData GetCollidedObjects(ItemInfo& collidingItem, bool onlyVisible,
// Override extents if specified.
if (customRadius > 0.0f)
{
collidingAabb = BoundingBox(collidingItem.Pose.Position.ToVector3(), Vector3(customRadius));
convertedBounds.Extents = Vector3(customRadius);
}
// Run through neighboring rooms.
const auto& room = g_Level.Rooms[collidingItem.RoomNumber];

View file

@ -381,8 +381,8 @@ namespace TEN::Collision::Floordata
// Calculate and return tilt.
auto sign = isFloor ? 1 : -1;
return Vector2i(
round(scaledNormal.x * 4),
round(scaledNormal.z * 4)) * sign;
(round(scaledNormal.x) * 4),
(round(scaledNormal.z) * 4)) * sign;
}
Vector2i GetSectorPoint(int x, int z)

View file

@ -370,7 +370,6 @@ void Trigger(short const value, short const flags)
if (item->Flags & IFLAG_KILLED)
return;
item->TouchBits = NO_JOINT_BITS;
item->Flags |= TRIGGERED;
if (flags & ONESHOT)
@ -408,6 +407,7 @@ void Trigger(short const value, short const flags)
}
item->Status = ITEM_ACTIVE;
item->TouchBits = NO_JOINT_BITS;
item->DisableInterpolation = true;
}
}

View file

@ -1247,19 +1247,20 @@ void KillAllCurrentItems(short itemNumber)
// TODO: Reimplement this functionality.
}
// TODO: Rename to SpawnDynamicLight().
void TriggerDynamicLight(const Vector3& pos, const Color& color, float falloff)
void TriggerDynamicPointLight(const Vector3& pos, const Color& color, float falloff, bool castShadows, int hash)
{
g_Renderer.AddDynamicLight(
pos.x, pos.y, pos.z,
falloff * UCHAR_MAX,
color.x * UCHAR_MAX, color.y * UCHAR_MAX, color.z * UCHAR_MAX);
g_Renderer.AddDynamicPointLight(pos, falloff , color, castShadows, hash);
}
void TriggerDynamicSpotLight(const Vector3& pos, const Vector3& dir, const Color& color, float radius, float falloff, float distance, bool castShadows, int hash)
{
g_Renderer.AddDynamicSpotLight(pos, dir, radius, falloff, distance, color, castShadows, hash);
}
// Deprecated. Use above version instead.
void TriggerDynamicLight(int x, int y, int z, short falloff, byte r, byte g, byte b)
{
g_Renderer.AddDynamicLight(x, y, z, falloff, r, g, b);
g_Renderer.AddDynamicPointLight(Vector3(x, y, z), (float)(falloff * UCHAR_MAX), Color(r / (float)UCHAR_MAX, g / (float)UCHAR_MAX, b / (float)UCHAR_MAX), false);
}
void SpawnPlayerWaterSurfaceEffects(const ItemInfo& item, int waterHeight, int waterDepth)

View file

@ -300,6 +300,8 @@ void ControlWaterfallMist(short itemNumber);
void TriggerWaterfallMist(const ItemInfo& item);
void KillAllCurrentItems(short itemNumber);
void TriggerDynamicLight(int x, int y, int z, short falloff, byte r, byte g, byte b);
void TriggerDynamicPointLight(const Vector3& pos, const Color& color, float falloff, bool castShadows = false, int hash = 0);
void TriggerDynamicSpotLight(const Vector3& pos, const Vector3& dir, const Color& color, float radius, float falloff, float distance, bool castShadows = false, int hash = 0);
void TriggerRocketFlame(int x, int y, int z, int xv, int yv, int zv, int itemNumber);
void TriggerRocketSmoke(int x, int y, int z);
void TriggerFlashSmoke(int x, int y, int z, short roomNumber);
@ -313,5 +315,3 @@ void TriggerExplosionBubbles(int x, int y, int z, short roomNumber);
void Ricochet(Pose& pos);
void ProcessEffects(ItemInfo* item);
void UpdateWibble();
void TriggerDynamicLight(const Vector3& pos, const Color& color, float falloff);

View file

@ -1383,7 +1383,7 @@ void UpdateShockwaves()
{
auto lightColor = Color(shockwave.r / (float)UCHAR_MAX, shockwave.g / (float)UCHAR_MAX, shockwave.b / (float)UCHAR_MAX);
auto pos = Vector3(shockwave.x, shockwave.y, shockwave.z);
TriggerDynamicLight(pos, lightColor, shockwave.life / (float)UCHAR_MAX);
TriggerDynamicPointLight(pos, lightColor, shockwave.life / 4.0f);
}
if (shockwave.style != (int)ShockwaveStyle::Knockback)

View file

@ -74,28 +74,26 @@ namespace TEN::Entities::Creatures::TR2
// Spawn light.
auto lightPos = item.Pose.Position.ToVector3() + Vector3(0.0f, -CLICK(1), 0.0f);
auto lightColor = Color(0.0f,Random::GenerateFloat(0.7f, 1.0f), Random::GenerateFloat(0.2f, 0.3f));
float lightFalloff = Random::GenerateFloat(0.1f, 0.2f);
float transformationLightFalloff = (0.5, 1.0);
TriggerDynamicLight(lightPos, lightColor, lightFalloff);
TriggerDynamicPointLight(lightPos, lightColor, Random::GenerateFloat(BLOCK(6), BLOCK(12)));
// Handle transformation.
if (effectTimer == timeExplosion1)
{
TriggerDynamicLight(lightPos, lightColor, transformationLightFalloff);
TriggerDynamicPointLight(lightPos, lightColor, Random::GenerateFloat(BLOCK(12), BLOCK(24)));
SpawnBartoliTransformEffect(item, ID_SPHERE_OF_DOOM);
SoundEffect(SFX_TR2_MARCO_BARTOLLI_TRANSFORM, &item.Pose);
}
if (effectTimer == timeExplosion2)
{
TriggerDynamicLight(lightPos, lightColor, transformationLightFalloff);
TriggerDynamicPointLight(lightPos, lightColor, Random::GenerateFloat(BLOCK(12), BLOCK(24)));
SpawnBartoliTransformEffect(item, ID_SPHERE_OF_DOOM2);
SoundEffect(SFX_TR2_MARCO_BARTOLLI_TRANSFORM, &item.Pose);
}
if (effectTimer == timeExplosion3)
{
TriggerDynamicLight(lightPos, lightColor, transformationLightFalloff);
TriggerDynamicPointLight(lightPos, lightColor, Random::GenerateFloat(BLOCK(12), BLOCK(24)));
SpawnBartoliTransformEffect(item, ID_SPHERE_OF_DOOM3);
SoundEffect(SFX_TR2_MARCO_BARTOLLI_TRANSFORM, &item.Pose);
item.Animation.FrameNumber = animationFrameEnd;

View file

@ -193,9 +193,9 @@ namespace TEN::Entities::Creatures::TR2
Random::GenerateFloat(0.8f, 0.9f),
Random::GenerateFloat(0.4f, 0.5f),
Random::GenerateFloat(0.2f, 0.3f));
float falloff = Random::GenerateFloat(0.1f, 0.4f);
float falloff = Random::GenerateFloat(BLOCK(6), BLOCK(20));
TriggerDynamicLight(pos, color, falloff);
TriggerDynamicPointLight(pos, color, falloff);
}
break;
@ -205,9 +205,9 @@ namespace TEN::Entities::Creatures::TR2
Random::GenerateFloat(0.8f, 0.9f),
Random::GenerateFloat(0.2f, 0.3f),
Random::GenerateFloat(0.0f, 0.1f));
float falloff = Random::GenerateFloat(0.1f, 0.2f);
float falloff = Random::GenerateFloat(BLOCK(6), BLOCK(12));
TriggerDynamicLight(pos, color, falloff);
TriggerDynamicPointLight(pos, color, falloff);
}
break;
}

View file

@ -178,8 +178,8 @@ namespace TEN::Entities::Creatures::TR3
{
auto pos = GetJointPosition(item, SealMutantGasBite.BoneID, Vector3(0.0f, -SEAL_MUTANT_FLAME_LIGHT_Y_OFFSET, 0.0f));
auto color = Color(Random::GenerateFloat(0.75f, 1.0f), Random::GenerateFloat(0.4f, 0.5f), Random::GenerateFloat(0.0f, 0.25f));
float falloff = Random::GenerateFloat(0.03f, 0.04f);
TriggerDynamicLight(pos.ToVector3(), color, falloff);
float falloff = Random::GenerateFloat(BLOCK(1.5f), BLOCK(2.5f));
TriggerDynamicPointLight(pos.ToVector3(), color, falloff);
}
}
else if (TestAnimFrameRange(item, 1, 124))

View file

@ -713,7 +713,7 @@ namespace TEN::Entities::TR4
TriggerShockwave((Pose*)&pos, 24, 88, 200, 128, 128, 128, 32, EulerAngles::Identity, 8, true, false, true, (int)ShockwaveStyle::Normal);
auto lightColor = Color(1.0f, 0.4f, 0.2f);
TriggerDynamicLight(pos.ToVector3(), lightColor, 0.1f);
TriggerDynamicPointLight(pos.ToVector3(), lightColor, BLOCK(6));
Camera.bounce = -128;

View file

@ -600,7 +600,7 @@ namespace TEN::Entities::Creatures::TR5
TriggerShockwave(&Pose(pos1), 16, 160, 64, 0, color / 2, color, 48, EulerAngles::Identity, 1, true, false, true, (int)ShockwaveStyle::Normal);
auto lightColor = Color(0.4f, 0.3f, 0.0f);
TriggerDynamicLight(pos.ToVector3(), lightColor, 0.04f);
TriggerDynamicPointLight(pos.ToVector3(), lightColor, BLOCK(2.5f));
}
deltaFrame = item->Animation.FrameNumber - GetAnimData(item).frameBase;
@ -629,7 +629,7 @@ namespace TEN::Entities::Creatures::TR5
if (item->ItemFlags[3])
{
auto lightColor = Color(0.0f, 0.4f, 1.0f);
TriggerDynamicLight(pos.ToVector3(), lightColor, 0.06f);
TriggerDynamicPointLight(pos.ToVector3(), lightColor, BLOCK(4));
}
}
}

View file

@ -74,10 +74,10 @@ namespace TEN::Entities::Traps
static void SpawnLaserBeamLight(const Vector3& pos, int roomNumber, const Color& color, float intensity, float amplitudeMax)
{
constexpr auto FALLOFF = 0.03f;
constexpr auto LASER_BEAM_FALLOFF = BLOCK(1.5f);
float intensityNorm = intensity - Random::GenerateFloat(0.0f, amplitudeMax);
TriggerDynamicLight(pos, color * intensityNorm, FALLOFF);
TriggerDynamicPointLight(pos, color * intensityNorm, LASER_BEAM_FALLOFF);
}
void LaserBeamEffect::StoreInterpolationData()

View file

@ -32,8 +32,6 @@ namespace TEN::Renderer
void Renderer::FreeRendererData()
{
_shadowLight = nullptr;
_items.resize(0);
_effects.resize(0);
_moveableObjects.resize(0);
@ -47,6 +45,12 @@ namespace TEN::Renderer
_animatedTextures.resize(0);
_animatedTextureSets.resize(0);
_shadowLight = nullptr;
_dynamicLightList = 0;
for (auto& dynamicLightList : _dynamicLights)
dynamicLightList.resize(0);
for (auto& mesh : _meshes)
delete mesh;
_meshes.resize(0);
@ -197,10 +201,21 @@ namespace TEN::Renderer
_context->PSSetSamplers((UINT)registerType, 1, &samplerState);
}
void Renderer::BindLight(RendererLight& light, ShaderLight* lights, int index)
{
memcpy(&lights[index], &light, sizeof(ShaderLight));
if (light.Hash == 0)
return;
lights[index].Position = Vector3::Lerp(light.PrevPosition, light.Position, GetInterpolationFactor());
lights[index].Direction = Vector3::Lerp(light.PrevDirection, light.Direction, GetInterpolationFactor());
}
void Renderer::BindRoomLights(std::vector<RendererLight*>& lights)
{
for (int i = 0; i < lights.size(); i++)
memcpy(&_stRoom.RoomLights[i], lights[i], sizeof(ShaderLight));
BindLight(*lights[i], _stRoom.RoomLights, i);
_stRoom.NumRoomLights = (int)lights.size();
}
@ -208,7 +223,7 @@ namespace TEN::Renderer
void Renderer::BindStaticLights(std::vector<RendererLight*>& lights)
{
for (int i = 0; i < lights.size(); i++)
memcpy(&_stStatic.Lights[i], lights[i], sizeof(ShaderLight));
BindLight(*lights[i], _stStatic.Lights, i);
_stStatic.NumLights = (int)lights.size();
}
@ -216,7 +231,7 @@ namespace TEN::Renderer
void Renderer::BindInstancedStaticLights(std::vector<RendererLight*>& lights, int instanceID)
{
for (int i = 0; i < lights.size(); i++)
memcpy(&_stInstancedStaticMeshBuffer.StaticMeshes[instanceID].Lights[i], lights[i], sizeof(ShaderLight));
BindLight(*lights[i], _stInstancedStaticMeshBuffer.StaticMeshes[instanceID].Lights, i);
_stInstancedStaticMeshBuffer.StaticMeshes[instanceID].NumLights = (int)lights.size();
}
@ -242,7 +257,7 @@ namespace TEN::Renderer
if (fadedCoeff == 0.0f)
continue;
memcpy(&_stItem.Lights[numLights], lights[i], sizeof(ShaderLight));
BindLight(*lights[i], _stItem.Lights, numLights);
_stItem.Lights[numLights].Intensity *= fadedCoeff;
numLights++;
}

View file

@ -245,7 +245,8 @@ namespace TEN::Renderer
// Lights
std::vector<RendererLight> _dynamicLights;
int _dynamicLightList = 0;
std::vector<RendererLight> _dynamicLights[2];
RendererLight* _shadowLight;
// Lines
@ -417,6 +418,7 @@ namespace TEN::Renderer
void ApplySMAA(RenderTarget2D* renderTarget, RenderView& view);
void ApplyFXAA(RenderTarget2D* renderTarget, RenderView& view);
void BindTexture(TextureRegister registerType, TextureBase* texture, SamplerStateRegister samplerType);
void BindLight(RendererLight& light, ShaderLight* lights, int index);
void BindRoomLights(std::vector<RendererLight*>& lights);
void BindStaticLights(std::vector<RendererLight*>& lights);
void BindInstancedStaticLights(std::vector<RendererLight*>& lights, int instanceID);
@ -643,7 +645,9 @@ namespace TEN::Renderer
void AddString(const std::string& string, const Vector2& pos, const Color& color, float scale, int flags);
void AddDebugString(const std::string& string, const Vector2& pos, const Color& color, float scale, RendererDebugPage page = RendererDebugPage::None);
void FreeRendererData();
void AddDynamicLight(int x, int y, int z, short falloff, byte r, byte g, byte b);
void AddDynamicPointLight(const Vector3& pos, float radius, const Color& color, bool castShadows, int hash = 0);
void AddDynamicSpotLight(const Vector3& pos, const Vector3& dir, float radius, float falloff, float distance, const Color& color, bool castShadows, int hash = 0);
void StoreInterpolatedDynamicLightData(RendererLight& light);
void RenderLoadingScreen(float percentage);
void RenderFreezeMode(float interpFactor, bool staticBackground);
void UpdateProgress(float value);

View file

@ -34,6 +34,10 @@ namespace TEN::Renderer
_meshes.clear();
_dynamicLightList = 0;
for (auto& dynamicLightList : _dynamicLights)
dynamicLightList.clear();
int allocatedItemSize = (int)g_Level.Items.size() + MAX_SPAWNED_ITEM_COUNT;
auto item = RendererItem();

View file

@ -148,8 +148,10 @@ namespace TEN::Renderer
SetBlendMode(BlendMode::Opaque);
SetCullMode(CullMode::CounterClockwise);
int steps = _shadowLight->Type == LightType::Point ? 6 : 1;
for (int step = 0; step < steps; step++)
auto shadowLightPos = _shadowLight->Hash == 0 ? _shadowLight->Position :
Vector3::Lerp(_shadowLight->PrevPosition, _shadowLight->Position, GetInterpolationFactor());
for (int step = 0; step < 6; step++)
{
// Bind render target
_context->OMSetRenderTargets(1, _shadowMap.RenderTargetView[step].GetAddressOf(),
@ -158,7 +160,7 @@ namespace TEN::Renderer
_context->RSSetViewports(1, &_shadowMapViewport);
ResetScissor();
if (_shadowLight->Position == item->Position)
if (shadowLightPos == item->Position)
return;
UINT stride = sizeof(Vertex);
@ -178,27 +180,11 @@ namespace TEN::Renderer
BindTexture(TextureRegister::NormalMap, &std::get<1>(_moveablesTextures[0]), SamplerStateRegister::AnisotropicClamp);
// Set camera matrices
Matrix view;
Matrix projection;
if (_shadowLight->Type == LightType::Point)
{
view = Matrix::CreateLookAt(_shadowLight->Position, _shadowLight->Position +
Matrix view = Matrix::CreateLookAt(shadowLightPos, shadowLightPos +
RenderTargetCube::forwardVectors[step] * BLOCK(10),
RenderTargetCube::upVectors[step]);
projection = Matrix::CreatePerspectiveFieldOfView(90.0f * PI / 180.0f, 1.0f, 16.0f, _shadowLight->Out);
}
else if (_shadowLight->Type == LightType::Spot)
{
view = Matrix::CreateLookAt(_shadowLight->Position,
_shadowLight->Position + _shadowLight->Direction * BLOCK(10),
Vector3(0.0f, -1.0f, 0.0f));
// Vertex lighting fades out in 1024-steps. increase angle artificially for a bigger blend radius.
float projectionAngle = _shadowLight->OutRange * 1.5f * (PI / 180.0f);
projection = Matrix::CreatePerspectiveFieldOfView(projectionAngle, 1.0f, 16.0f, _shadowLight->Out);
}
Matrix projection = Matrix::CreatePerspectiveFieldOfView(90.0f * PI / 180.0f, 1.0f, 16.0f, _shadowLight->Out);
CCameraMatrixBuffer shadowProjection;
shadowProjection.ViewProjection = view * projection;
@ -1536,41 +1522,102 @@ namespace TEN::Renderer
AddDebugSphere(sphere.Center, sphere.Radius, color, page, isWireframe);
}
void Renderer::AddDynamicLight(int x, int y, int z, short falloff, byte r, byte g, byte b)
void Renderer::AddDynamicSpotLight(const Vector3& pos, const Vector3& dir, float radius, float falloff, float distance, const Color& color, bool castShadows, int hash)
{
if (_isLocked || g_GameFlow->LastFreezeMode != FreezeMode::None)
return;
RendererLight dynamicLight = {};
if (falloff >= 8)
{
dynamicLight.Color = Vector3(r / 255.0f, g / 255.0f, b / 255.0f) * 2.0f;
}
else
{
r = (r * falloff) >> 3;
g = (g * falloff) >> 3;
b = (b * falloff) >> 3;
dynamicLight.Color = Vector3(color.x, color.y, color.z) * 2.0f;
if (falloff < 8)
dynamicLight.Color *= (falloff / 8.0f);
dynamicLight.Color = Vector3(r / 255.0f, g / 255.0f, b / 255.0f) * 2.0f;
}
// Calculate outer cone angle (degrees) based on radius at the cone's end distance.
float outerConeAngle = atan(radius / distance) * (180.0f / PI);
float innerConeAngle = atan((radius - falloff) / distance) * (180.0f / PI);
float innerDistance = std::max(0.0f, distance - distance * (falloff / radius));
// Normalize direction for safety.
auto normalizedDirection = dir;
normalizedDirection.Normalize();
dynamicLight.RoomNumber = NO_VALUE;
dynamicLight.Intensity = 1.0f;
dynamicLight.Position = Vector3(float(x), float(y), float(z));
dynamicLight.Out = falloff * 256.0f;
dynamicLight.Type = LightType::Point;
dynamicLight.BoundingSphere = BoundingSphere(dynamicLight.Position, dynamicLight.Out);
dynamicLight.Position = pos;
dynamicLight.Direction = normalizedDirection;
dynamicLight.In = innerDistance;
dynamicLight.Out = distance;
dynamicLight.InRange = innerConeAngle > 0.0f ? innerConeAngle : 0.5f;
dynamicLight.OutRange = outerConeAngle;
dynamicLight.Type = LightType::Spot;
dynamicLight.CastShadows = castShadows;
dynamicLight.BoundingSphere = BoundingSphere(pos, distance);
dynamicLight.Luma = Luma(dynamicLight.Color);
dynamicLight.Hash = hash;
_dynamicLights.push_back(dynamicLight);
StoreInterpolatedDynamicLightData(dynamicLight);
_dynamicLights[_dynamicLightList].push_back(dynamicLight);
}
void Renderer::AddDynamicPointLight(const Vector3& pos, float radius, const Color& color, bool castShadows, int hash)
{
if (_isLocked || g_GameFlow->LastFreezeMode != FreezeMode::None)
return;
RendererLight dynamicLight = {};
dynamicLight.Color = Vector3(color.x, color.y, color.z) * 2.0f;
if (radius < BLOCK(2))
dynamicLight.Color *= (radius / BLOCK(2));
dynamicLight.RoomNumber = NO_VALUE;
dynamicLight.Intensity = 1.0f;
dynamicLight.Position = pos;
dynamicLight.In = 1.0f;
dynamicLight.Out = radius;
dynamicLight.Type = LightType::Point;
dynamicLight.CastShadows = castShadows;
dynamicLight.BoundingSphere = BoundingSphere(pos, radius);
dynamicLight.Luma = Luma(dynamicLight.Color);
dynamicLight.Hash = hash;
StoreInterpolatedDynamicLightData(dynamicLight);
_dynamicLights[_dynamicLightList].push_back(dynamicLight);
}
void Renderer::StoreInterpolatedDynamicLightData(RendererLight& light)
{
// Hash is not provided, do not search for same light in old buffer.
if (light.Hash == 0)
return;
// Determine the previous buffer index.
const auto& previousList = _dynamicLights[1 - _dynamicLightList];
// Find a light in the previous buffer with the same Hash.
auto it = std::find_if(previousList.begin(), previousList.end(),
[&light](const auto& prevLight)
{
return prevLight.Hash == light.Hash;
});
if (it == previousList.end())
return;
// If a matching light is found, copy its data.
const auto& prevLight = *it;
light.PrevPosition = prevLight.Position;
light.PrevDirection = prevLight.Direction;
}
void Renderer::PrepareScene()
{
if (g_GameFlow->CurrentFreezeMode == FreezeMode::None)
_dynamicLights.clear();
{
_dynamicLightList ^= 1;
_dynamicLights[_dynamicLightList].clear();
}
_lines2DToDraw.clear();
_lines3DToDraw.clear();
@ -1854,7 +1901,7 @@ namespace TEN::Renderer
_context->ClearDepthStencilView(_renderTarget.DepthStencilView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
// HUD must be drawn before post-processing to be antialiased.
if (renderMode == SceneRenderMode::Full)
if (renderMode == SceneRenderMode::Full && g_GameFlow->LastGameStatus == GameStatus::Normal)
g_Hud.Draw(*LaraItem);
if (renderMode != SceneRenderMode::NoPostprocess)
@ -1889,7 +1936,7 @@ namespace TEN::Renderer
DrawLines2D();
}
if (renderMode == SceneRenderMode::Full)
if (renderMode == SceneRenderMode::Full && g_GameFlow->LastGameStatus == GameStatus::Normal)
{
// Draw display sprites sorted by priority.
CollectDisplaySprites(view);
@ -2292,7 +2339,7 @@ namespace TEN::Renderer
for (int k = 0; k < moveableObj.ObjectMeshes.size(); k++)
{
if (!(nativeItem->MeshBits & (1 << k)))
if (!nativeItem->MeshBits.Test(k))
continue;
DrawMoveableMesh(item, GetMesh(item->MeshIds[k]), room, k, view, rendererPass);

View file

@ -885,7 +885,7 @@ namespace TEN::Renderer
void Renderer::RenderTitleImage()
{
Texture2D texture;
SetTextureOrDefault(texture, TEN::Utils::ToWString(g_GameFlow->IntroImagePath.c_str()));
SetTextureOrDefault(texture, TEN::Utils::ToWString(g_GameFlow->GetGameDir() + g_GameFlow->IntroImagePath.c_str()));
if (!texture.Texture)
return;

View file

@ -530,7 +530,7 @@ namespace TEN::Renderer
void Renderer::CollectLights(Vector3 position, float radius, int roomNumber, int prevRoomNumber, bool prioritizeShadowLight, bool useCachedRoomLights, std::vector<RendererLightNode>* roomsLights, std::vector<RendererLight*>* outputLights)
{
if (_rooms.size() < roomNumber)
if (_rooms.size() <= roomNumber)
return;
// Now collect lights from dynamic list and from rooms
@ -540,30 +540,41 @@ namespace TEN::Renderer
auto& room = _rooms[roomNumber];
RendererLight* brightestLight = nullptr;
float brightest = 0.0f;
float highestIntensity = 0.0f;
// Dynamic lights have the priority
for (auto& light : _dynamicLights)
auto calculateIntensity = [](float distSqr, const RendererLight& light, float radius) -> std::optional<float>
{
float distSqr =
SQUARE(position.x - light.Position.x) +
SQUARE(position.y - light.Position.y) +
SQUARE(position.z - light.Position.z);
// Collect only lights nearer than 20 sectors
if (distSqr >= SQUARE(BLOCK(20)))
continue;
// Check the out radius
if (distSqr > SQUARE(light.Out + radius))
continue;
if (distSqr >= SQUARE(BLOCK(20)) || distSqr > SQUARE(light.Out + radius))
return std::nullopt; // Light is too far.
float distance = sqrt(distSqr);
float attenuation = 1.0f - distance / light.Out;
float intensity = attenuation * light.Intensity * light.Luma;
return attenuation * light.Intensity * light.Luma;
};
RendererLightNode node = { &light, intensity, distance, 1 };
tempLights.push_back(node);
auto processLight = [&](RendererLight& light, float distSqr, int dynamicFlag)
{
float distance = sqrt(distSqr);
float intensity = calculateIntensity(distSqr, light, radius).value_or(0.0f);
if (intensity <= EPSILON)
return;
if ((light.Type == LightType::Point || light.Type == LightType::Spot) &&
light.CastShadows && prioritizeShadowLight && intensity >= highestIntensity)
{
highestIntensity = intensity;
brightestLight = &light;
}
tempLights.push_back({ &light, intensity, distance, dynamicFlag });
};
// Dynamic lights have the priority
for (auto& light : _dynamicLights[_dynamicLightList])
{
float distSqr = Vector3::DistanceSquared(position, light.Position);
processLight(light, distSqr, 1);
}
if (!useCachedRoomLights)
@ -572,132 +583,62 @@ namespace TEN::Renderer
for (int roomToCheck : room.Neighbors)
{
auto& currentRoom = _rooms[roomToCheck];
int lightCount = (int)currentRoom.Lights.size();
for (int j = 0; j < lightCount; j++)
for (auto& light : currentRoom.Lights)
{
auto* light = &currentRoom.Lights[j];
float intensity = 0;
float dist = 0;
// Check only lights different from sun.
if (light->Type == LightType::Sun)
if (light.Type == LightType::Sun)
{
// Suns from non-adjacent rooms not added.
if (roomToCheck != roomNumber && (prevRoomNumber != roomToCheck || prevRoomNumber == NO_VALUE))
continue;
// Sun is added without distance checks.
intensity = light->Intensity * Luma(light->Color);
float intensity = light.Intensity * Luma(light.Color);
RendererLightNode node = { &light, intensity, 0.0f, 0 };
tempLights.push_back(node);
if (roomsLights != nullptr)
roomsLights->push_back(node);
}
else if (light->Type == LightType::Point || light->Type == LightType::Shadow)
else if (light.Type == LightType::Point ||
light.Type == LightType::Shadow ||
light.Type == LightType::Spot)
{
float distSqr =
SQUARE(position.x - light->Position.x) +
SQUARE(position.y - light->Position.y) +
SQUARE(position.z - light->Position.z);
// Collect only lights nearer than 20 blocks.
if (distSqr >= SQUARE(BLOCK(20)))
continue;
// Check out radius.
if (distSqr > SQUARE(light->Out + radius))
continue;
dist = sqrt(distSqr);
float attenuation = 1.0f - dist / light->Out;
intensity = attenuation * light->Intensity * Luma(light->Color);
// If collecting shadows, try collecting shadow-casting light.
if (light->CastShadows && prioritizeShadowLight && light->Type == LightType::Point)
{
if (intensity >= brightest)
{
brightest = intensity;
brightestLight = light;
}
}
}
else if (light->Type == LightType::Spot)
{
float distSqr =
SQUARE(position.x - light->Position.x) +
SQUARE(position.y - light->Position.y) +
SQUARE(position.z - light->Position.z);
// Collect only lights nearer than 20 blocks.
if (distSqr >= SQUARE(BLOCK(20)))
continue;
// Check range.
if (distSqr > SQUARE(light->Out + radius))
continue;
dist = sqrt(distSqr);
float attenuation = 1.0f - dist / light->Out;
intensity = attenuation * light->Intensity * light->Luma;
// If shadow pointer provided, try collecting shadow-casting light.
if (light->CastShadows && prioritizeShadowLight)
{
if (intensity >= brightest)
{
brightest = intensity;
brightestLight = light;
}
}
float distSqr = Vector3::DistanceSquared(position, light.Position);
processLight(light, distSqr, 0);
}
else
{
// Invalid light type.
continue;
}
RendererLightNode node = { light, intensity, dist, 0 };
if (roomsLights != nullptr)
roomsLights->push_back(node);
tempLights.push_back(node);
}
}
}
else
{
for (int i = 0; i < roomsLights->size(); i++)
tempLights.push_back(roomsLights->at(i));
for (auto& node : *roomsLights)
tempLights.push_back(node);
}
// Sort lights.
if (tempLights.size() > MAX_LIGHTS_PER_ITEM)
{
std::sort(
tempLights.begin(),
tempLights.end(),
[](RendererLightNode a, RendererLightNode b)
std::sort(tempLights.begin(), tempLights.end(), [](const RendererLightNode& a, const RendererLightNode& b)
{
if (a.Dynamic == b.Dynamic)
{
return (a.LocalIntensity > b.LocalIntensity);
}
else
{
return (a.Dynamic > b.Dynamic);
}
return (a.Dynamic == b.Dynamic) ? (a.LocalIntensity > b.LocalIntensity) : (a.Dynamic > b.Dynamic);
});
}
// Put actual lights in provided vector.
outputLights->clear();
// Add brightest ligh, if collecting shadow light is specified, even if it's far in range.
// Add brightest light, if collecting shadow light is specified, even if it's far in range.
if (prioritizeShadowLight && brightestLight)
outputLights->push_back(brightestLight);
// Add max 8 lights per item, including shadow light for player eventually.
for (auto l : tempLights)
for (auto& l : tempLights)
{
if (prioritizeShadowLight && brightestLight == l.Light)
continue;
@ -714,7 +655,7 @@ namespace TEN::Renderer
std::vector<RendererLight*> lightsToDraw;
CollectLights(Vector3(Camera.pos.x, Camera.pos.y, Camera.pos.z), CAMERA_LIGHT_COLLECTION_RADIUS, Camera.pos.RoomNumber, NO_VALUE, true, false, nullptr, &lightsToDraw);
if (lightsToDraw.size() > 0 && lightsToDraw.front()->CastShadows)
if (!lightsToDraw.empty() && lightsToDraw.front()->CastShadows)
{
_shadowLight = lightsToDraw.front();
}
@ -784,9 +725,9 @@ namespace TEN::Renderer
ROOM_INFO* r = &g_Level.Rooms[roomNumber];
// Collect dynamic lights for rooms
for (int i = 0; i < _dynamicLights.size(); i++)
for (int i = 0; i < _dynamicLights[_dynamicLightList].size(); i++)
{
RendererLight* light = &_dynamicLights[i];
RendererLight* light = &_dynamicLights[_dynamicLightList][i];
// If no radius, ignore
if (light->Out == 0.0f)

View file

@ -126,11 +126,13 @@ namespace TEN::Renderer
_currentCausticsFrame = 0;
// Preallocate lists
_dynamicLights = createVector<RendererLight>(MAX_DYNAMIC_LIGHTS);
_lines2DToDraw = createVector<RendererLine2D>(MAX_LINES_2D);
_lines3DToDraw = createVector<RendererLine3D>(MAX_LINES_3D);
_triangles3DToDraw = createVector<RendererTriangle3D>(MAX_TRIANGLES_3D);
for (auto& dynamicLightList : _dynamicLights)
dynamicLightList = createVector<RendererLight>(MAX_DYNAMIC_LIGHTS);
for (auto& item : _items)
item.LightsToDraw = createVector<RendererLight*>(MAX_LIGHTS_PER_ITEM);

View file

@ -25,6 +25,11 @@ namespace TEN::Renderer::Structures
bool AffectNeighbourRooms;
bool CastShadows;
float Luma;
Vector3 PrevPosition;
Vector3 PrevDirection;
int Hash = 0;
};
struct RendererLightNode

View file

@ -306,6 +306,7 @@ static constexpr char ScriptReserved_EmitParticle[] = "EmitParticle";
static constexpr char ScriptReserved_EmitLightningArc[] = "EmitLightningArc";
static constexpr char ScriptReserved_EmitShockwave[] = "EmitShockwave";
static constexpr char ScriptReserved_EmitLight[] = "EmitLight";
static constexpr char ScriptReserved_EmitSpotLight[] = "EmitSpotLight";
static constexpr char ScriptReserved_EmitBlood[] = "EmitBlood";
static constexpr char ScriptReserved_EmitFire[] = "EmitFire";
static constexpr char ScriptReserved_MakeExplosion[] = "MakeExplosion";
@ -421,3 +422,7 @@ constexpr char ScriptReserved_Vec3Length[] = "Length";
constexpr char ScriptReserved_Vec3Lerp[] = "Lerp";
constexpr char ScriptReserved_Vec3Normalize[] = "Normalize";
constexpr char ScriptReserved_Vec3Rotate[] = "Rotate";
// Rotation
constexpr char ScriptReserved_RotationDirection[] = "Direction";

View file

@ -23,6 +23,7 @@
#include "Scripting/Internal/TEN/Vec2/Vec2.h"
#include "Sound/sound.h"
#include "Specific/clock.h"
#include "Specific/trutils.h"
/***
Functions to generate effects.
@ -258,15 +259,38 @@ namespace TEN::Scripting::Effects
/***Emit dynamic light that lasts for a single frame.
* If you want a light that sticks around, you must call this each frame.
@function EmitLight
@tparam Vec3 pos
@tparam Color color (default Color(255, 255, 255))
@tparam int radius (default 20) corresponds loosely to both intensity and range
@tparam Vec3 pos position of the light
@tparam[opt] Color color light color (default Color(255, 255, 255))
@tparam[opt] int radius measured in "clicks" or 256 world units (default 20)
@tparam[opt] bool shadows determines whether light should generate dynamic shadows for applicable moveables (default is false)
@tparam[opt] string name if provided, engine will interpolate this light for high framerate mode (be careful not to use same name for different lights)
*/
static void EmitLight(Vec3 pos, TypeOrNil<ScriptColor> col, TypeOrNil<int> radius)
static void EmitLight(Vec3 pos, TypeOrNil<ScriptColor> col, TypeOrNil<int> radius, TypeOrNil<bool> castShadows, TypeOrNil<std::string> name)
{
auto color = USE_IF_HAVE(ScriptColor, col, ScriptColor(255, 255, 255));
int rad = USE_IF_HAVE(int, radius, 20);
TriggerDynamicLight(pos.x, pos.y, pos.z, rad, color.GetR(), color.GetG(), color.GetB());
int rad = (float)(USE_IF_HAVE(int, radius, 20) * BLOCK(0.25f));
TriggerDynamicPointLight(pos.ToVector3(), color, rad, USE_IF_HAVE(bool, castShadows, false), GetHash(USE_IF_HAVE(std::string, name, std::string())));
}
/***Emit dynamic directional spotlight that lasts for a single frame.
* If you want a light that sticks around, you must call this each frame.
@function EmitSpotLight
@tparam Vec3 pos position of the light
@tparam Vec3 dir direction, or a point to which spotlight should be directed to
@tparam[opt] Color color (default Color(255, 255, 255))
@tparam[opt] int radius overall radius at the endpoint of a light cone, measured in "clicks" or 256 world units (default 10)
@tparam[opt] int falloff radius, at which light starts to fade out, measured in "clicks" (default 5)
@tparam[opt] int distance distance, at which light cone fades out, measured in "clicks" (default 20)
@tparam[opt] bool shadows determines whether light should generate dynamic shadows for applicable moveables (default is false)
@tparam[opt] string name if provided, engine will interpolate this light for high framerate mode (be careful not to use same name for different lights)
*/
static void EmitSpotLight(Vec3 pos, Vec3 dir, TypeOrNil<ScriptColor> col, TypeOrNil<int> radius, TypeOrNil<int> falloff, TypeOrNil<int> distance, TypeOrNil<bool> castShadows, TypeOrNil<std::string> name)
{
auto color = USE_IF_HAVE(ScriptColor, col, ScriptColor(255, 255, 255));
int rad = (float)(USE_IF_HAVE(int, radius, 10) * BLOCK(0.25f));
int fallOff = (float)(USE_IF_HAVE(int, falloff, 5) * BLOCK(0.25f));
int dist = (float)(USE_IF_HAVE(int, distance, 20) * BLOCK(0.25f));
TriggerDynamicSpotLight(pos.ToVector3(), dir.ToVector3(), color, rad, fallOff, dist, USE_IF_HAVE(bool, castShadows, false), GetHash(USE_IF_HAVE(std::string, name, std::string())));
}
/***Emit blood.
@ -328,6 +352,7 @@ namespace TEN::Scripting::Effects
tableEffects.set_function(ScriptReserved_EmitParticle, &EmitParticle);
tableEffects.set_function(ScriptReserved_EmitShockwave, &EmitShockwave);
tableEffects.set_function(ScriptReserved_EmitLight, &EmitLight);
tableEffects.set_function(ScriptReserved_EmitSpotLight, &EmitSpotLight);
tableEffects.set_function(ScriptReserved_EmitBlood, &EmitBlood);
tableEffects.set_function(ScriptReserved_MakeExplosion, &MakeExplosion);
tableEffects.set_function(ScriptReserved_EmitFire, &EmitFire);

View file

@ -637,7 +637,20 @@ Vec3 Moveable::GetJointPos(int jointIndex, sol::optional<Vec3> offset) const
Rotation Moveable::GetJointRot(int jointIndex) const
{
return GetBoneOrientation(*m_item, jointIndex);
auto point1 = GetJointPosition(m_item, jointIndex);
auto point2 = GetJointPosition(m_item, jointIndex, Vector3::Forward * BLOCK(1));
auto normal = (point1 - point2).ToVector3();
normal.Normalize();
auto eulers = EulerAngles(normal);
return
{
TO_DEGREES(eulers.x),
TO_DEGREES(eulers.y),
TO_DEGREES(eulers.z)
};
}
// This does not guarantee that the returned value will be identical

View file

@ -18,6 +18,7 @@ void Rotation::Register(sol::table& parent)
ctors(),
sol::call_constructor, ctors(),
sol::meta_function::to_string, &Rotation::ToString,
ScriptReserved_RotationDirection, &Rotation::Direction,
/// (float) X angle component.
// @mem x
@ -77,6 +78,24 @@ Rotation::operator Vector3() const
return Vector3(x, y, z);
};
/// Converts rotation to a direction normal.
// @treturn Vec3 resulting normal calculated from this rotation.
// @function Direction
Vec3 Rotation::Direction() const
{
// Convert degrees to radians.
float xRad = x * RADIAN;
float yRad = y * RADIAN;
// Calculate the direction vector.
float dirX = sin(yRad) * cos(xRad);
float dirY = -sin(xRad);
float dirZ = cos(yRad) * cos(xRad);
// Scale by the given distance.
return Vec3(dirX, dirY, dirZ);
}
/// @tparam Rotation rotation this Rotation.
// @treturn string A string showing the X, Y, and Z angle components of the Rotation.
// @function __tostring

View file

@ -1,5 +1,6 @@
#pragma once
#include "Math/Objects/EulerAngles.h"
#include "Scripting/Internal/TEN/Vec3/Vec3.h"
class EulerAngles;
class Pose;
@ -27,6 +28,7 @@ public:
// Converters
std::string ToString() const;
EulerAngles ToEulerAngles() const;
Vec3 Direction() const;
// Operators
operator Vector3() const;

View file

@ -30,7 +30,7 @@ Default: nil (i.e. infinite)
@tparam bool autoDelete should be string automatically deleted after timeout is reached.
If not given, the string will remain allocated even after timeout is reached, and can be
shown again without re-initialization.
Default: false
Default: true
*/
table.set_function(ScriptReserved_ShowString, &StringsHandler::ShowString, this);
@ -93,7 +93,7 @@ void StringsHandler::ShowString(const DisplayString& str, sol::optional<float> n
auto it = m_userDisplayStrings.find(str.GetID());
it->second._timeRemaining = numSeconds.value_or(0.0f);
it->second._isInfinite = !numSeconds.has_value();
it->second._deleteWhenZero = autoDelete.value_or(false);
it->second._deleteWhenZero = autoDelete.value_or(true);
}
bool StringsHandler::IsStringDisplaying(const DisplayString& displayString)
@ -110,7 +110,7 @@ void StringsHandler::ProcessDisplayStrings(float deltaTime)
{
auto& str = it->second;
bool endOfLife = 0.0f >= str._timeRemaining;
if (str._deleteWhenZero && endOfLife)
if (!str._isInfinite && str._deleteWhenZero && endOfLife)
{
ScriptAssertF(!str._isInfinite, "The infinite string {} (key \"{}\") went out of scope without being hidden.", it->first, str._key);
it = m_userDisplayStrings.erase(it);

View file

@ -135,7 +135,7 @@ PixelShaderOutput PS(PixelShaderInput input)
if (AmbientOcclusion == 1)
{
float2 samplePosition;
samplePosition = input.PositionCopy.xy / input.PositionCopy.w; // perspective divide
samplePosition = input.PositionCopy.xy / input.PositionCopy.w; // Perspective divide
samplePosition = samplePosition * 0.5f + 0.5f; // transform to range 0.0 - 1.0
samplePosition.y = 1.0f - samplePosition.y;
occlusion = pow(SSAOTexture.Sample(SSAOSampler, samplePosition).x, AmbientOcclusionExponent);
@ -143,41 +143,26 @@ PixelShaderOutput PS(PixelShaderInput input)
if (CastShadows)
{
if (Light.Type == LT_POINT)
{
DoPointLightShadow(input.WorldPosition, lighting);
float isPointLight = step(0.5f, Light.Type == LT_POINT); // 1.0 if LT_POINT, 0.0 otherwise
float isSpotLight = step(0.5f, Light.Type == LT_SPOT); // 1.0 if LT_SPOT, 0.0 otherwise
float isOtherLight = 1.0 - (isPointLight + isSpotLight); // 1.0 if neither LT_POINT nor LT_SPOT
}
else if (Light.Type == LT_SPOT)
{
DoSpotLightShadow(input.WorldPosition, lighting);
}
float3 pointLightShadow = DoPointLightShadow(input.WorldPosition, lighting);
float3 spotLightShadow = DoSpotLightShadow(input.WorldPosition, normal, lighting);
// Blend the shadows based on the light type
lighting = pointLightShadow * isPointLight + spotLightShadow * isSpotLight + lighting * isOtherLight;
}
DoBlobShadows(input.WorldPosition, lighting);
lighting = DoBlobShadows(input.WorldPosition, lighting);
if (doLights)
{
for (int i = 0; i < NumRoomLights; i++)
{
float3 lightPos = RoomLights[i].Position.xyz;
float3 color = RoomLights[i].Color.xyz;
float radius = RoomLights[i].Out;
float isPointLightRoom = step(0.5f, RoomLights[i].Type == LT_POINT);
float isSpotLightRoom = step(0.5f, RoomLights[i].Type == LT_SPOT);
float3 lightVec = (lightPos - input.WorldPosition);
float distance = length(lightVec);
if (distance > radius)
continue;
lightVec = normalize(lightVec);
float d = saturate(dot(normal, lightVec ));
if (d < 0)
continue;
float attenuation = pow(((radius - distance) / radius), 2);
lighting += color * attenuation * d;
}
lighting += DoPointLight(input.WorldPosition, normal, RoomLights[i]) * isPointLightRoom;
lighting += DoSpotLight(input.WorldPosition, normal, RoomLights[i]) * isSpotLightRoom;
}
if (Caustics)

View file

@ -6,7 +6,7 @@
float3 DoSpecularPoint(float3 pos, float3 n, ShaderLight light, float strength)
{
if ((strength <= 0.0))
if (strength <= 0.0)
return float3(0, 0, 0);
else
{
@ -97,116 +97,57 @@ float3 DoSpecularSpot(float3 pos, float3 n, ShaderLight light, float strength)
}
}
float3 DoPointLight(float3 pos, float3 n, ShaderLight light)
float3 DoPointLight(float3 pos, float3 normal, ShaderLight light)
{
float3 lightPos = light.Position.xyz;
float3 color = light.Color.xyz;
float intensity = saturate(light.Intensity);
float3 lightVec = (lightPos - pos);
float3 lightVec = light.Position.xyz - pos;
float distance = length(lightVec);
float3 lightDir = normalize(lightVec);
if (distance > light.Out)
return float3(0, 0, 0);
else
{
lightVec = normalize(lightVec);
float d = saturate(dot(n, lightVec));
float attenuation = saturate((light.Out - distance) / (light.Out - light.In));
float d = saturate(dot(normal, lightDir));
float attenuation = 1.0f;
if (distance > light.In)
attenuation = 1.0f - saturate((distance - light.In) / (light.Out - light.In));
return saturate(color * intensity * attenuation * d);
}
return saturate(light.Color.xyz * light.Intensity * attenuation * d);
}
float3 DoShadowLight(float3 pos, float3 n, ShaderLight light)
float3 DoShadowLight(float3 pos, float3 normal, ShaderLight light)
{
float3 lightPos = light.Position.xyz;
float3 color = light.Color.xyz;
float intensity = light.Intensity;
float3 lightVec = (lightPos - pos);
float3 lightVec = light.Position.xyz - pos;
float distance = length(lightVec);
float3 lightDir = normalize(lightVec);
if (distance > light.Out)
return float3(0, 0, 0);
else
{
lightVec = normalize(lightVec);
float d = saturate(dot(n, lightVec));
float attenuation = saturate((light.Out - distance) / (light.Out - light.In));
float d = saturate(dot(normal, lightDir));
float attenuation = 1.0f;
if (distance > light.In)
attenuation = 1.0f - saturate((distance - light.In) / (light.Out - light.In));
float absolute = float3(color * intensity * attenuation);
float absolute = light.Color.xyz * light.Intensity * attenuation;
float directional = absolute * d;
return ((absolute * 0.33f) + (directional * 0.66f)) * 2.0f;
}
return saturate((absolute * 0.33f) + (directional * 0.66f)) * 2.0f;
}
float3 DoSpotLight(float3 pos, float3 n, ShaderLight light)
float3 DoSpotLight(float3 pos, float3 normal, ShaderLight light)
{
float3 lightPos = light.Position.xyz;
float3 color = light.Color.xyz;
float intensity = saturate(light.Intensity);
float3 direction = light.Direction.xyz;
float innerRange = light.In;
float outerRange = light.Out;
float coneIn = light.InRange;
float coneOut = light.OutRange;
float3 lightVec = pos - lightPos;
float3 lightVec = pos - light.Position.xyz;
float distance = length(lightVec);
lightVec = normalize(lightVec);
float3 lightDir = normalize(lightVec);
float cosine = dot(lightDir, light.Direction.xyz);
if (distance > outerRange)
return float3(0, 0, 0);
else
{
float d = saturate(dot(n, -lightVec));
if (d < 0)
return float3(0, 0, 0);
else
{
float cosine = dot(lightVec, direction);
// Angle attenuation
float coneInCos = cos(light.InRange * (PI / 180.0f));
float coneOutCos = cos(light.OutRange * (PI / 180.0f));
float angleAttenuation = saturate((cosine - coneOutCos) / (coneInCos - coneOutCos));
float minCosineIn = cos(coneIn * (PI / 180.0f));
float attenuationIn = max((cosine - minCosineIn), 0.0f) / (1.0f - minCosineIn);
// Distance attenuation
float distanceAttenuation = saturate((light.Out - distance) / (light.Out - light.In));
float minCosineOut = cos(coneOut * (PI / 180.0f));
float attenuationOut = max((cosine - minCosineOut), 0.0f) / (1.0f - minCosineOut);
float attenuation = saturate(attenuationIn * 2.0f + attenuationOut);
if (attenuation > 0.0f)
{
float falloff = saturate((outerRange - distance) / (outerRange - innerRange + 1.0f));
return saturate(color * intensity * attenuation * falloff * d);
}
else
return float3(0, 0, 0);
}
}
// Surface lighting
float d = saturate(dot(normal, -lightDir));
return saturate(light.Color.xyz * light.Intensity * angleAttenuation * distanceAttenuation * d);
}
float3 DoDirectionalLight(float3 pos, float3 n, ShaderLight light)
float3 DoDirectionalLight(float3 pos, float3 normal, ShaderLight light)
{
float3 color = light.Color.xyz;
float3 intensity = light.Intensity;
float3 direction = -light.Direction.xyz;
float d = max(dot(direction, n), .0f);
if (d > 0.f)
{
return (color * intensity * d);
}
return float3(0, 0, 0);
float d = saturate(dot(-light.Direction.xyz, normal));
return light.Color.xyz * light.Intensity * d;
}
float DoFogBulb(float3 pos, ShaderFogBulb bulb)
@ -368,14 +309,13 @@ float DoFogBulbForSky(float3 pos, ShaderFogBulb bulb)
}
float DoDistanceFogForVertex(float3 pos)
{
float fog = 0.0f;
if (FogMaxDistance > 0.0f)
{
float d = length(CamPositionWS.xyz - pos);
fog = clamp((d - FogMinDistance * 1024) / (FogMaxDistance * 1024 - FogMinDistance * 1024), 0, 1);
}
float fogRange = FogMaxDistance * 1024 - FogMinDistance * 1024;
float fogEnabled = step(0.0f, FogMaxDistance);
float fogFactor = (d - FogMinDistance * 1024) / fogRange;
float fog = saturate(fogFactor) * fogEnabled;
return fog;
}
@ -387,12 +327,12 @@ float4 DoFogBulbsForVertex(float3 pos)
for (int i = 0; i < NumFogBulbs; i++)
{
float fogFactor = DoFogBulb(pos, FogBulbs[i]);
fog.xyz += FogBulbs[i].Color.xyz * fogFactor;
float3 fogColor = FogBulbs[i].Color.xyz * fogFactor;
fog.xyz += fogColor;
fog.w += fogFactor;
if (fog.w >= 1.0f)
{
break;
}
fog.w = saturate(fog.w);
}
return fog;
@ -405,12 +345,12 @@ float4 DoFogBulbsForSky(float3 pos)
for (int i = 0; i < NumFogBulbs; i++)
{
float fogFactor = DoFogBulbForSky(pos, FogBulbs[i]);
fog.xyz += FogBulbs[i].Color.xyz * fogFactor;
float3 fogColor = FogBulbs[i].Color.xyz * fogFactor;
fog.xyz += fogColor;
fog.w += fogFactor;
if (fog.w >= 1.0f)
{
break;
}
fog.w = saturate(fog.w);
}
return fog;
@ -425,31 +365,25 @@ float3 CombineLights(float3 ambient, float3 vertex, float3 tex, float3 pos, floa
for (int i = 0; i < numLights; i++)
{
int lightType = lights[i].Type;
float isPoint = step(0.5f, float(lights[i].Type == LT_POINT));
float isSpot = step(0.5f, float(lights[i].Type == LT_SPOT));
float isSun = step(0.5f, float(lights[i].Type == LT_SUN));
float isShadow = step(0.5f, float(lights[i].Type == LT_SHADOW));
if (lightType == LT_POINT)
{
diffuse += DoPointLight(pos, normal, lights[i]);
spec += DoSpecularPoint(pos, normal, lights[i], sheen);
}
else if (lightType == LT_SHADOW)
{
shadow += DoShadowLight(pos, normal, lights[i]);
}
else if (lightType == LT_SUN)
{
diffuse += DoDirectionalLight(pos, normal, lights[i]);
spec += DoSpecularSun(normal, lights[i], sheen);
}
else if (lightType == LT_SPOT)
{
diffuse += DoSpotLight(pos, normal, lights[i]);
spec += DoSpecularSpot(pos, normal, lights[i], sheen);
}
diffuse += isPoint * DoPointLight(pos, normal, lights[i]);
spec += isPoint * DoSpecularPoint(pos, normal, lights[i], sheen);
diffuse += isSpot * DoSpotLight(pos, normal, lights[i]);
spec += isSpot * DoSpecularSpot(pos, normal, lights[i], sheen);
diffuse += isSun * DoDirectionalLight(pos, normal, lights[i]);
spec += isSun * DoSpecularSun(normal, lights[i], sheen);
shadow += isShadow * DoShadowLight(pos, normal, lights[i]);
}
shadow = saturate(shadow);
diffuse.xyz *= tex.xyz;
diffuse *= tex;
float3 ambTex = saturate(ambient - shadow) * tex;
float3 combined = ambTex + diffuse + spec;

View file

@ -1,3 +1,5 @@
#include "./ShaderLight.hlsli"
#define SHADOW_INTENSITY (0.55f)
#define INV_SHADOW_INTENSITY (1.0f - SHADOW_INTENSITY)
@ -66,45 +68,35 @@ float2 GetCubeUVFromDir(int faceIndex, float3 dir)
return uv * .5 + .5;
}
void DoPointLightShadow(float3 worldPos, inout float3 lighting)
float3 DoBlobShadows(float3 worldPos, float3 lighting)
{
float shadowFactor = 1.0f;
for (int i = 0; i < NumSpheres; i++)
{
Sphere s = Spheres[i];
float dist = distance(worldPos, s.position);
float insideSphere = saturate(1.0f - step(s.radius, dist)); // Eliminates branching
float radiusFactor = dist / s.radius;
float factor = (1.0f - saturate(radiusFactor)) * insideSphere;
shadowFactor -= factor * shadowFactor;
}
shadowFactor = saturate(shadowFactor);
return lighting * saturate(shadowFactor + SHADOW_INTENSITY);
}
float3 DoPointLightShadow(float3 worldPos, float3 lighting)
{
float shadowFactor = 1.0f;
[unroll]
for (int i = 0; i < 6; i++)
{
float3 dir = normalize(worldPos - Light.Position);
int face = GetCubeFaceIndex(dir);
//debug coloring
/*
switch (face)
{
case 0:
lighting += float3(0.2, 0, 0);
break;
case 1:
lighting += float3(0.1, 0, 0);
break;
case 2:
lighting += float3(0, 0.2, 0);
break;
case 3:
lighting += float3(0, 0.1, 0);
break;
case 4:
lighting += float3(0, 0, 0.2);
break;
default:
lighting += float3(0, 0, 0.1);
break;
}
*/
float2 uv = GetCubeUVFromDir(face, dir);
float4 lightClipSpace = mul(float4(worldPos, 1.0f), LightViewProjections[i]);
lightClipSpace.xyz /= lightClipSpace.w;
if (lightClipSpace.x >= -1.0f && lightClipSpace.x <= 1.0f &&
lightClipSpace.y >= -1.0f && lightClipSpace.y <= 1.0f &&
lightClipSpace.z >= 0.0f && lightClipSpace.z <= 1.0f)
@ -115,10 +107,11 @@ void DoPointLightShadow(float3 worldPos, inout float3 lighting)
float sum = 0;
float x, y;
// Perform PCF filtering on a 4 x 4 texel neighborhood
// what about borders of cubemap?
// Perform PCF filtering on a 4 x 4 texel neighborhood.
[unroll]
for (y = -1.5; y <= 1.5; y += 1.0)
{
[unroll]
for (x = -1.5; x <= 1.5; x += 1.0)
{
sum += ShadowMap.SampleCmpLevelZero(ShadowMapSampler, float3(lightClipSpace.xy + TexOffset(x, y), i), lightClipSpace.z);
@ -128,59 +121,50 @@ void DoPointLightShadow(float3 worldPos, inout float3 lighting)
shadowFactor = sum / 16.0;
}
}
// Compute attenuation and combine lighting contribution with shadow factor
float distanceFactor = saturate(((distance(worldPos, Light.Position)) / (Light.Out)));
lighting *= saturate((shadowFactor + SHADOW_INTENSITY) + (pow(distanceFactor, 4) * INV_SHADOW_INTENSITY));
return lighting * saturate((shadowFactor + SHADOW_INTENSITY) + (pow(distanceFactor, 4) * INV_SHADOW_INTENSITY));
}
void DoBlobShadows(float3 worldPos, inout float3 lighting)
float3 DoSpotLightShadow(float3 worldPos, float3 normal, float3 lighting)
{
float influence = 1.0f - Luma(DoSpotLight(worldPos, normal, Light));
float shadowFactor = 1.0f;
for (int i = 0; i < NumSpheres; i++)
{
Sphere s = Spheres[i];
float dist = distance(worldPos, s.position);
if (dist > s.radius)
continue;
float radiusFactor = dist / s.radius;
float factor = 1 - (saturate(radiusFactor));
shadowFactor -= factor * shadowFactor;
}
shadowFactor = saturate(shadowFactor);
lighting *= saturate((shadowFactor + SHADOW_INTENSITY));
}
void DoSpotLightShadow(float3 worldPos, inout float3 lighting)
[unroll]
for (int i = 0; i < 6; i++)
{
float4 lightClipSpace = mul(float4(worldPos, 1.0f), LightViewProjections[0]);
float3 dir = normalize(worldPos - Light.Position);
float4 lightClipSpace = mul(float4(worldPos, 1.0f), LightViewProjections[i]);
lightClipSpace.xyz /= lightClipSpace.w;
float2 shadowUV = lightClipSpace.xy * 0.5f + 0.5f;
shadowUV.y = (1 - shadowUV.y);
float shadowFactor = 1.0f;
if (lightClipSpace.x >= -1.0f && lightClipSpace.x <= 1.0f &&
lightClipSpace.y >= -1.0f && lightClipSpace.y <= 1.0f &&
lightClipSpace.z >= 0.0f && lightClipSpace.z <= 1.0f)
{
lightClipSpace.x = lightClipSpace.x / 2 + 0.5;
lightClipSpace.y = lightClipSpace.y / -2 + 0.5;
float sum = 0;
float x, y;
//perform PCF filtering on a 4 x 4 texel neighborhood
// Perform PCF filtering on a 4 x 4 texel neighborhood.
[unroll]
for (y = -1.5; y <= 1.5; y += 1.0)
{
[unroll]
for (x = -1.5; x <= 1.5; x += 1.0)
{
sum += ShadowMap.SampleCmpLevelZero(ShadowMapSampler, float3(shadowUV.xy + TexOffset(x, y), 0), lightClipSpace.z);
sum += ShadowMap.SampleCmpLevelZero(ShadowMapSampler, float3(lightClipSpace.xy + TexOffset(x, y), i), lightClipSpace.z);
}
}
shadowFactor = sum / 16.0;
}
// Fade out towards the borders of the sampled texture
// for that we simply compare the distance between the shadow texture UV coordinate we sampled and the center (0.5,0.5) of the shadow texture
// use pow to "boost" the shadow intensity towards the center
float angleFactor = saturate(pow(distance(shadowUV.xy, 0.5f) * 2,2.2f));
lighting *= saturate((shadowFactor + SHADOW_INTENSITY) + ((angleFactor) * INV_SHADOW_INTENSITY));
}
// Compute attenuation and combine lighting contribution with shadow factor
return lighting * saturate((shadowFactor + SHADOW_INTENSITY) + (pow(influence, 4) * INV_SHADOW_INTENSITY));
}

View file

@ -38,6 +38,17 @@ namespace TEN::Utils
_bits.push_back(bit == '1');
}
bool BitField::IndexIsCorrect(unsigned int index) const
{
if (index >= _bits.size())
{
TENLog(std::string("BitField attempted to access bit at invalid index."), LogLevel::Warning);
return false;
}
return true;
}
unsigned int BitField::GetSize() const
{
return (unsigned int)_bits.size();
@ -59,11 +70,8 @@ namespace TEN::Utils
{
for (const unsigned int& index : indices)
{
if (index >= _bits.size())
{
TENLog(std::string("BitField attempted to set bit at invalid index."), LogLevel::Warning);
if (!IndexIsCorrect(index))
continue;
}
_bits[index] = true;
}
@ -83,11 +91,8 @@ namespace TEN::Utils
{
for (const unsigned int& index : indices)
{
if (index >= _bits.size())
{
TENLog(std::string("BitField attempted to clear bit at invalid index."), LogLevel::Warning);
if (!IndexIsCorrect(index))
continue;
}
_bits[index] = false;
}
@ -107,11 +112,8 @@ namespace TEN::Utils
{
for (const unsigned int& index : indices)
{
if (index >= _bits.size())
{
TENLog(std::string("BitField attempted to flip bit at invalid index."), LogLevel::Warning);
if (!IndexIsCorrect(index))
continue;
}
_bits[index].flip();
}
@ -131,11 +133,8 @@ namespace TEN::Utils
{
for (const unsigned int& index : indices)
{
if (index >= _bits.size())
{
TENLog(std::string("BitField attempted to test bit at invalid index."), LogLevel::Warning);
if (!IndexIsCorrect(index))
continue;
}
// Test if any bits at input indices are set.
if (testAny)
@ -156,7 +155,10 @@ namespace TEN::Utils
bool BitField::Test(unsigned int index) const
{
return Test(std::vector<unsigned int>{ index });
if (!IndexIsCorrect(index))
return false;
return _bits[index];
}
bool BitField::TestAny() const

View file

@ -8,29 +8,23 @@ namespace TEN::Utils
class BitField
{
private:
// Constants
static constexpr auto SIZE_DEFAULT = 32;
// Members
std::vector<bool> _bits = {};
bool IndexIsCorrect(unsigned int index) const;
public:
// Presets
static const BitField Empty;
static const BitField Default;
// Constructors
BitField();
BitField(unsigned int size);
BitField(unsigned int size, unsigned int packedBits);
BitField(const std::string& bitString);
// Getters
unsigned int GetSize() const;
unsigned int GetCount() const;
@ -46,14 +40,12 @@ namespace TEN::Utils
void FlipAll();
// Inquirers
bool Test(const std::vector<unsigned int>& indices, bool testAny = true) const;
bool Test(unsigned int index) const;
bool TestAny() const;
bool TestAll() const;
// Converters
unsigned int ToPackedBits() const;
std::string ToString() const;

View file

@ -155,6 +155,21 @@ namespace TEN::Utils
return strings;
}
int GetHash(const std::string& string)
{
if (string.empty())
return 0;
uint32_t hash = 2166136261u;
for (char c : string)
{
hash ^= static_cast<uint8_t>(c);
hash *= 16777619u;
}
return static_cast<int>(hash);
}
Vector2 GetAspectCorrect2DPosition(const Vector2& pos)
{
constexpr auto DISPLAY_SPACE_ASPECT = DISPLAY_SPACE_RES.x / DISPLAY_SPACE_RES.y;

View file

@ -12,6 +12,7 @@ namespace TEN::Utils
std::wstring ToWString(const std::string& string);
std::wstring ToWString(const char* cString);
std::vector<std::wstring> SplitString(const std::wstring& string);
int GetHash(const std::string& string);
// 2D space utilities
Vector2 GetAspectCorrect2DPosition(const Vector2& pos);