From e81192f052e0ac18d56b54e281c97ee60ed41b24 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 20:02:51 +0000 Subject: [PATCH] deploy: 44d25c57ca2c1974725ed6ee851bdd0c0c864725 --- 404.html | 4 ++-- assets/js/{238951b7.d4c5ca87.js => 238951b7.216b530c.js} | 2 +- assets/js/{5ca5d66a.b1c65f8d.js => 5ca5d66a.f4d56d75.js} | 2 +- assets/js/b2f554cd.432e2c91.js | 1 - assets/js/b2f554cd.ecc0ee6a.js | 1 + ...{runtime~main.0270755a.js => runtime~main.cd37ca3b.js} | 2 +- blog/Hello World/index.html | 8 ++++---- blog/archive/index.html | 6 +++--- blog/atom.xml | 4 ++-- blog/index.html | 6 +++--- blog/rss.xml | 4 ++-- blog/tags/general/index.html | 6 +++--- blog/tags/index.html | 4 ++-- docs/category/documentation/index.html | 4 ++-- docs/category/jitter-demo/index.html | 4 ++-- docs/category/quickstart/index.html | 4 ++-- docs/changelog/index.html | 4 ++-- docs/demo/jitterdemo/index.html | 4 ++-- docs/documentation/00unmanaged-memory/index.html | 4 ++-- docs/documentation/01world-entities/index.html | 4 ++-- docs/documentation/02simulation-step/index.html | 4 ++-- docs/documentation/03raycasting/index.html | 4 ++-- docs/documentation/04contact-generation/index.html | 4 ++-- docs/intro/index.html | 4 ++-- docs/quickstart/hello-world/index.html | 4 ++-- docs/quickstart/project-setup/index.html | 4 ++-- docs/quickstart/render-loop/index.html | 4 ++-- docs/webasm/index.html | 4 ++-- index.html | 4 ++-- markdown-page/index.html | 4 ++-- 30 files changed, 59 insertions(+), 59 deletions(-) rename assets/js/{238951b7.d4c5ca87.js => 238951b7.216b530c.js} (79%) rename assets/js/{5ca5d66a.b1c65f8d.js => 5ca5d66a.f4d56d75.js} (79%) delete mode 100644 assets/js/b2f554cd.432e2c91.js create mode 100644 assets/js/b2f554cd.ecc0ee6a.js rename assets/js/{runtime~main.0270755a.js => runtime~main.cd37ca3b.js} (63%) diff --git a/404.html b/404.html index 4ec572db..3b1e9c7b 100644 --- a/404.html +++ b/404.html @@ -9,13 +9,13 @@ - +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- + \ No newline at end of file diff --git a/assets/js/238951b7.d4c5ca87.js b/assets/js/238951b7.216b530c.js similarity index 79% rename from assets/js/238951b7.d4c5ca87.js rename to assets/js/238951b7.216b530c.js index b6eb5c51..b05207dc 100644 --- a/assets/js/238951b7.d4c5ca87.js +++ b/assets/js/238951b7.216b530c.js @@ -1 +1 @@ -"use strict";(self.webpackChunkjitterphysics=self.webpackChunkjitterphysics||[]).push([[902],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function l(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,l=e.originalType,c=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),s=p(r),d=o,g=s["".concat(c,".").concat(d)]||s[d]||f[d]||l;return r?n.createElement(g,a(a({ref:t},u),{},{components:r})):n.createElement(g,a({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var l=r.length,a=new Array(l);a[0]=d;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i[s]="string"==typeof e?e:o,a[1]=i;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>f,frontMatter:()=>l,metadata:()=>i,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const l={slug:"Hello World",title:"Hello World",authors:["notgiven688"],tags:["general"]},a=void 0,i={permalink:"/blog/Hello World",source:"@site/blog/2023.10-01-hello-world/index.md",title:"Hello World",description:"Hello World",date:"2024-04-29T10:32:13.000Z",formattedDate:"April 29, 2024",tags:[{label:"general",permalink:"/blog/tags/general"}],readingTime:.015,hasTruncateMarker:!1,authors:[{name:"notgiven688",url:"https://github.com/notgiven688",key:"notgiven688"}],frontMatter:{slug:"Hello World",title:"Hello World",authors:["notgiven688"],tags:["general"]}},c={authorsImageUrls:[void 0]},p=[{value:"Hello World",id:"hello-world",level:4}],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h4",{id:"hello-world"},"Hello World"))}f.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkjitterphysics=self.webpackChunkjitterphysics||[]).push([[902],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function l(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,l=e.originalType,c=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),s=p(r),d=o,g=s["".concat(c,".").concat(d)]||s[d]||f[d]||l;return r?n.createElement(g,a(a({ref:t},u),{},{components:r})):n.createElement(g,a({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var l=r.length,a=new Array(l);a[0]=d;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i[s]="string"==typeof e?e:o,a[1]=i;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>f,frontMatter:()=>l,metadata:()=>i,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const l={slug:"Hello World",title:"Hello World",authors:["notgiven688"],tags:["general"]},a=void 0,i={permalink:"/blog/Hello World",source:"@site/blog/2023.10-01-hello-world/index.md",title:"Hello World",description:"Hello World",date:"2024-05-07T20:01:48.000Z",formattedDate:"May 7, 2024",tags:[{label:"general",permalink:"/blog/tags/general"}],readingTime:.015,hasTruncateMarker:!1,authors:[{name:"notgiven688",url:"https://github.com/notgiven688",key:"notgiven688"}],frontMatter:{slug:"Hello World",title:"Hello World",authors:["notgiven688"],tags:["general"]}},c={authorsImageUrls:[void 0]},p=[{value:"Hello World",id:"hello-world",level:4}],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h4",{id:"hello-world"},"Hello World"))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/5ca5d66a.b1c65f8d.js b/assets/js/5ca5d66a.f4d56d75.js similarity index 79% rename from assets/js/5ca5d66a.b1c65f8d.js rename to assets/js/5ca5d66a.f4d56d75.js index 6a165feb..2ee121ea 100644 --- a/assets/js/5ca5d66a.b1c65f8d.js +++ b/assets/js/5ca5d66a.f4d56d75.js @@ -1 +1 @@ -"use strict";(self.webpackChunkjitterphysics=self.webpackChunkjitterphysics||[]).push([[751],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function l(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,l=e.originalType,c=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),s=p(r),d=o,g=s["".concat(c,".").concat(d)]||s[d]||f[d]||l;return r?n.createElement(g,a(a({ref:t},u),{},{components:r})):n.createElement(g,a({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var l=r.length,a=new Array(l);a[0]=d;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i[s]="string"==typeof e?e:o,a[1]=i;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>f,frontMatter:()=>l,metadata:()=>i,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const l={slug:"Hello World",title:"Hello World",authors:["notgiven688"],tags:["general"]},a=void 0,i={permalink:"/blog/Hello World",source:"@site/blog/2023.10-01-hello-world/index.md",title:"Hello World",description:"Hello World",date:"2024-04-29T10:32:13.000Z",formattedDate:"April 29, 2024",tags:[{label:"general",permalink:"/blog/tags/general"}],readingTime:.015,hasTruncateMarker:!1,authors:[{name:"notgiven688",url:"https://github.com/notgiven688",key:"notgiven688"}],frontMatter:{slug:"Hello World",title:"Hello World",authors:["notgiven688"],tags:["general"]}},c={authorsImageUrls:[void 0]},p=[{value:"Hello World",id:"hello-world",level:4}],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h4",{id:"hello-world"},"Hello World"))}f.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkjitterphysics=self.webpackChunkjitterphysics||[]).push([[751],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function l(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,l=e.originalType,c=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),s=p(r),d=o,g=s["".concat(c,".").concat(d)]||s[d]||f[d]||l;return r?n.createElement(g,a(a({ref:t},u),{},{components:r})):n.createElement(g,a({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var l=r.length,a=new Array(l);a[0]=d;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i[s]="string"==typeof e?e:o,a[1]=i;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>f,frontMatter:()=>l,metadata:()=>i,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const l={slug:"Hello World",title:"Hello World",authors:["notgiven688"],tags:["general"]},a=void 0,i={permalink:"/blog/Hello World",source:"@site/blog/2023.10-01-hello-world/index.md",title:"Hello World",description:"Hello World",date:"2024-05-07T20:01:48.000Z",formattedDate:"May 7, 2024",tags:[{label:"general",permalink:"/blog/tags/general"}],readingTime:.015,hasTruncateMarker:!1,authors:[{name:"notgiven688",url:"https://github.com/notgiven688",key:"notgiven688"}],frontMatter:{slug:"Hello World",title:"Hello World",authors:["notgiven688"],tags:["general"]}},c={authorsImageUrls:[void 0]},p=[{value:"Hello World",id:"hello-world",level:4}],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h4",{id:"hello-world"},"Hello World"))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/b2f554cd.432e2c91.js b/assets/js/b2f554cd.432e2c91.js deleted file mode 100644 index b67f4f43..00000000 --- a/assets/js/b2f554cd.432e2c91.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkjitterphysics=self.webpackChunkjitterphysics||[]).push([[477],{10:e=>{e.exports=JSON.parse('{"blogPosts":[{"id":"Hello World","metadata":{"permalink":"/blog/Hello World","source":"@site/blog/2023.10-01-hello-world/index.md","title":"Hello World","description":"Hello World","date":"2024-04-29T10:32:13.000Z","formattedDate":"April 29, 2024","tags":[{"label":"general","permalink":"/blog/tags/general"}],"readingTime":0.015,"hasTruncateMarker":false,"authors":[{"name":"notgiven688","url":"https://github.com/notgiven688","key":"notgiven688"}],"frontMatter":{"slug":"Hello World","title":"Hello World","authors":["notgiven688"],"tags":["general"]}},"content":"#### Hello World"}]}')}}]); \ No newline at end of file diff --git a/assets/js/b2f554cd.ecc0ee6a.js b/assets/js/b2f554cd.ecc0ee6a.js new file mode 100644 index 00000000..72158afa --- /dev/null +++ b/assets/js/b2f554cd.ecc0ee6a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkjitterphysics=self.webpackChunkjitterphysics||[]).push([[477],{10:e=>{e.exports=JSON.parse('{"blogPosts":[{"id":"Hello World","metadata":{"permalink":"/blog/Hello World","source":"@site/blog/2023.10-01-hello-world/index.md","title":"Hello World","description":"Hello World","date":"2024-05-07T20:01:48.000Z","formattedDate":"May 7, 2024","tags":[{"label":"general","permalink":"/blog/tags/general"}],"readingTime":0.015,"hasTruncateMarker":false,"authors":[{"name":"notgiven688","url":"https://github.com/notgiven688","key":"notgiven688"}],"frontMatter":{"slug":"Hello World","title":"Hello World","authors":["notgiven688"],"tags":["general"]}},"content":"#### Hello World"}]}')}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.0270755a.js b/assets/js/runtime~main.cd37ca3b.js similarity index 63% rename from assets/js/runtime~main.0270755a.js rename to assets/js/runtime~main.cd37ca3b.js index fdf83a18..b68265af 100644 --- a/assets/js/runtime~main.0270755a.js +++ b/assets/js/runtime~main.cd37ca3b.js @@ -1 +1 @@ -(()=>{"use strict";var e,t,r,a,c,f={},d={};function o(e){var t=d[e];if(void 0!==t)return t.exports;var r=d[e]={exports:{}};return f[e].call(r.exports,r,r.exports,o),r.exports}o.m=f,e=[],o.O=(t,r,a,c)=>{if(!r){var f=1/0;for(i=0;i=c)&&Object.keys(o.O).every((e=>o.O[e](r[n])))?r.splice(n--,1):(d=!1,c0&&e[i-1][2]>c;i--)e[i]=e[i-1];e[i]=[r,a,c]},o.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return o.d(t,{a:t}),t},r=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,o.t=function(e,a){if(1&a&&(e=this(e)),8&a)return e;if("object"==typeof e&&e){if(4&a&&e.__esModule)return e;if(16&a&&"function"==typeof e.then)return e}var c=Object.create(null);o.r(c);var f={};t=t||[null,r({}),r([]),r(r)];for(var d=2&a&&e;"object"==typeof d&&!~t.indexOf(d);d=r(d))Object.getOwnPropertyNames(d).forEach((t=>f[t]=()=>e[t]));return f.default=()=>e,o.d(c,f),c},o.d=(e,t)=>{for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.f={},o.e=e=>Promise.all(Object.keys(o.f).reduce(((t,r)=>(o.f[r](e,t),t)),[])),o.u=e=>"assets/js/"+({13:"01a85c17",34:"9beb87c2",53:"935f2afb",80:"1b5ff8e9",85:"1f391b9e",89:"a6aa9e1f",103:"ccc49370",149:"d2f6244d",195:"c4f5d8e4",372:"783efc44",414:"393be207",477:"b2f554cd",483:"7c58df75",514:"1be78505",527:"2a0f5d50",533:"b2b675dd",535:"814f3328",593:"36c73e7f",597:"df97ccc7",604:"fd02f162",608:"9e4087bc",610:"6875c492",617:"53464f74",633:"59717b93",678:"d639381c",713:"a7023ddc",714:"8955095c",751:"5ca5d66a",766:"34b8f584",792:"0e7fd199",817:"14eb3368",818:"a967c795",846:"a7e80a08",902:"238951b7",918:"17896441",973:"29043984",975:"874e495d",994:"69577797"}[e]||e)+"."+{13:"88f2bec1",34:"64205222",53:"70b0ed3a",80:"b32c78de",85:"417a37fc",89:"05908165",103:"63ab29b7",149:"abd9def6",195:"ca7abc69",210:"a5a50a76",372:"103b744f",414:"41429192",477:"432e2c91",483:"a7a1f777",514:"69a5145b",527:"24710c96",529:"a0768649",533:"24b75f6a",535:"da60346e",593:"d99d06a3",597:"ef1c8b44",604:"4b52e7c6",608:"927c9c37",610:"ea7e57d4",617:"c2969a74",633:"188a7eac",678:"4bc53f97",713:"68590c5b",714:"967d5ad7",751:"b1c65f8d",766:"46ad7417",792:"0ddec764",817:"efd93555",818:"ada3c3d8",846:"b17a3806",902:"d4c5ca87",918:"d63d0983",972:"caad5551",973:"fdbc91da",975:"4caeaee1",994:"f61e5e6d"}[e]+".js",o.miniCssF=e=>{},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),a={},c="jitterphysics:",o.l=(e,t,r,f)=>{if(a[e])a[e].push(t);else{var d,n;if(void 0!==r)for(var b=document.getElementsByTagName("script"),i=0;i{d.onerror=d.onload=null,clearTimeout(s);var c=a[e];if(delete a[e],d.parentNode&&d.parentNode.removeChild(d),c&&c.forEach((e=>e(r))),t)return t(r)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:d}),12e4);d.onerror=l.bind(null,d.onerror),d.onload=l.bind(null,d.onload),n&&document.head.appendChild(d)}},o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.p="/",o.gca=function(e){return e={17896441:"918",29043984:"973",69577797:"994","01a85c17":"13","9beb87c2":"34","935f2afb":"53","1b5ff8e9":"80","1f391b9e":"85",a6aa9e1f:"89",ccc49370:"103",d2f6244d:"149",c4f5d8e4:"195","783efc44":"372","393be207":"414",b2f554cd:"477","7c58df75":"483","1be78505":"514","2a0f5d50":"527",b2b675dd:"533","814f3328":"535","36c73e7f":"593",df97ccc7:"597",fd02f162:"604","9e4087bc":"608","6875c492":"610","53464f74":"617","59717b93":"633",d639381c:"678",a7023ddc:"713","8955095c":"714","5ca5d66a":"751","34b8f584":"766","0e7fd199":"792","14eb3368":"817",a967c795:"818",a7e80a08:"846","238951b7":"902","874e495d":"975"}[e]||e,o.p+o.u(e)},(()=>{var e={303:0,532:0};o.f.j=(t,r)=>{var a=o.o(e,t)?e[t]:void 0;if(0!==a)if(a)r.push(a[2]);else if(/^(303|532)$/.test(t))e[t]=0;else{var c=new Promise(((r,c)=>a=e[t]=[r,c]));r.push(a[2]=c);var f=o.p+o.u(t),d=new Error;o.l(f,(r=>{if(o.o(e,t)&&(0!==(a=e[t])&&(e[t]=void 0),a)){var c=r&&("load"===r.type?"missing":r.type),f=r&&r.target&&r.target.src;d.message="Loading chunk "+t+" failed.\n("+c+": "+f+")",d.name="ChunkLoadError",d.type=c,d.request=f,a[1](d)}}),"chunk-"+t,t)}},o.O.j=t=>0===e[t];var t=(t,r)=>{var a,c,f=r[0],d=r[1],n=r[2],b=0;if(f.some((t=>0!==e[t]))){for(a in d)o.o(d,a)&&(o.m[a]=d[a]);if(n)var i=n(o)}for(t&&t(r);b{"use strict";var e,t,r,a,f,c={},d={};function o(e){var t=d[e];if(void 0!==t)return t.exports;var r=d[e]={exports:{}};return c[e].call(r.exports,r,r.exports,o),r.exports}o.m=c,e=[],o.O=(t,r,a,f)=>{if(!r){var c=1/0;for(i=0;i=f)&&Object.keys(o.O).every((e=>o.O[e](r[n])))?r.splice(n--,1):(d=!1,f0&&e[i-1][2]>f;i--)e[i]=e[i-1];e[i]=[r,a,f]},o.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return o.d(t,{a:t}),t},r=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,o.t=function(e,a){if(1&a&&(e=this(e)),8&a)return e;if("object"==typeof e&&e){if(4&a&&e.__esModule)return e;if(16&a&&"function"==typeof e.then)return e}var f=Object.create(null);o.r(f);var c={};t=t||[null,r({}),r([]),r(r)];for(var d=2&a&&e;"object"==typeof d&&!~t.indexOf(d);d=r(d))Object.getOwnPropertyNames(d).forEach((t=>c[t]=()=>e[t]));return c.default=()=>e,o.d(f,c),f},o.d=(e,t)=>{for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.f={},o.e=e=>Promise.all(Object.keys(o.f).reduce(((t,r)=>(o.f[r](e,t),t)),[])),o.u=e=>"assets/js/"+({13:"01a85c17",34:"9beb87c2",53:"935f2afb",80:"1b5ff8e9",85:"1f391b9e",89:"a6aa9e1f",103:"ccc49370",149:"d2f6244d",195:"c4f5d8e4",372:"783efc44",414:"393be207",477:"b2f554cd",483:"7c58df75",514:"1be78505",527:"2a0f5d50",533:"b2b675dd",535:"814f3328",593:"36c73e7f",597:"df97ccc7",604:"fd02f162",608:"9e4087bc",610:"6875c492",617:"53464f74",633:"59717b93",678:"d639381c",713:"a7023ddc",714:"8955095c",751:"5ca5d66a",766:"34b8f584",792:"0e7fd199",817:"14eb3368",818:"a967c795",846:"a7e80a08",902:"238951b7",918:"17896441",973:"29043984",975:"874e495d",994:"69577797"}[e]||e)+"."+{13:"88f2bec1",34:"64205222",53:"70b0ed3a",80:"b32c78de",85:"417a37fc",89:"05908165",103:"63ab29b7",149:"abd9def6",195:"ca7abc69",210:"a5a50a76",372:"103b744f",414:"41429192",477:"ecc0ee6a",483:"a7a1f777",514:"69a5145b",527:"24710c96",529:"a0768649",533:"24b75f6a",535:"da60346e",593:"d99d06a3",597:"ef1c8b44",604:"4b52e7c6",608:"927c9c37",610:"ea7e57d4",617:"c2969a74",633:"188a7eac",678:"4bc53f97",713:"68590c5b",714:"967d5ad7",751:"f4d56d75",766:"46ad7417",792:"0ddec764",817:"efd93555",818:"ada3c3d8",846:"b17a3806",902:"216b530c",918:"d63d0983",972:"caad5551",973:"fdbc91da",975:"4caeaee1",994:"f61e5e6d"}[e]+".js",o.miniCssF=e=>{},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),a={},f="jitterphysics:",o.l=(e,t,r,c)=>{if(a[e])a[e].push(t);else{var d,n;if(void 0!==r)for(var b=document.getElementsByTagName("script"),i=0;i{d.onerror=d.onload=null,clearTimeout(s);var f=a[e];if(delete a[e],d.parentNode&&d.parentNode.removeChild(d),f&&f.forEach((e=>e(r))),t)return t(r)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:d}),12e4);d.onerror=l.bind(null,d.onerror),d.onload=l.bind(null,d.onload),n&&document.head.appendChild(d)}},o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.p="/",o.gca=function(e){return e={17896441:"918",29043984:"973",69577797:"994","01a85c17":"13","9beb87c2":"34","935f2afb":"53","1b5ff8e9":"80","1f391b9e":"85",a6aa9e1f:"89",ccc49370:"103",d2f6244d:"149",c4f5d8e4:"195","783efc44":"372","393be207":"414",b2f554cd:"477","7c58df75":"483","1be78505":"514","2a0f5d50":"527",b2b675dd:"533","814f3328":"535","36c73e7f":"593",df97ccc7:"597",fd02f162:"604","9e4087bc":"608","6875c492":"610","53464f74":"617","59717b93":"633",d639381c:"678",a7023ddc:"713","8955095c":"714","5ca5d66a":"751","34b8f584":"766","0e7fd199":"792","14eb3368":"817",a967c795:"818",a7e80a08:"846","238951b7":"902","874e495d":"975"}[e]||e,o.p+o.u(e)},(()=>{var e={303:0,532:0};o.f.j=(t,r)=>{var a=o.o(e,t)?e[t]:void 0;if(0!==a)if(a)r.push(a[2]);else if(/^(303|532)$/.test(t))e[t]=0;else{var f=new Promise(((r,f)=>a=e[t]=[r,f]));r.push(a[2]=f);var c=o.p+o.u(t),d=new Error;o.l(c,(r=>{if(o.o(e,t)&&(0!==(a=e[t])&&(e[t]=void 0),a)){var f=r&&("load"===r.type?"missing":r.type),c=r&&r.target&&r.target.src;d.message="Loading chunk "+t+" failed.\n("+f+": "+c+")",d.name="ChunkLoadError",d.type=f,d.request=c,a[1](d)}}),"chunk-"+t,t)}},o.O.j=t=>0===e[t];var t=(t,r)=>{var a,f,c=r[0],d=r[1],n=r[2],b=0;if(c.some((t=>0!==e[t]))){for(a in d)o.o(d,a)&&(o.m[a]=d[a]);if(n)var i=n(o)}for(t&&t(r);b -Hello World | Jitter Physics +Hello World | Jitter Physics - +
-
- +
+ \ No newline at end of file diff --git a/blog/archive/index.html b/blog/archive/index.html index 55e83184..ab29a2f6 100644 --- a/blog/archive/index.html +++ b/blog/archive/index.html @@ -9,13 +9,13 @@ - +
-
- +

Archive

Archive

+ \ No newline at end of file diff --git a/blog/atom.xml b/blog/atom.xml index f368ff79..cea494cf 100644 --- a/blog/atom.xml +++ b/blog/atom.xml @@ -2,7 +2,7 @@ https://jitterphysics.com/blog Jitter Physics Blog - 2024-04-29T10:32:13.000Z + 2024-05-07T20:01:48.000Z https://github.com/jpmonette/feed Jitter Physics Blog @@ -11,7 +11,7 @@ <![CDATA[Hello World]]> https://jitterphysics.com/blog/Hello World - 2024-04-29T10:32:13.000Z + 2024-05-07T20:01:48.000Z Hello World]]> diff --git a/blog/index.html b/blog/index.html index fe16ba18..059e9cc8 100644 --- a/blog/index.html +++ b/blog/index.html @@ -9,13 +9,13 @@ - +
-
- +
+ \ No newline at end of file diff --git a/blog/rss.xml b/blog/rss.xml index 139618e4..224b65af 100644 --- a/blog/rss.xml +++ b/blog/rss.xml @@ -4,7 +4,7 @@ Jitter Physics Blog https://jitterphysics.com/blog Jitter Physics Blog - Mon, 29 Apr 2024 10:32:13 GMT + Tue, 07 May 2024 20:01:48 GMT https://validator.w3.org/feed/docs/rss2.html https://github.com/jpmonette/feed en @@ -12,7 +12,7 @@ <![CDATA[Hello World]]> https://jitterphysics.com/blog/Hello World https://jitterphysics.com/blog/Hello World - Mon, 29 Apr 2024 10:32:13 GMT + Tue, 07 May 2024 20:01:48 GMT Hello World]]> general diff --git a/blog/tags/general/index.html b/blog/tags/general/index.html index 244bee52..e05a3357 100644 --- a/blog/tags/general/index.html +++ b/blog/tags/general/index.html @@ -9,13 +9,13 @@ - +
-

One post tagged with "general"

View All Tags
- +

One post tagged with "general"

View All Tags
+ \ No newline at end of file diff --git a/blog/tags/index.html b/blog/tags/index.html index 69fbc94e..2f5f0255 100644 --- a/blog/tags/index.html +++ b/blog/tags/index.html @@ -9,13 +9,13 @@ - +

Tags

- + \ No newline at end of file diff --git a/docs/category/documentation/index.html b/docs/category/documentation/index.html index ef29d01a..d4c96cc0 100644 --- a/docs/category/documentation/index.html +++ b/docs/category/documentation/index.html @@ -9,13 +9,13 @@ - + - + \ No newline at end of file diff --git a/docs/category/jitter-demo/index.html b/docs/category/jitter-demo/index.html index 894da567..dba8bfad 100644 --- a/docs/category/jitter-demo/index.html +++ b/docs/category/jitter-demo/index.html @@ -9,13 +9,13 @@ - + - + \ No newline at end of file diff --git a/docs/category/quickstart/index.html b/docs/category/quickstart/index.html index d747a374..318fdfca 100644 --- a/docs/category/quickstart/index.html +++ b/docs/category/quickstart/index.html @@ -9,13 +9,13 @@ - + - + \ No newline at end of file diff --git a/docs/changelog/index.html b/docs/changelog/index.html index 11981875..199b9b9c 100644 --- a/docs/changelog/index.html +++ b/docs/changelog/index.html @@ -9,13 +9,13 @@ - +

Changelog

Jitter 2.2.1 (04-29-2024)

  • Add optional activate parameter to world.AddShape.
  • Add NarrowPhase.SweepTest.
  • EPA collision detection: various improvements.
  • Improve exit condition for RayCast and PointTest.
  • Remove redundant ArgumentException for zero mass shapes.
  • Handle zero time steps. Throw ArgumentException for negative time steps.
  • Add joint base class to joint classes.

Jitter 2.2.0 (01-02-2024)

  • Breaking Change: Renamed Raycast to RayCast.
  • world.Remove(world.NullBody) does now remove all shapes, constraints and contacts associated with NullBody.
  • world.AddShape(shape) respects the activation state of the associated rigid body. Most notable: performance improvement when directly adding TriangleShapes to world.NullBody for static geometry.
  • Performance improvements for ConvexHullShape.
  • Improved termination condition in GJKEPA collision detection.

Jitter 2.1.1 (12-17-2023)

  • Fixed O(n^2) problem in TriangleMesh due to hash collisions.
  • WorldBoundingBox of Shape is now updated even if no RigidBody is attached.

Jitter 2.1.0 (12-10-2023)

  • Added debug drawing for rigid bodies (RigidBody.DebugDraw).
  • Fixed a bug in CalculateMassInertia within TransformedShape.cs.
  • Improved ray casting performance and introduced NarrowPhase.PointTest.
  • Breaking Change: Inverted behavior of BroadPhaseCollisionFilter.
  • Breaking Change: Inverted definition of damping factors in RigidBody.Damping (0 = no damping, 1 = immediate halt).
  • Added RigidBody.SetMassInertia overload to enable setting the inverse inertia to zero.
  • An exception is now thrown when a body's mass is set to zero.
  • Fixed a bug in the friction handling in Contact.cs.

Jitter 2.0.1 (10-28-2023)

  • Fixed a bug in contact initialization which affected soft body physics.

Jitter 2.0.0 (10-22-2023)

Initial stable Release.

Jitter 2.0.0-beta (10-17-2023)

  • Added softbodies.

Jitter 2.0.0-alpha (09-18-2023)

Initial Release.

- + \ No newline at end of file diff --git a/docs/demo/jitterdemo/index.html b/docs/demo/jitterdemo/index.html index 5277452c..bfc27010 100644 --- a/docs/demo/jitterdemo/index.html +++ b/docs/demo/jitterdemo/index.html @@ -9,14 +9,14 @@ - +
- + \ No newline at end of file diff --git a/docs/documentation/00unmanaged-memory/index.html b/docs/documentation/00unmanaged-memory/index.html index aac55aab..464cfdc1 100644 --- a/docs/documentation/00unmanaged-memory/index.html +++ b/docs/documentation/00unmanaged-memory/index.html @@ -9,13 +9,13 @@ - +

Unmanaged Memory

The constructor of the world class takes three optional arguments, each with quite large default values:

public World(int numBodies = 32768, int numContacts = 65536, int numConstraints = 32768)

These values specify the maximum number of entities that can exist in the world class. This is unusual for a managed library because the user must commit to a certain maximum size of the simulation, and the parameters cannot be changed after calling the constructor.

  • numBodies: The maximum number of RigidBodies in the simulation. RigidBodies possess attributes such as position, velocity, mass, inertia, and also maintain a list of shapes that exist within the collision system of the engine.
  • numContacts: Collisions reported by the collision system are utilized to construct contact manifolds between shapes. A contact manifold contains one to four collision points. The collision points for a pair of shapes are stored in a data structure called "Arbiter". Each pair of shapes can only have one Arbiter. The numContacts parameter refers to the maximum number of Arbiters.
  • numConstraints: This parameter indicates the maximum number of Constraints. A constraint limits the positions or velocities of a pair of rigid bodies.

RigidBodies, Arbiters, and Constraints are regular C# classes that reside on the managed heap. However, these objects are linked to their unmanaged counterparts: RigidBodyData, ContactData, and ConstraintData. Memory management for these structures is facilitated by Jitter: An array of pointers is allocated (referred to as the index-list in the following), where each entry indicates the actual memory of the data structure. These data structures exist in a contiguous blob of allocated memory. The managed classes maintain pointers to the index-list. Whenever the memory position of a native data structure is altered, the index-list gets updated. Jitter relocates the native structures in a manner that ensures active objects are housed in contiguous memory, enabling efficient access by the iterative solver. The size of the index-list is dictated by the corresponding number specified in the constructor. For instance, with the default constructor, the index-list can hold 32768 pointers (256 KB on a 64-bit system). The continuous block of memory that hosts the native structures adapts to the actual number of rigid bodies in the simulation in a grow-only manner. Consequently, only 265 KB are initially earmarked for a maximum of 32768 bodies, scaling up to (256 KB + 32768 x {size of RigidBodyData}) of unmanaged memory usage if 32768 bodies are effectively integrated into the simulation.

Accessing Unmanaged Memory

Raw Memory Access

Accessing raw memory is generally not required when utilizing the standard functionalities of Jitter. Although reading the raw data of objects is generally safe, modifying data can corrupt the internal state of the engine.

world.RawData facilitates access to Spans into unmanaged contiguous memory. This data is also reachable via body.Handle.Data, arbiter.Handle.Data, and constraint.Handle.Data.

- + \ No newline at end of file diff --git a/docs/documentation/01world-entities/index.html b/docs/documentation/01world-entities/index.html index b53acb5f..3ac543b3 100644 --- a/docs/documentation/01world-entities/index.html +++ b/docs/documentation/01world-entities/index.html @@ -9,13 +9,13 @@ - +

World Entities

For a more detailed description of the entities of a world, namely Islands, Shapes, RigidBodies, Constraints, and Arbiters, refer to the corresponding documentation pages.

Creating RigidBodies and Constraints

Use world.CreateRigidBody() to create a new instance of the RigidBody class. A typical code snippet for adding a unit cube to Jitter could look like this:

RigidBody body = world.CreateRigidBody();
body.Position = new JVector(0, 5, 0);
var shape = new BoxShape(1);
body.AddShape(shape);

It is not valid to add the same instance of a shape to multiple bodies.

Order of Initialization

When calling body.AddShape(shape), the shape is registered in the collision system of the engine and added to the spatial tree structure (AABB-tree) for efficient broad-phase collision detection. Make sure to not accidentally register many objects at (0, 0, 0). This may happen by repeatedly calling body.AddShape, before specifying the positions of the associated rigid bodies.

Constraints are another type of entities that can be explicitly added to the world using world.CreateConstraint<T>(body1, body2), where T is a constraint. In the following example, two constraints (a HingeAngle and a BallSocket constraint) are added:

hingeAngle = world.CreateConstraint<HingeAngle>(body1, body2);
hingeAngle.Initialize(hingeAxis, angle);

ballSocket = world.CreateConstraint<BallSocket>(body1, body2);
ballSocket.Initialize(hingeCenter);

CreateConstraint always takes two bodies as parameters; the Initialize method depends on the constraint used.

Constraint Initialization

For all default constraints available in Jitter, constraint.Initialize must be called once after world.CreateConstraint.

Accessing Entities

Once created, RigidBodies are available as an ActiveList<RigidBody> under world.RigidBodies. You can loop over all rigid bodies in the world using a regular foreach loop or a simple for loop:

foreach(var body in world.RigidBodies)
{
// ...
}

for(int i = 0; i < world.RigidBodies.Count; i++)
{
var body = world.RigidBodies[i];
// ...
}

Note that the items in ReadOnlyActiveList<RigidBody> are not necessarily in a fixed order; Jitter may rearrange items during a call to world.Step(). However, active bodies (bodies which have not been inactivated by the engine) are guaranteed to be enumerated first. Using a for-loop, active and inactive bodies can be enumerated separately:

// enumerate all active bodies
for(int i = 0; i < world.RigidBodies.Active; i++)
{
var body = world.RigidBodies[i];
// ...
}

// enumerate all inactive bodies
for(int i = world.RigidBodies.Active; i < world.RigidBodies.Count; i++)
{
var body = world.RigidBodies[i];
// ...
}

Constraints are not directly available from the world class. Users can keep track of them independently or by enumerating the HashSet of constraints owned by the associated bodies, using body.Constraints.

Islands and Shapes are also stored in ReadOnlyActiveLists and can be accessed using world.Islands and world.Shapes.

Removing Entities

The world.Remove function has overloads for removing instances of RigidBody, Arbiter, and Constraint.

Removing a rigid body also removes all constraints and contacts in which the body is involved.

Accessing Removed Entities

Instances of RigidBody, Arbiter, and Constraint store some of their data in unmanaged memory, which is automatically freed once the entities are removed from the world. Do not use these entities any longer, i.e., do not call functions or use their properties, otherwise, a NullReferenceException may be thrown.

- + \ No newline at end of file diff --git a/docs/documentation/02simulation-step/index.html b/docs/documentation/02simulation-step/index.html index 717501c1..03ea25d6 100644 --- a/docs/documentation/02simulation-step/index.html +++ b/docs/documentation/02simulation-step/index.html @@ -9,13 +9,13 @@ - +

Simulation Step

Call world.Step(float dt, bool multiThread = true) to simulate a time step of length dt. Every time world.Step is called, the following phases are performed in the engine:

  1. All collisions are detected.
  2. Forces are integrated to update the velocities.
  3. Contacts and Constraints are solved in an iterative solver.
  4. Velocities are integrated to update the positions.
Units in Jitter

The unit system of Jitter is not explicitly defined. The engine utilizes 32-bit floating-point arithmetic and is optimized for objects with a size of 1 [len_unit]. For instance, the collision system uses length thresholds on the order of 1e-04 [len_unit]. It assumes a unit density of 1 [mass_unit/len_unit³] for the mass properties of shapes. Consequently, the default mass of a unit cube is 1 [mass_unit]. The default value for gravity in Jitter is 9.819.81 [len_unit/time_unit²], which aligns with the gravitational acceleration on Earth in metric units (m/s²). Therefore, it is reasonable to use metric units (kg, m, s) when conceptualizing these values.

Step Size

To achieve accurate physical results, the time step (dt) should be as small as possible. However, to maintain interactive frame rates, it's not feasible to call world.Step too frequently. A suitable compromise, aligning with the engine's design, is to choose dt=1/100. The time step should not exceed 1/60 to prevent potential simulation instability.

Time Step Size

Maintain a consistent time step size, if possible, to avoid instabilities introduced by fluctuating time steps.

Suppose your game using Jitter operates at a varying frame rate of 80-160 fps. In this case, calling world.Step(1.0f / 100.0f) each frame might cause the simulated time to desynchronize from real time. You can implement a strategy to accumulate delta times (the discrepancy between the elapsed real time and the simulation step) and accordingly adjust the calls to world.Step(1.0f / 100.0f) based on the magnitude of the delta time.

Multithreading

Jitter employs its own thread pool (Parallelization.ThreadPool) to distribute tasks across multiple threads, potentially processed by multiple cores. You can modify the number of worker threads managed by the thread pool using threadPool.ChangeThreadCount(int numThreads). A singleton pattern is used here, as demonstrated below:

ThreadPool.Instance.ChangeThreadCount(4);

This adjusts the number of worker threads to four. Jitter utilizes the thread pool when the world.Step method is invoked with the multiThread argument set to true. Aside from this, the engine manages multithreading internally. Except when injecting derived types of Jitter into the engine (like using custom constraints or registering Broad- and NarrowPhase interfaces), the program flow operates on a single main thread as usual.

Thread Safety

Methods in Jitter are generally not thread-safe.

Substepping

Improving the simulation quality is feasible by employing smaller time steps. Substepping involves conducting collision detection once per step and executing several smaller time steps for the remainder of the simulation step, with reduced solver iterations in each step. The process is as follows:

  1. All collisions are detected.
  2. Repeat the next steps nn times with a step size of dt / nn, where nn is the number of substeps:
    1. Forces are integrated to update the velocities.
    2. Contacts and Constraints are solved in an iterative solver.
    3. Velocities are integrated to update the positions.

Utilizing smaller substeps enhances the simulation quality disproportionately. However, it also introduces a significant overhead due to the alternating between contact solving and force- and velocity-integration. Substepping is excellent for enhancing the overall quality of constraints, stabilizing large stacks of objects, and simulating large mass ratios (like heavy objects resting on light objects) with greater accuracy.

To adjust the number of substeps, use world.NumberSubsteps. Setting it to one equates to conducting a regular step.

- + \ No newline at end of file diff --git a/docs/documentation/03raycasting/index.html b/docs/documentation/03raycasting/index.html index f2f9e8b2..544b0821 100644 --- a/docs/documentation/03raycasting/index.html +++ b/docs/documentation/03raycasting/index.html @@ -9,13 +9,13 @@ - +

Ray Casting

Retrieve information about where a ray, defined by an origin and a direction, hits a target. Generally, the actual hit point can be calculated using the fraction value returned by the appropriate functions using the formula:

hit=origin+fraction×direction,with fraction[0,).\textbf{hit} = \textbf{origin} + \textrm{fraction} \times \textbf{direction}, \quad \textrm{with fraction} \in [0,\infty).

The direction given to Jitter does not need to be normalized. The normal returned by Jitter is the normalized surface normal of the collision target at the hit point.

Generic Ray Cast for ISupportMap

To cast a ray against any object implementing ISupportMap, use NarrowPhase.RayCast:

public static bool RayCast(ISupportMap support, 
ref JMatrix orientation, ref JVector position,
ref JVector origin, ref JVector direction,
out float fraction, out JVector normal)

Ray Cast Against Shapes

The world class offers two ray cast methods:

public bool RayCast(Shape shape, JVector origin, JVector direction,
out JVector normal, out float fraction)
public bool RayCast(JVector origin, JVector direction, 
RayCastFilterPre? pre, RayCastFilterPost? post,
out Shape? shape, out JVector normal, out float fraction)

The first method can be used to cast a ray against a single shape. The second method tests a ray against the world. Use the ray cast filter to get information about possible candidates or to avoid collision with specific shapes entirely. For example, a bullet may always be able to penetrate a wall; the pre-filter can be used to discard any collision with the wall. For a wall with non-uniform thickness, the bullet may only be able to penetrate the thinner part. In this case, the post-filter can be used to get information on where the ray hit the wall and, based on that information, decide whether to drop the collision.

- + \ No newline at end of file diff --git a/docs/documentation/04contact-generation/index.html b/docs/documentation/04contact-generation/index.html index f69ed048..0fca57ff 100644 --- a/docs/documentation/04contact-generation/index.html +++ b/docs/documentation/04contact-generation/index.html @@ -9,13 +9,13 @@ - +

Contact Generation

Jitter exclusively uses algorithms based on the Minkowski sum to detect collisions (available in the NarrowPhase class), i.e., there is no explicit code for the collision of two boxes, for example.

The collision of two boxes can serve as an illustrative example: The intersection of two boxes can be empty, a single point, a segment, a two-dimensional surface, or a three-dimensional volume. Handling all these cases in an algorithm is already complicated. The various kinds of results then must be managed by the solver. For instance, the solver must be able to resolve a collision where the intersection of two boxes is a two-dimensional surface, as is generally the case when one box is resting on another.

Jitter, like most other engines, handles all cases using contact points. The collision algorithms utilized by Jitter always report the point of deepest penetration as a contact point. The normal is the relative direction both shapes must move in to resolve the collision. Contact points might be cached, as depicted in the following figure where a smaller box rests on top of a larger static one (shown here for two dimensions):

contact

In each frame (world.Step), only one collision point is generated for a pair of shapes (depicted as a black 'x'). This collision point is forwarded to the solver, which then attempts to resolve the collision. In the next frame, another point might be reported by the collision system. The previous point remains valid. Now both points are solved simultaneously in the solver - the box stabilizes and eventually rests on top of the larger static box. This stabilization over several frames can lead to significant jitter, which might worsen in the general three-dimensional case and also becomes more noticeable with larger time steps. For each collision pair, Jitter stores up to four contacts, which then more or less accurately describe the true contact surface (contact manifold).

Auxiliary Contacts

Jitter employs a technique termed "auxiliary contacts", where additional contacts are generated for the general case where two flat surfaces are in contact. These additional contacts are calculated within one frame, generating the full contact manifold in "one shot", thereby preventing the jittering problem discussed in the last section. The world.EnableAuxiliaryContactPoints property can be used to enable or disable the usage of auxiliary contact point generation.

Speculative Contacts

Speculative contacts can be utilized to prevent fast and small objects from tunneling through thin objects. An object moving quickly enough might "miss" a collision since the distance traveled between two frames exceeds the thickness of another object. Speculative contacts can be enabled on a per-body basis using body.EnableSpeculativeContacts. The world.SpeculativeRelaxationFactor and world.SpeculativeVelocityThreshold can be adjusted to fine-tune speculative contacts for your use case. However, note that an accurate simulation of fast-moving objects is only possible using smaller time steps. Speculative contacts might entail the cost of inaccurate collision detection and/or response.

Collision Filters

Detected collisions can be filtered out or manipulated before they are used for contact manifold generation.

The world.BroadPhaseFilter and world.NarrowPhaseFilter properties can be utilized to specify custom implementations for the filter interfaces.

Example: Broadphase Filter

In this example, we have two "teams", team blue and team red. We will implement a filter that disregards all collisions between team members (rigid bodies) of different colors:

public class TeamFilter : IBroadPhaseFilter
{
public class TeamMember { }

public static TeamMember TeamRed = new();
public static TeamMember TeamBlue = new();

public bool Filter(Shape shapeA, Shape shapeB)
{
if (shapeA.RigidBody.Tag is not TeamMember || shapeB.RigidBody.Tag is not TeamMember)
{
// Handle collision normally if at least one body is not a member of any team
return true;
}

// There is no collision between team red and team blue.
return shapeA.RigidBody.Tag != shapeB.RigidBody.Tag;
}
}

The TeamFilter class can then be instantiated and assigned to world.BroadPhaseFilter. Rigid bodies of different colors do not interact:

world.BroadPhaseFilter = new TeamFilter();
...
bodyA.Tag = TeamFilter.TeamBlue;
bodyB.Tag = TeamFilter.TeamRed;
bodyC.Tag = TeamFilter.TeamRed;

Narrowphase Filter

The narrow phase filter operates similarly. However, the callback is called after narrow-phase collision detection, meaning detailed collision information (normal, penetration depth, collision points) is available at this stage.

The default narrow phase collision filter in Jitter is assigned to an instance of TriangleEdgeCollisionFilter, which filters out so-called "internal edges". Consider the following example of a box sliding on static triangles (referred to as "ground", depicted here in 2D as blue and red segments):

contact

The box slightly sinks into the ground due to the possibility of the collision from gravity not being perfectly resolved by design (the solver permits a small penetration).

For t=1t=1, the collision system detects a collision with the red triangle. While this is accurate, the collision normal might point in the opposite direction of the box's movement, since this is the direction in which the box and triangle must move to resolve the collision (rather than "lifting" the box up). Consequently, the box stumbles over the internal edge, instead of sliding over the non-existing gap between the two triangles.

- + \ No newline at end of file diff --git a/docs/intro/index.html b/docs/intro/index.html index 2daabc13..07105dca 100644 --- a/docs/intro/index.html +++ b/docs/intro/index.html @@ -9,14 +9,14 @@ - +

Jitter Physics 2

You will find tutorials and documentation here. Work in progress. You can help by editing or adding new content 👋

- + \ No newline at end of file diff --git a/docs/quickstart/hello-world/index.html b/docs/quickstart/hello-world/index.html index d99b59fc..0c1715d3 100644 --- a/docs/quickstart/hello-world/index.html +++ b/docs/quickstart/hello-world/index.html @@ -9,13 +9,13 @@ - +

Hello World

We will now add physics to the scene. We do this by creating a new instance of the World class and adding several rigid bodies to it.

Replace the content of Program.cs with the following code (marked lines indicate the additions to the source code):

using System.Numerics;
using Raylib_cs;
using Jitter2;
using Jitter2.Collision.Shapes;
using Jitter2.Dynamics;
using Jitter2.LinearMath;
using static Raylib_cs.Raylib;

static Matrix4x4 GetRayLibTransformMatrix(RigidBody body)
{
JMatrix ori = body.Orientation;
JVector pos = body.Position;

return new Matrix4x4(ori.M11, ori.M12, ori.M13, pos.X,
ori.M21, ori.M22, ori.M23, pos.Y,
ori.M31, ori.M32, ori.M33, pos.Z,
0, 0, 0, 1.0f);
}

static Texture2D GenCheckedTexture(int size, int checks, Color colorA, Color colorB)
{
Image imageMag = GenImageChecked(size, size, checks, checks, colorA, colorB);
Texture2D textureMag = LoadTextureFromImage(imageMag);
UnloadImage(imageMag);
return textureMag;
}

const int NumberOfBoxes = 12;

// set a hint for anti-aliasing
SetConfigFlags(ConfigFlags.FLAG_MSAA_4X_HINT);

// initialize a 1200x800 px window with a title
InitWindow(1200, 800, "BoxDrop example");

// dynamically create a plane model
Texture2D texture = GenCheckedTexture(10, 1, Color.LIGHTGRAY, Color.GRAY);
Model planeModel = LoadModelFromMesh(GenMeshPlane(10, 10, 10, 10));
SetMaterialTexture(ref planeModel, 0, MaterialMapIndex.MATERIAL_MAP_DIFFUSE, ref texture);

// dynamically create a box model
texture = GenCheckedTexture(2, 1, Color.WHITE, Color.MAGENTA);
Mesh boxMesh = GenMeshCube(1, 1, 1);
Material boxMat = LoadMaterialDefault();
SetMaterialTexture(ref boxMat, MaterialMapIndex.MATERIAL_MAP_DIFFUSE, texture);

// initialize the Jitter physics world
World world = new ();

// add a body representing the plane
RigidBody planeBody = world.CreateRigidBody();
planeBody.AddShape(new BoxShape(10));
planeBody.Position = new JVector(0, -5, 0);
planeBody.IsStatic = true;

// add NumberOfBoxes cubes
for(int i = 0; i < NumberOfBoxes; i++)
{
RigidBody body = world.CreateRigidBody();
body.AddShape(new BoxShape(1));
body.Position = new JVector(0, i * 2 + 0.5f, 0);
}

// create a camera
Camera3D camera = new ()
{
Position = new Vector3(-20.0f, 8.0f, 10.0f),
Target = new Vector3(0.0f, 4.0f, 0.0f),
Up = new Vector3(0.0f, 1.0f, 0.0f),
FovY = 45.0f,
Projection = CameraProjection.CAMERA_PERSPECTIVE
};

// 100 fps target
SetTargetFPS(100);

// simple render loop
while (!WindowShouldClose())
{
BeginDrawing();
ClearBackground(Color.BLUE);

BeginMode3D(camera);

DrawModel(planeModel, Vector3.Zero, 1.0f, Color.WHITE);

world.Step(1.0f / 100.0f, true);

foreach(var body in world.RigidBodies)
{
if(body == planeBody) continue; // do not draw this
DrawMesh(boxMesh, boxMat, GetRayLibTransformMatrix(body));
}

EndMode3D();
DrawText($"{GetFPS()} fps", 10, 10, 20, Color.WHITE);

EndDrawing();
}

CloseWindow();

Running your program, you should now see a few boxes dynamically falling onto the ground.

plane

- + \ No newline at end of file diff --git a/docs/quickstart/project-setup/index.html b/docs/quickstart/project-setup/index.html index 10b9d826..01d491e7 100644 --- a/docs/quickstart/project-setup/index.html +++ b/docs/quickstart/project-setup/index.html @@ -9,13 +9,13 @@ - +

Project Setup

Requirements

Install the .NET 8.0 SDK.

Ensure that dotnet is correctly set up by executing the following command:

dotnet --version

Create a New Console Application and Add Jitter and Raylib

First, create a new directory named "BoxDrop" and navigate into it:

mkdir BoxDrop && cd BoxDrop

Next, create a new console application in this directory and add Raylib-cs and Jitter2:

dotnet new console
dotnet add package Raylib-cs --version 5.0.0
dotnet add package Jitter2 --version 2.2.1

You have completed the setup. If you now execute the following command:

dotnet run

Your console should display: "Hello, World!".

- + \ No newline at end of file diff --git a/docs/quickstart/render-loop/index.html b/docs/quickstart/render-loop/index.html index 81a5c9d6..c42beccc 100644 --- a/docs/quickstart/render-loop/index.html +++ b/docs/quickstart/render-loop/index.html @@ -9,13 +9,13 @@ - +

Setting Up a Render Loop

The first thing we need to do is to familiarize ourselves a bit with Raylib_cs. Replace the content of Program.cs with the following code:

using System.Numerics;
using Raylib_cs;
using static Raylib_cs.Raylib;

static Texture2D GenCheckedTexture(int size, int checks, Color colorA, Color colorB)
{
Image imageMag = GenImageChecked(size, size, checks, checks, colorA, colorB);
Texture2D textureMag = LoadTextureFromImage(imageMag);
UnloadImage(imageMag);
return textureMag;
}

// Set a hint for anti-aliasing
SetConfigFlags(ConfigFlags.FLAG_MSAA_4X_HINT);

// Initialize a 1200x800 px window with a title
InitWindow(1200, 800, "BoxDrop Example");

// Dynamically create a plane model
Texture2D texture = GenCheckedTexture(10, 1, Color.LIGHTGRAY, Color.GRAY);
Model planeModel = LoadModelFromMesh(GenMeshPlane(10, 10, 10, 10));
SetMaterialTexture(ref planeModel, 0, MaterialMapIndex.MATERIAL_MAP_DIFFUSE, ref texture);

// Create a camera
Camera3D camera = new ()
{
Position = new Vector3(-20.0f, 8.0f, 10.0f),
Target = new Vector3(0.0f, 4.0f, 0.0f),
Up = new Vector3(0.0f, 1.0f, 0.0f),
FovY = 45.0f,
Projection = CameraProjection.CAMERA_PERSPECTIVE
};

// Set a target of 100 fps
SetTargetFPS(100);

// Simple render loop
while (!WindowShouldClose())
{
BeginDrawing();
ClearBackground(Color.BLUE);

BeginMode3D(camera);

DrawModel(planeModel, Vector3.Zero, 1.0f, Color.WHITE);

EndMode3D();
DrawText($"{GetFPS()} fps", 10, 10, 20, Color.WHITE);

EndDrawing();
}

CloseWindow();

Running your program should now display a plane:

plane

We will add some physically simulated boxes in the next chapter.

- + \ No newline at end of file diff --git a/docs/webasm/index.html b/docs/webasm/index.html index ffcef981..c38036c0 100644 --- a/docs/webasm/index.html +++ b/docs/webasm/index.html @@ -9,13 +9,13 @@ - +
- + \ No newline at end of file diff --git a/index.html b/index.html index 9ea690a0..629af0f1 100644 --- a/index.html +++ b/index.html @@ -9,13 +9,13 @@ - +
- + \ No newline at end of file diff --git a/markdown-page/index.html b/markdown-page/index.html index d041be77..98e489fb 100644 --- a/markdown-page/index.html +++ b/markdown-page/index.html @@ -9,13 +9,13 @@ - +

Markdown page example

You don't need React to write simple standalone pages.

- + \ No newline at end of file