fbx loader improvements, test map

This commit is contained in:
Dmitry
2019-06-16 16:58:31 +03:00
parent 9c03492a6c
commit ee3f00f89b
17 changed files with 30064 additions and 793 deletions
+235 -241
View File
@@ -5,16 +5,20 @@
</component>
<component name="ChangeListManager">
<list default="true" id="1932b2c4-d6ff-413c-9558-19959667326b" name="Default Changelist" comment="scene graph">
<change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Cargo.lock" beforeDir="false" afterPath="$PROJECT_DIR$/Cargo.lock" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Cargo.toml" beforeDir="false" afterPath="$PROJECT_DIR$/Cargo.toml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/engine/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/engine/mod.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/main.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/math/mat4.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/math/mat4.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/math/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/math/mod.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/math/quat.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/math/quat.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/math/triangulator.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/math/triangulator.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/math/vec2.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/math/vec2.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/math/vec3.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/math/vec3.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/math/vec4.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/math/vec4.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/renderer/renderer.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/renderer/renderer.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/renderer/surface.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/renderer/surface.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/resource/fbx/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/resource/fbx/mod.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/scene/node.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/scene/node.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/utils/pool.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/utils/pool.rs" afterDir="false" />
</list>
<ignored path="$PROJECT_DIR$/target/" />
@@ -28,64 +32,10 @@
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/math/vec3.rs">
<entry file="file://$PROJECT_DIR$/src/resource/fbx/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="294">
<caret line="56" column="11" selection-start-line="56" selection-start-column="11" selection-end-line="56" selection-end-column="11" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/src/math/triangulator.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="340">
<caret line="115" column="51" selection-start-line="115" selection-start-column="51" selection-end-line="115" selection-end-column="51" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libstd/macros.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="387">
<caret line="844" column="17" selection-start-line="844" selection-start-column="17" selection-end-line="844" selection-end-column="17" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="315">
<caret line="67" column="29" lean-forward="true" selection-start-line="67" selection-start-column="29" selection-end-line="67" selection-end-column="29" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/result.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="322">
<caret line="245" column="9" selection-start-line="245" selection-start-column="9" selection-end-line="245" selection-end-column="9" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/main.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="17">
<caret line="1" column="20" selection-start-line="1" selection-start-column="20" selection-end-line="1" selection-end-column="20" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/math/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="330">
<caret line="63" selection-start-line="63" selection-end-line="63" />
<state relative-caret-position="515">
<caret line="320" column="31" selection-start-line="320" selection-start-column="31" selection-end-line="320" selection-end-column="31" />
</state>
</provider>
</entry>
@@ -93,8 +43,53 @@
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/math/mat4.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="530">
<caret line="201" column="11" selection-start-line="201" selection-start-column="11" selection-end-line="201" selection-end-column="11" />
<state relative-caret-position="357">
<caret line="136" selection-start-line="136" selection-end-line="136" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/resource/texture.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="527">
<caret line="31" selection-start-line="31" selection-end-line="31" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/scene/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="884">
<caret line="52" column="11" selection-start-line="52" selection-start-column="11" selection-end-line="52" selection-end-column="11" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/renderer/surface.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="972">
<caret line="338" column="13" selection-start-line="338" selection-start-column="13" selection-end-line="338" selection-end-column="13" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/math/vec3.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="629">
<caret line="42" column="30" lean-forward="true" selection-start-line="42" selection-start-column="30" selection-end-line="42" selection-end-column="30" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/src/renderer/renderer.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="422">
<caret line="125" column="41" selection-start-line="125" selection-start-column="41" selection-end-line="125" selection-end-column="41" />
</state>
</provider>
</entry>
@@ -103,16 +98,25 @@
<entry file="file://$PROJECT_DIR$/src/math/vec2.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="34">
<caret line="2" column="27" selection-start-line="2" selection-start-column="27" selection-end-line="2" selection-end-column="27" />
<caret line="2" column="38" selection-start-line="2" selection-start-column="38" selection-end-line="2" selection-end-column="38" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/resource/mod.rs">
<entry file="file://$PROJECT_DIR$/src/main.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="17">
<caret line="1" column="10" selection-start-line="1" selection-start-column="10" selection-end-line="1" selection-end-column="10" />
<state relative-caret-position="565">
<caret line="264" column="29" lean-forward="true" selection-start-line="264" selection-start-column="29" selection-end-line="264" selection-end-column="29" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/engine/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="864">
<caret line="109" column="11" selection-start-line="109" selection-start-column="11" selection-end-line="109" selection-end-column="11" />
</state>
</provider>
</entry>
@@ -128,16 +132,21 @@
</component>
<component name="FindInProjectRecents">
<findStrings>
<find>b-&gt;</find>
<find>a-&gt;</find>
<find>cursorst</find>
<find>find_node</find>
<find>Handle</find>
<find>type_id</find>
<find>b-&gt;</find>
<find>borrow</find>
<find>materials</find>
</findStrings>
<replaceStrings>
<replace>b.</replace>
</replaceStrings>
</component>
<component name="Git.Settings">
<option name="ROOT_SYNC" value="DONT_SYNC" />
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="IdeDocumentHistory">
@@ -145,28 +154,29 @@
<list>
<option value="$PROJECT_DIR$/src/pool.rs" />
<option value="$PROJECT_DIR$/src/vec3.rs" />
<option value="$PROJECT_DIR$/src/math/vec4.rs" />
<option value="$PROJECT_DIR$/src/core/mod.rs" />
<option value="$PROJECT_DIR$/src/core/pool.rs" />
<option value="$PROJECT_DIR$/src/scene/scene.rs" />
<option value="$PROJECT_DIR$/src/renderer/mod.rs" />
<option value="$PROJECT_DIR$/src/resource/texture.rs" />
<option value="$PROJECT_DIR$/src/resource/mod.rs" />
<option value="$PROJECT_DIR$/src/math/mod.rs" />
<option value="$PROJECT_DIR$/src/utils/persistent_pool.rs" />
<option value="$PROJECT_DIR$/src/utils/mod.rs" />
<option value="$PROJECT_DIR$/src/math/quat.rs" />
<option value="$PROJECT_DIR$/src/renderer/mod.rs" />
<option value="$PROJECT_DIR$/src/scene/mod.rs" />
<option value="$PROJECT_DIR$/src/resource/texture.rs" />
<option value="$PROJECT_DIR$/src/renderer/renderer.rs" />
<option value="$PROJECT_DIR$/src/math/vec2.rs" />
<option value="$PROJECT_DIR$/src/math/triangulator.rs" />
<option value="$PROJECT_DIR$/src/scene/node.rs" />
<option value="$PROJECT_DIR$/src/math/vec4.rs" />
<option value="$PROJECT_DIR$/src/renderer/surface.rs" />
<option value="$PROJECT_DIR$/src/engine/mod.rs" />
<option value="$PROJECT_DIR$/src/resource/mod.rs" />
<option value="$PROJECT_DIR$/src/utils/pool.rs" />
<option value="$PROJECT_DIR$/src/scene/node.rs" />
<option value="$PROJECT_DIR$/src/resource/fbx/mod.rs" />
<option value="$PROJECT_DIR$/src/math/mod.rs" />
<option value="$PROJECT_DIR$/src/math/vec2.rs" />
<option value="$PROJECT_DIR$/src/main.rs" />
<option value="$PROJECT_DIR$/src/math/vec3.rs" />
<option value="$PROJECT_DIR$/src/math/mat4.rs" />
<option value="$PROJECT_DIR$/src/math/triangulator.rs" />
<option value="$PROJECT_DIR$/src/math/vec3.rs" />
<option value="$PROJECT_DIR$/src/main.rs" />
<option value="$PROJECT_DIR$/src/renderer/renderer.rs" />
</list>
</option>
</component>
@@ -188,6 +198,8 @@
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="PackagesPane" />
<pane id="Scope" />
<pane id="ProjectPane">
<subPane>
<expand>
@@ -252,18 +264,17 @@
<select />
</subPane>
</pane>
<pane id="PackagesPane" />
<pane id="Scope" />
</panes>
</component>
<component name="PropertiesComponent">
<property name="com.android.tools.idea.instantapp.provision.ProvisionBeforeRunTaskProvider.myTimeStamp" value="1559414534374" />
<property name="com.android.tools.idea.instantapp.provision.ProvisionBeforeRunTaskProvider.myTimeStamp" value="1560693432309" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/../Program Files/Git/bin/git.exe" />
<property name="org.rust.cargo.project.model.PROJECT_DISCOVERY" value="true" />
<property name="project.structure.last.edited" value="Project" />
<property name="project.structure.proportion" value="0.0" />
<property name="project.structure.side.proportion" value="0.0" />
<property name="project.structure.side.proportion" value="0.2" />
<property name="run.code.analysis.last.selected.profile" value="pProject Default" />
<property name="settings.editor.selected.configurable" value="reference.settingsdialog.IDE.editor.colors.Language Defaults" />
<property name="settings.editor.selected.configurable" value="vcs.Git" />
<property name="settings.editor.splitter.proportion" value="0.23435949" />
</component>
<component name="RunDashboard">
@@ -278,7 +289,7 @@
</list>
</option>
</component>
<component name="RunManager" selected="Cargo Command.Test">
<component name="RunManager" selected="Cargo Command.Release">
<configuration name="Debug" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true">
<option name="channel" value="DEFAULT" />
<option name="command" value="run --package rg3d --bin rg3d" />
@@ -309,11 +320,6 @@
<envs />
<method v="2" />
</configuration>
<list>
<item itemvalue="Cargo Command.Release" />
<item itemvalue="Cargo Command.Test" />
<item itemvalue="Cargo Command.Debug" />
</list>
<recent_temporary>
<list>
<item itemvalue="Cargo Command.Debug" />
@@ -383,7 +389,7 @@
<frame x="0" y="0" width="1280" height="1400" extended-state="0" />
<editor active="true" />
<layout>
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.15081967" />
<window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.17295082" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info id="Image Layers" order="2" />
<window_info id="Designer" order="3" />
@@ -392,7 +398,7 @@
<window_info id="Favorites" order="6" side_tool="true" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Find" order="1" weight="0.23264985" />
<window_info active="true" anchor="bottom" id="Run" order="2" sideWeight="0.49925372" visible="true" weight="0.2626183" />
<window_info anchor="bottom" id="Run" order="2" sideWeight="0.49925372" visible="true" weight="0.18690851" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
@@ -422,39 +428,6 @@
<option name="FILTER_TARGETS" value="false" />
</component>
<component name="editorHistoryManager">
<entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.19.0/src/lib.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="5576">
<caret line="344" column="11" selection-start-line="344" selection-start-column="11" selection-end-line="344" selection-end-column="11" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/liballoc/macros.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="731">
<caret line="43" column="17" lean-forward="true" selection-start-line="43" selection-start-column="17" selection-end-line="43" selection-end-column="17" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.19.0/src/window.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="309">
<caret line="250" column="11" selection-start-line="250" selection-start-column="11" selection-end-line="250" selection-end-column="11" />
<folding>
<element signature="e#8111#8112#0" expanded="true" />
<element signature="e#8154#8155#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/num/f32.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="309">
<caret line="356" column="11" selection-start-line="356" selection-start-column="11" selection-end-line="356" selection-end-column="11" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/vec3.rs" />
<entry file="file://$PROJECT_DIR$/src/core/mod.rs" />
<entry file="file://$PROJECT_DIR$/src/core/pool.rs" />
<entry file="file://$PROJECT_DIR$/src/scene/scene.rs" />
@@ -487,13 +460,6 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/math/vec4.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="34">
<caret line="2" column="4" selection-start-line="2" selection-start-column="4" selection-end-line="2" selection-end-column="4" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/image-0.21.0/src/lib.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="527">
@@ -530,17 +496,6 @@
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/clone.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="3400">
<caret line="208" column="11" selection-start-line="208" selection-start-column="11" selection-end-line="208" selection-end-column="11" />
<folding>
<element signature="e#7200#7201#0" expanded="true" />
<element signature="e#7228#7229#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.19.0/src/events.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1428">
@@ -548,13 +503,6 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/renderer/surface.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="5304">
<caret line="312" column="67" selection-start-line="312" selection-start-column="67" selection-end-line="312" selection-end-column="67" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libstd/io/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="479">
@@ -595,31 +543,6 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/engine/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1309">
<caret line="81" column="45" selection-start-line="81" selection-start-column="45" selection-end-line="81" selection-end-column="45" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/str/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1326">
<caret line="78" column="9" selection-start-line="78" selection-start-column="9" selection-end-line="78" selection-end-column="9" />
<folding>
<element signature="e#126234#126235#0" expanded="true" />
<element signature="e#126272#126273#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/slice/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="39780">
<caret line="2405" column="14" selection-start-line="2405" selection-start-column="14" selection-end-line="2405" selection-end-column="14" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/liballoc/collections/linked_list.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="3519">
@@ -627,13 +550,6 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/scene/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="493">
<caret line="29" selection-start-line="29" selection-end-line="29" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/macros.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="731">
@@ -655,17 +571,77 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/resource/texture.rs">
<entry file="file://$PROJECT_DIR$/src/math/plane.rs">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libstd/macros.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="408">
<caret line="24" column="36" selection-start-line="24" selection-start-column="36" selection-end-line="24" selection-end-column="36" />
<state relative-caret-position="14348">
<caret line="844" column="17" selection-start-line="844" selection-start-column="17" selection-end-line="844" selection-end-column="17" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/renderer/renderer.rs">
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="340">
<caret line="20" column="5" selection-start-line="20" selection-start-column="5" selection-end-line="20" selection-end-column="5" />
<state relative-caret-position="1139">
<caret line="67" column="29" selection-start-line="67" selection-start-column="29" selection-end-line="67" selection-end-column="29" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/result.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="4165">
<caret line="245" column="9" selection-start-line="245" selection-start-column="9" selection-end-line="245" selection-end-column="9" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/liballoc/macros.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1087">
<caret line="100" column="13" selection-start-line="100" selection-start-column="13" selection-end-line="100" selection-end-column="13" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/str/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="581">
<caret line="74" column="9" selection-start-line="74" selection-start-column="9" selection-end-line="74" selection-end-column="9" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/math/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="309">
<caret line="38" column="33" selection-start-line="38" selection-start-column="33" selection-end-line="38" selection-end-column="33" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/utils/persistent_pool.rs" />
<entry file="file://$PROJECT_DIR$/src/math/quat.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="850">
<caret line="50" column="21" selection-start-line="50" selection-start-column="11" selection-end-line="50" selection-end-column="21" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/ops/index.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1020">
<caret line="60" column="10" selection-start-line="60" selection-start-column="10" selection-end-line="60" selection-end-column="10" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/clone.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2057">
<caret line="121" column="7" selection-start-line="121" selection-start-column="7" selection-end-line="121" selection-end-column="7" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/slice/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="641">
<caret line="324" column="23" lean-forward="true" selection-start-line="324" selection-start-column="23" selection-end-line="324" selection-end-column="23" />
</state>
</provider>
</entry>
@@ -676,34 +652,17 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/math/plane.rs">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/src/math/quat.rs">
<entry file="file://$PROJECT_DIR$/src/math/triangulator.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="340">
<caret line="20" column="11" selection-start-line="20" selection-start-column="11" selection-end-line="20" selection-end-column="11" />
<state relative-caret-position="666">
<caret line="58" selection-start-line="58" selection-end-line="72" selection-end-column="1" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/utils/pool.rs">
<entry file="file://$PROJECT_DIR$/src/math/vec4.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1649">
<caret line="97" column="17" selection-start-line="97" selection-start-column="17" selection-end-line="97" selection-end-column="17" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/scene/node.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1683">
<caret line="99" column="9" selection-start-line="99" selection-start-column="9" selection-end-line="99" selection-end-column="9" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/resource/fbx/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="187">
<caret line="11" column="4" selection-start-line="11" selection-start-column="4" selection-end-line="11" selection-end-column="4" />
<state>
<caret column="38" selection-start-column="38" selection-end-column="38" />
</state>
</provider>
</entry>
@@ -714,66 +673,101 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/math/mod.rs">
<entry file="file://$PROJECT_DIR$/src/scene/node.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="330">
<caret line="63" selection-start-line="63" selection-end-line="63" />
<state relative-caret-position="813">
<caret line="128" column="11" selection-start-line="128" selection-start-column="11" selection-end-line="128" selection-end-column="11" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/result.rs">
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/cmp.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="322">
<caret line="245" column="9" selection-start-line="245" selection-start-column="9" selection-end-line="245" selection-end-column="9" />
<state relative-caret-position="335">
<caret line="244" column="10" selection-start-line="244" selection-start-column="10" selection-end-line="244" selection-end-column="10" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs">
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libcore/hash/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="315">
<caret line="67" column="29" lean-forward="true" selection-start-line="67" selection-start-column="29" selection-end-line="67" selection-end-column="29" />
<state relative-caret-position="335">
<caret line="174" column="7" selection-start-line="174" selection-start-column="7" selection-end-line="174" selection-end-column="7" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/utils/pool.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="714">
<caret line="52" column="31" selection-start-line="52" selection-start-column="31" selection-end-line="52" selection-end-column="31" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/scene/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="884">
<caret line="52" column="11" selection-start-line="52" selection-start-column="11" selection-end-line="52" selection-end-column="11" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/resource/texture.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="527">
<caret line="31" selection-start-line="31" selection-end-line="31" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/renderer/surface.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="972">
<caret line="338" column="13" selection-start-line="338" selection-start-column="13" selection-end-line="338" selection-end-column="13" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/math/mat4.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="530">
<caret line="201" column="11" selection-start-line="201" selection-start-column="11" selection-end-line="201" selection-end-column="11" />
<state relative-caret-position="357">
<caret line="136" selection-start-line="136" selection-end-line="136" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/math/vec2.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="34">
<caret line="2" column="27" selection-start-line="2" selection-start-column="27" selection-end-line="2" selection-end-column="27" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.rustup/toolchains/stable-x86_64-pc-windows-gnu/lib/rustlib/src/rust/src/libstd/macros.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="387">
<caret line="844" column="17" selection-start-line="844" selection-start-column="17" selection-end-line="844" selection-end-column="17" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/main.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="17">
<caret line="1" column="20" selection-start-line="1" selection-start-column="20" selection-end-line="1" selection-end-column="20" />
<caret line="2" column="38" selection-start-line="2" selection-start-column="38" selection-end-line="2" selection-end-column="38" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/math/vec3.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="294">
<caret line="56" column="11" selection-start-line="56" selection-start-column="11" selection-end-line="56" selection-end-column="11" />
<state relative-caret-position="629">
<caret line="42" column="30" lean-forward="true" selection-start-line="42" selection-start-column="30" selection-end-line="42" selection-end-column="30" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/math/triangulator.rs">
<entry file="file://$PROJECT_DIR$/src/resource/fbx/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="340">
<caret line="115" column="51" selection-start-line="115" selection-start-column="51" selection-end-line="115" selection-end-column="51" />
<state relative-caret-position="515">
<caret line="320" column="31" selection-start-line="320" selection-start-column="31" selection-end-line="320" selection-end-column="31" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/main.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="565">
<caret line="264" column="29" lean-forward="true" selection-start-line="264" selection-start-column="29" selection-end-line="264" selection-end-column="29" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/engine/mod.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="864">
<caret line="109" column="11" selection-start-line="109" selection-start-column="11" selection-end-line="109" selection-end-column="11" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/renderer/renderer.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="422">
<caret line="125" column="41" selection-start-line="125" selection-start-column="41" selection-end-line="125" selection-end-column="41" />
</state>
</provider>
</entry>
+7957
View File
File diff suppressed because it is too large Load Diff
+20841
View File
File diff suppressed because it is too large Load Diff
+59 -35
View File
@@ -7,47 +7,17 @@ use std::cell::*;
use std::path::*;
use crate::resource::texture::*;
pub struct Engine {
renderer: Renderer,
scenes: Pool<Scene>,
events: Vec<glutin::Event>,
running: bool,
pub struct ResourceManager {
resources: Vec<Rc<RefCell<Resource>>>
}
impl Engine {
pub fn new() -> Engine {
Engine {
scenes: Pool::new(),
renderer: Renderer::new(),
events: Vec::new(),
running: true,
impl ResourceManager {
pub fn new() -> ResourceManager {
ResourceManager {
resources: Vec::new()
}
}
pub fn add_scene(&mut self, scene: Scene) -> Handle<Scene> {
self.scenes.spawn(scene)
}
pub fn borrow_scene(&self, handle: &Handle<Scene>) -> Option<&Scene> {
if let Some(scene) = self.scenes.borrow(handle) {
return Some(scene);
}
None
}
pub fn borrow_scene_mut(&mut self, handle: &Handle<Scene>) -> Option<&mut Scene> {
if let Some(scene) = self.scenes.borrow_mut(handle) {
return Some(scene);
}
None
}
pub fn is_running(&self) -> bool {
self.running
}
pub fn request_texture(&mut self, path: &Path) -> Option<Rc<RefCell<Resource>>> {
for existing in self.resources.iter() {
let resource = existing.borrow_mut();
@@ -73,6 +43,58 @@ impl Engine {
// Fail
None
}
}
pub struct Engine {
renderer: Renderer,
scenes: Pool<Scene>,
events: Vec<glutin::Event>,
running: bool,
resource_manager: ResourceManager,
}
impl Engine {
#[inline]
pub fn new() -> Engine {
Engine {
scenes: Pool::new(),
renderer: Renderer::new(),
events: Vec::new(),
running: true,
resource_manager: ResourceManager::new()
}
}
#[inline]
pub fn add_scene(&mut self, scene: Scene) -> Handle<Scene> {
self.scenes.spawn(scene)
}
#[inline]
pub fn borrow_scene(&self, handle: &Handle<Scene>) -> Option<&Scene> {
if let Some(scene) = self.scenes.borrow(handle) {
return Some(scene);
}
None
}
#[inline]
pub fn borrow_scene_mut(&mut self, handle: &Handle<Scene>) -> Option<&mut Scene> {
if let Some(scene) = self.scenes.borrow_mut(handle) {
return Some(scene);
}
None
}
#[inline]
pub fn is_running(&self) -> bool {
self.running
}
#[inline]
pub fn get_resource_manager(&mut self) -> &mut ResourceManager {
&mut self.resource_manager
}
pub fn update(&mut self) {
let client_size = self.renderer.context.get_inner_size().unwrap();
@@ -95,7 +117,7 @@ impl Engine {
}
pub fn render(&mut self) {
self.renderer.upload_resources(&mut self.resources);
self.renderer.upload_resources(&mut self.resource_manager.resources);
let mut alive_scenes: Vec<&Scene> = Vec::new();
for i in 0..self.scenes.capacity() {
@@ -106,10 +128,12 @@ impl Engine {
self.renderer.render(alive_scenes.as_slice());
}
#[inline]
pub fn stop(&mut self) {
self.running = false;
}
#[inline]
pub fn pop_event(&mut self) -> Option<glutin::Event> {
self.events.pop()
}
+34 -29
View File
@@ -1,23 +1,29 @@
#![allow(dead_code)]
extern crate image;
extern crate glutin;
use std::path::*;
mod utils;
use utils::pool::*;
mod math;
use math::vec2::*;
use math::vec3::*;
use math::quat::*;
mod scene;
use scene::node::*;
use scene::*;
mod renderer;
mod engine;
use engine::*;
mod resource;
@@ -44,7 +50,7 @@ impl Player {
camera.set_local_position(Vec3 { x: 0.0, y: 2.0, z: 0.0 });
let mut pivot = Node::new(NodeKind::Base);
pivot.set_local_position(Vec3 { x: 0.0, y: 0.0, z: 20.0 });
pivot.set_local_position(Vec3 { x: -1.0, y: 0.0, z: 1.0 });
let camera_handle = scene.add_node(camera);
let pivot_handle = scene.add_node(pivot);
@@ -61,7 +67,7 @@ impl Player {
},
yaw: 0.0,
pitch: 0.0,
last_mouse_pos: Vec2::new()
last_mouse_pos: Vec2::new(),
}
}
@@ -72,20 +78,20 @@ impl Player {
let mut velocity = Vec3::new();
if self.controller.move_forward {
velocity -= look;
}
if self.controller.move_backward {
velocity += look;
}
if self.controller.move_backward {
velocity -= look;
}
if self.controller.move_left {
velocity -= side;
velocity += side;
}
if self.controller.move_right {
velocity += side;
velocity -= side;
}
if let Ok(normalized_velocity) = velocity.normalized() {
pivot_node.offset(normalized_velocity);
pivot_node.offset(normalized_velocity.scale(0.2));
}
pivot_node.set_local_rotation(Quat::from_axis_angle(Vec3::up(), self.yaw.to_radians()));
@@ -100,7 +106,6 @@ impl Player {
use glutin::*;
match event {
WindowEvent::CursorMoved { position, .. } => {
let mouse_velocity = Vec2 {
x: position.x as f32 - self.last_mouse_pos.x,
@@ -109,10 +114,10 @@ impl Player {
let sens: f32 = 0.3;
self.pitch -= mouse_velocity.y * sens;
self.pitch += mouse_velocity.y * sens;
self.yaw -= mouse_velocity.x * sens;
if self.pitch > 90.0 {
if self.pitch > 90.0 {
self.pitch = 90.0;
} else if self.pitch < -90.0 {
self.pitch = -90.0;
@@ -120,9 +125,9 @@ impl Player {
self.last_mouse_pos = Vec2 {
x: position.x as f32,
y: position.y as f32
y: position.y as f32,
};
},
}
WindowEvent::KeyboardInput { input, .. } => {
match input.state {
@@ -136,7 +141,7 @@ impl Player {
_ => ()
}
}
},
}
ElementState::Released => {
if let Some(key) = input.virtual_keycode {
match key {
@@ -173,21 +178,21 @@ impl Level {
let mut scene = Scene::new();
// Load some test models
resource::fbx::load_to_scene(&mut scene, Path::new("data/models/cube.fbx"));
// Create floor
{
let mut floor_mesh = Mesh::default();
floor_mesh.make_cube();
if let Some(floor_tex) = engine.request_texture(Path::new("data/textures/floor.png")) {
floor_mesh.apply_texture(floor_tex);
}
let mut floor_node = Node::new(NodeKind::Mesh(floor_mesh));
floor_node.set_local_scale(Vec3 { x: 100.0, y: 0.1, z: 100.0 });
scene.add_node(floor_node);
if let Err(err_msg) = resource::fbx::load_to_scene(
&mut scene, engine.get_resource_manager(), Path::new("data/models/map.fbx")) {
println!("{}", err_msg);
} else {
println!("Map loaded!");
}
match resource::fbx::load_to_scene(&mut scene, engine.get_resource_manager(), Path::new("data/models/ripper.fbx")) {
Ok(node_handle) => {
if let Some(node) = scene.borrow_node_mut(&node_handle) {
node.set_local_position(Vec3::make(-1.0, 0.0, -1.0));
}
}
Err(err_msg) => println!("{}", err_msg)
}
// Create cubes
for i in 0..3 {
@@ -195,7 +200,7 @@ impl Level {
for k in 0..3 {
let mut cube_mesh = Mesh::default();
cube_mesh.make_cube();
if let Some(ref cube_t) = engine.request_texture(Path::new("data/textures/box.png")) {
if let Some(ref cube_t) = engine.get_resource_manager().request_texture(Path::new("data/textures/box.png")) {
cube_mesh.apply_texture(cube_t.clone());
}
let mut cube_node = Node::new(NodeKind::Mesh(cube_mesh));
+10 -2
View File
@@ -136,7 +136,7 @@ impl Mat4 {
}
pub fn look_at(eye: Vec3, at: Vec3, up: Vec3) -> Result<Mat4, &'static str> {
let zaxis = (at - eye).normalized()?;
let zaxis = (eye - at).normalized()?;
let xaxis = up.cross(&zaxis).normalized()?;
let yaxis = zaxis.cross(&xaxis).normalized()?;
@@ -159,7 +159,7 @@ impl Mat4 {
-xaxis.dot(&eye),
-yaxis.dot(&eye),
-zaxis.dot(&eye), // ????????????
-zaxis.dot(&eye),
1.0,
]
})
@@ -206,6 +206,14 @@ impl Mat4 {
z: v.x * self.f[2] + v.y * self.f[6] + v.z * self.f[10] + self.f[14]
}
}
pub fn transform_vector_normal(&self, v: Vec3) -> Vec3 {
Vec3 {
x: v.x * self.f[0] + v.y * self.f[4] + v.z * self.f[8],
y: v.x * self.f[1] + v.y * self.f[5] + v.z * self.f[9],
z: v.x * self.f[2] + v.y * self.f[6] + v.z * self.f[10]
}
}
}
impl ops::Mul<Self> for Mat4 {
+10 -11
View File
@@ -17,28 +17,27 @@ pub struct Rect<T> {
#[derive(Copy, Clone)]
pub enum PlaneClass {
oXY,
oYZ,
oXZ,
XY,
YZ,
XZ,
}
pub fn classify_plane(normal: Vec3) -> PlaneClass {
let mut longest = 0.0f32;
let mut class = PlaneClass::oXY;
let mut class = PlaneClass::XY;
if normal.x.abs() > longest {
longest = normal.x.abs();
class = PlaneClass::oYZ;
class = PlaneClass::YZ;
}
if normal.y.abs() > longest {
longest = normal.y.abs();
class = PlaneClass::oXZ;
class = PlaneClass::XZ;
}
if normal.z.abs() > longest {
longest = normal.z.abs();
class = PlaneClass::oXY;
class = PlaneClass::XY;
}
class
@@ -67,9 +66,9 @@ pub fn get_signed_triangle_area(v1: Vec2, v2: Vec2, v3: Vec2) -> f32 {
pub fn vec3_to_vec2_by_plane(plane_class: PlaneClass, normal: Vec3, point: Vec3) -> Vec2 {
match plane_class {
PlaneClass::oXY => if normal.z < 0.0 { Vec2::make(point.y, point.x) } else { Vec2::make(point.x, point.y) }
PlaneClass::oXZ => if normal.y < 0.0 { Vec2::make(point.x, point.z) } else { Vec2::make(point.z, point.x) }
PlaneClass::oYZ => if normal.x < 0.0 { Vec2::make(point.z, point.y) } else { Vec2::make(point.y, point.z) }
PlaneClass::XY => if normal.z < 0.0 { Vec2::make(point.y, point.x) } else { Vec2::make(point.x, point.y) }
PlaneClass::XZ => if normal.y < 0.0 { Vec2::make(point.x, point.z) } else { Vec2::make(point.z, point.x) }
PlaneClass::YZ => if normal.x < 0.0 { Vec2::make(point.z, point.y) } else { Vec2::make(point.y, point.z) }
}
}
+37 -1
View File
@@ -1,4 +1,5 @@
use crate::math::vec3::*;
use std::ops;
#[derive(Copy, Clone)]
pub struct Quat {
@@ -8,6 +9,15 @@ pub struct Quat {
pub w: f32,
}
pub enum RotationOrder {
XYZ,
XZY,
YZX,
YXZ,
ZXY,
ZYX,
}
impl Quat {
pub fn new() -> Self {
Quat {
@@ -37,4 +47,30 @@ impl Quat {
w: half_angle.cos(),
}
}
}
pub fn from_euler(euler_radians: Vec3, order: RotationOrder) -> Self {
let qx: Quat = Quat::from_axis_angle(Vec3::make(1.0, 0.0, 0.0), euler_radians.x);
let qy: Quat = Quat::from_axis_angle(Vec3::make(0.0, 1.0, 0.0), euler_radians.y);
let qz: Quat = Quat::from_axis_angle(Vec3::make(0.0, 0.0, 1.0), euler_radians.z);
match order {
RotationOrder::XYZ => qz * qy * qx,
RotationOrder::XZY => qy * qz * qx,
RotationOrder::YZX => qx * qz * qy,
RotationOrder::YXZ => qz * qx * qy,
RotationOrder::ZXY => qy * qx * qz,
RotationOrder::ZYX => qx * qy * qz,
}
}
}
impl ops::Mul<Self> for Quat {
type Output = Self;
fn mul(self, b: Self) -> Self {
Self {
x: self.w * b.x + self.x * b.w + self.y * b.z - self.z * b.y,
y: self.w * b.y + self.y * b.w + self.z * b.x - self.x * b.z,
z: self.w * b.z + self.z * b.w + self.x * b.y - self.y * b.x,
w: self.w * b.w - self.x * b.x - self.y * b.y - self.z * b.z,
}
}
}
+2 -2
View File
@@ -5,9 +5,9 @@
use super::vec2::*;
use super::vec3::*;
use super::mat4::*;
use super::quat::*;
use crate::math;
use std::fmt;
use crate::math::quat::Quat;
///
/// Polygon vertex
@@ -62,7 +62,7 @@ impl fmt::Debug for Polygon {
let mut i = self.head;
loop {
let vertex = &self.vertices[i];
writeln!(f, "Vertex {:?}; {} {} {}", vertex.position, vertex.prev, vertex.index, vertex.next);
writeln!(f, "Vertex {:?}; {} {} {}", vertex.position, vertex.prev, vertex.index, vertex.next)?;
i = self.vertices[i].next;
if i == self.head {
break;
+1 -1
View File
@@ -1,6 +1,6 @@
use std::ops;
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Vec2 {
pub x: f32,
pub y: f32,
+8 -2
View File
@@ -1,7 +1,6 @@
use std::ops;
use super::mat4::*;
#[derive(Copy, Clone)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Vec3 {
pub x: f32,
pub y: f32,
@@ -37,6 +36,13 @@ impl Vec3 {
}
}
pub fn scale(&self, scalar: f32) -> Self {
Vec3 {
x: self.x * scalar,
y: self.y * scalar,
z: self.z * scalar
}
}
pub fn right() -> Self {
Vec3 {
+5 -5
View File
@@ -1,9 +1,9 @@
#[derive(Copy, Clone)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Vec4 {
x: f32,
y: f32,
z: f32,
w: f32,
pub x: f32,
pub y: f32,
pub z: f32,
pub w: f32,
}
impl Vec4 {
+14 -16
View File
@@ -9,7 +9,7 @@ use crate::scene::node::*;
use crate::renderer::surface::*;
use crate::resource::*;
use std::rc::*;
use std::ffi::{c_void};
use std::ffi::c_void;
use std::cell::*;
pub fn check_gl_error() {
@@ -172,7 +172,7 @@ impl Renderer {
).unwrap();
Self {
context: context,
context,
events_loop: el,
flat_shader: GpuProgram::from_source(&vertex_source, &fragment_source).unwrap(),
traversal_stack: Vec::new(),
@@ -239,19 +239,17 @@ impl Renderer {
self.cameras.clear();
self.traversal_stack.clear();
self.traversal_stack.push(scene.root.clone());
while !self.traversal_stack.is_empty() {
if let Some(node_handle) = self.traversal_stack.pop() {
if let Some(node) = scene.borrow_node(&node_handle) {
match node.borrow_kind() {
NodeKind::Mesh(_) => self.meshes.push(node_handle),
NodeKind::Light(_) => self.lights.push(node_handle),
NodeKind::Camera(_) => self.cameras.push(node_handle),
_ => ()
}
// Queue children for render
for child_handle in node.children.iter() {
self.traversal_stack.push(child_handle.clone());
}
while let Some(node_handle) = self.traversal_stack.pop() {
if let Some(node) = scene.borrow_node(&node_handle) {
match node.borrow_kind() {
NodeKind::Mesh(_) => self.meshes.push(node_handle),
NodeKind::Light(_) => self.lights.push(node_handle),
NodeKind::Camera(_) => self.cameras.push(node_handle),
_ => ()
}
// Queue children for render
for child_handle in node.children.iter() {
self.traversal_stack.push(child_handle.clone());
}
}
}
@@ -289,7 +287,7 @@ impl Renderer {
}
if let NodeKind::Mesh(mesh) = node.borrow_kind() {
for surface in mesh.surfaces.iter() {
for surface in mesh.get_surfaces().iter() {
surface.draw();
}
}
+203 -183
View File
@@ -1,57 +1,71 @@
use crate::math::vec3::*;
use crate::math::vec2::*;
use crate::math::vec4::*;
use crate::math::{vec2::*, vec3::*, vec4::*};
use crate::renderer::renderer::*;
use crate::renderer::gl;
use crate::renderer::gl::types::*;
use std::ffi::c_void;
use std::rc::Rc;
use std::cell::RefCell;
use std::{ffi::c_void, rc::Rc, cell::RefCell, mem::size_of, fmt};
use crate::resource::*;
#[derive(Copy, Clone, Debug)]
pub struct Vertex {
pub position: Vec3,
pub tex_coord: Vec2,
pub normal: Vec3,
pub tangent: Vec4,
}
pub struct SurfaceSharedData {
need_upload: bool,
vbo: GLuint,
vao: GLuint,
ebo: GLuint,
positions: Vec<Vec3>,
normals: Vec<Vec3>,
tex_coords: Vec<Vec2>,
tangents: Vec<Vec4>,
vertices: Vec<Vertex>,
indices: Vec<i32>,
}
impl SurfaceSharedData {
fn new() -> Self {
pub fn new() -> Self {
let mut vbo: GLuint = 0;
let mut ebo: GLuint = 0;
let mut vao: GLuint = 0;
unsafe {
gl::GenBuffers(1, &mut vbo);
gl::GenBuffers(1, &mut ebo);
gl::GenVertexArrays(1, &mut vao);
}
Self {
need_upload: true,
vbo,
vao,
ebo,
positions: Vec::new(),
normals: Vec::new(),
tex_coords: Vec::new(),
tangents: Vec::new(),
vbo, vao, ebo,
vertices: Vec::new(),
indices: Vec::new(),
}
}
pub fn add_vertex(&mut self, vertex: Vertex) {
self.vertices.push(vertex);
}
/// Inserts vertex or its index. Performs optimizing insertion with checking if such
/// vertex already exists.
pub fn insert_vertex(&mut self, vertex: Vertex) {
// Reverse search is much faster because it is most likely that we'll find identic
// vertex at the end of the array.
self.indices.push(match self.vertices.iter().rposition(|v| {
v.position == vertex.position && v.normal == vertex.normal && v.tex_coord == vertex.tex_coord
}) {
Some(exisiting_index) => exisiting_index as i32, // Already have such vertex
None => { // No such vertex, add it
let index = self.vertices.len() as i32;
self.vertices.push(vertex);
index
}
});
self.need_upload = true;
}
pub fn upload(&mut self) {
let positions_bytes = self.positions.len() * std::mem::size_of::<Vec3>();
let tex_coords_bytes = self.tex_coords.len() * std::mem::size_of::<Vec2>();
let normals_bytes = self.normals.len() * std::mem::size_of::<Vec3>();
let tangents_bytes = self.tangents.len() * std::mem::size_of::<Vec4>();
let total_size_bytes = positions_bytes + normals_bytes + tex_coords_bytes + tangents_bytes;
let total_size_bytes = self.vertices.len() * std::mem::size_of::<Vertex>();
unsafe {
gl::BindVertexArray(self.vao);
@@ -67,68 +81,32 @@ impl SurfaceSharedData {
gl::BindBuffer(gl::ARRAY_BUFFER, self.vbo);
gl::BufferData(gl::ARRAY_BUFFER,
total_size_bytes as GLsizeiptr,
std::ptr::null(),
self.vertices.as_ptr() as *const GLvoid,
gl::STATIC_DRAW);
let pos_offset = 0;
let mut size = positions_bytes;
gl::BufferSubData(gl::ARRAY_BUFFER,
pos_offset as GLsizeiptr,
size as GLsizeiptr,
self.positions.as_ptr() as *const c_void);
let mut offset = 0;
let tex_coord_offset = pos_offset + size;
size = tex_coords_bytes;
gl::BufferSubData(gl::ARRAY_BUFFER,
tex_coord_offset as GLsizeiptr,
size as GLsizeiptr,
self.tex_coords.as_ptr() as *const c_void);
let normals_offset = tex_coord_offset + size;
size = normals_bytes;
gl::BufferSubData(gl::ARRAY_BUFFER,
normals_offset as GLsizeiptr,
size as GLsizeiptr,
self.normals.as_ptr() as *const c_void);
let tangents_offset = normals_offset + size;
size = tangents_bytes;
gl::BufferSubData(gl::ARRAY_BUFFER,
tangents_offset as GLsizeiptr,
size as GLsizeiptr,
self.tangents.as_ptr() as *const c_void);
// Setup attribute locations
gl::VertexAttribPointer(0,
3,
gl::FLOAT,
gl::FALSE,
std::mem::size_of::<Vec3>() as GLint,
pos_offset as *const c_void);
// Positions
gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE,
size_of::<Vertex>() as GLint, offset as *const c_void);
gl::EnableVertexAttribArray(0);
offset += size_of::<Vec3>();
gl::VertexAttribPointer(1,
2,
gl::FLOAT,
gl::FALSE,
std::mem::size_of::<Vec2>() as GLint,
tex_coord_offset as *const c_void);
// Texture coordinates
gl::VertexAttribPointer(1, 2, gl::FLOAT, gl::FALSE,
size_of::<Vertex>() as GLint, offset as *const c_void);
gl::EnableVertexAttribArray(1);
offset += size_of::<Vec2>();
gl::VertexAttribPointer(2,
3,
gl::FLOAT,
gl::FALSE,
std::mem::size_of::<Vec3>() as GLint,
normals_offset as *const c_void);
// Normals
gl::VertexAttribPointer(2, 3, gl::FLOAT, gl::FALSE,
size_of::<Vertex>() as GLint, offset as *const c_void);
gl::EnableVertexAttribArray(2);
offset += size_of::<Vec3>();
gl::VertexAttribPointer(2,
3,
gl::FLOAT,
gl::FALSE,
std::mem::size_of::<Vec4>() as GLint,
tangents_offset as *const c_void);
// Tangents
gl::VertexAttribPointer(3, 4, gl::FLOAT, gl::FALSE,
size_of::<Vertex>() as GLint, offset as *const c_void);
gl::EnableVertexAttribArray(3);
gl::BindVertexArray(0);
@@ -144,118 +122,162 @@ impl SurfaceSharedData {
pub fn make_cube() -> Self {
let mut data = Self::new();
data.positions = vec![
data.vertices = vec![
// Front
Vec3 { x: -0.5, y: -0.5, z: 0.5 },
Vec3 { x: -0.5, y: 0.5, z: 0.5 },
Vec3 { x: 0.5, y: 0.5, z: 0.5 },
Vec3 { x: 0.5, y: -0.5, z: 0.5 },
Vertex {
position: Vec3 { x: -0.5, y: -0.5, z: 0.5 },
normal: Vec3 { x: 0.0, y: 0.0, z: 1.0 },
tex_coord: Vec2 { x: 0.0, y: 0.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: -0.5, y: 0.5, z: 0.5 },
normal: Vec3 { x: 0.0, y: 0.0, z: 1.0 },
tex_coord: Vec2 { x: 0.0, y: 1.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: 0.5, y: 0.5, z: 0.5 },
normal: Vec3 { x: 0.0, y: 0.0, z: 1.0 },
tex_coord: Vec2 { x: 1.0, y: 1.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: 0.5, y: -0.5, z: 0.5 },
normal: Vec3 { x: 0.0, y: 0.0, z: 1.0 },
tex_coord: Vec2 { x: 1.0, y: 0.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
// Back
Vec3 { x: -0.5, y: -0.5, z: -0.5 },
Vec3 { x: -0.5, y: 0.5, z: -0.5 },
Vec3 { x: 0.5, y: 0.5, z: -0.5 },
Vec3 { x: 0.5, y: -0.5, z: -0.5 },
Vertex {
position: Vec3 { x: -0.5, y: -0.5, z: -0.5 },
normal: Vec3 { x: 0.0, y: 0.0, z: -1.0 },
tex_coord: Vec2 { x: 0.0, y: 0.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: -0.5, y: 0.5, z: -0.5 },
normal: Vec3 { x: 0.0, y: 0.0, z: -1.0 },
tex_coord: Vec2 { x: 0.0, y: 1.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: 0.5, y: 0.5, z: -0.5 },
normal: Vec3 { x: 0.0, y: 0.0, z: -1.0 },
tex_coord: Vec2 { x: 1.0, y: 1.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: 0.5, y: -0.5, z: -0.5 },
normal: Vec3 { x: 0.0, y: 0.0, z: -1.0 },
tex_coord: Vec2 { x: 1.0, y: 0.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
// Left
Vec3 { x: -0.5, y: -0.5, z: -0.5 },
Vec3 { x: -0.5, y: 0.5, z: -0.5 },
Vec3 { x: -0.5, y: 0.5, z: 0.5 },
Vec3 { x: -0.5, y: -0.5, z: 0.5 },
Vertex {
position: Vec3 { x: -0.5, y: -0.5, z: -0.5 },
normal: Vec3 { x: -1.0, y: 0.0, z: 0.0 },
tex_coord: Vec2 { x: 0.0, y: 0.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: -0.5, y: 0.5, z: -0.5 },
normal: Vec3 { x: -1.0, y: 0.0, z: 0.0 },
tex_coord: Vec2 { x: 0.0, y: 1.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: -0.5, y: 0.5, z: 0.5 },
normal: Vec3 { x: -1.0, y: 0.0, z: 0.0 },
tex_coord: Vec2 { x: 1.0, y: 1.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: -0.5, y: -0.5, z: 0.5 },
normal: Vec3 { x: -1.0, y: 0.0, z: 0.0 },
tex_coord: Vec2 { x: 1.0, y: 0.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
// Right
Vec3 { x: 0.5, y: -0.5, z: -0.5 },
Vec3 { x: 0.5, y: 0.5, z: -0.5 },
Vec3 { x: 0.5, y: 0.5, z: 0.5 },
Vec3 { x: 0.5, y: -0.5, z: 0.5 },
Vertex {
position: Vec3 { x: 0.5, y: -0.5, z: -0.5 },
normal: Vec3 { x: 1.0, y: 0.0, z: 0.0 },
tex_coord: Vec2 { x: 0.0, y: 0.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: 0.5, y: 0.5, z: -0.5 },
normal: Vec3 { x: 1.0, y: 0.0, z: 0.0 },
tex_coord: Vec2 { x: 0.0, y: 1.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: 0.5, y: 0.5, z: 0.5 },
normal: Vec3 { x: 1.0, y: 0.0, z: 0.0 },
tex_coord: Vec2 { x: 1.0, y: 1.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: 0.5, y: -0.5, z: 0.5 },
normal: Vec3 { x: 1.0, y: 0.0, z: 0.0 },
tex_coord: Vec2 { x: 1.0, y: 0.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
// Top
Vec3 { x: -0.5, y: 0.5, z: 0.5 },
Vec3 { x: -0.5, y: 0.5, z: -0.5 },
Vec3 { x: 0.5, y: 0.5, z: -0.5 },
Vec3 { x: 0.5, y: 0.5, z: 0.5 },
Vertex {
position: Vec3 { x: -0.5, y: 0.5, z: 0.5 },
normal: Vec3 { x: 0.0, y: 1.0, z: 0.0 },
tex_coord: Vec2 { x: 0.0, y: 0.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: -0.5, y: 0.5, z: -0.5 },
normal: Vec3 { x: 0.0, y: 1.0, z: 0.0 },
tex_coord: Vec2 { x: 0.0, y: 1.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: 0.5, y: 0.5, z: -0.5 },
normal: Vec3 { x: 0.0, y: 1.0, z: 0.0 },
tex_coord: Vec2 { x: 1.0, y: 1.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: 0.5, y: 0.5, z: 0.5 },
normal: Vec3 { x: 0.0, y: 1.0, z: 0.0 },
tex_coord: Vec2 { x: 1.0, y: 0.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
// Bottom
Vec3 { x: -0.5, y: -0.5, z: 0.5 },
Vec3 { x: -0.5, y: -0.5, z: -0.5 },
Vec3 { x: 0.5, y: -0.5, z: -0.5 },
Vec3 { x: 0.5, y: -0.5, z: 0.5 },
];
data.normals = vec![
// Front
Vec3 { x: 0.0, y: 0.0, z: 1.0 },
Vec3 { x: 0.0, y: 0.0, z: 1.0 },
Vec3 { x: 0.0, y: 0.0, z: 1.0 },
Vec3 { x: 0.0, y: 0.0, z: 1.0 },
// Back
Vec3 { x: 0.0, y: 0.0, z: -1.0 },
Vec3 { x: 0.0, y: 0.0, z: -1.0 },
Vec3 { x: 0.0, y: 0.0, z: -1.0 },
Vec3 { x: 0.0, y: 0.0, z: -1.0 },
// Left
Vec3 { x: -1.0, y: 0.0, z: 0.0 },
Vec3 { x: -1.0, y: 0.0, z: 0.0 },
Vec3 { x: -1.0, y: 0.0, z: 0.0 },
Vec3 { x: -1.0, y: 0.0, z: 0.0 },
// Right
Vec3 { x: 1.0, y: 0.0, z: 0.0 },
Vec3 { x: 1.0, y: 0.0, z: 0.0 },
Vec3 { x: 1.0, y: 0.0, z: 0.0 },
Vec3 { x: 1.0, y: 0.0, z: 0.0 },
// Top
Vec3 { x: 0.0, y: 1.0, z: 0.0 },
Vec3 { x: 0.0, y: 1.0, z: 0.0 },
Vec3 { x: 0.0, y: 1.0, z: 0.0 },
Vec3 { x: 0.0, y: 1.0, z: 0.0 },
// Bottom
Vec3 { x: 0.0, y: -1.0, z: 0.0 },
Vec3 { x: 0.0, y: -1.0, z: 0.0 },
Vec3 { x: 0.0, y: -1.0, z: 0.0 },
Vec3 { x: 0.0, y: -1.0, z: 0.0 },
];
data.tex_coords = vec![
// Front
Vec2 { x: 0.0, y: 0.0 },
Vec2 { x: 0.0, y: 1.0 },
Vec2 { x: 1.0, y: 1.0 },
Vec2 { x: 1.0, y: 0.0 },
// Back
Vec2 { x: 0.0, y: 0.0 },
Vec2 { x: 0.0, y: 1.0 },
Vec2 { x: 1.0, y: 1.0 },
Vec2 { x: 1.0, y: 0.0 },
// Left
Vec2 { x: 0.0, y: 0.0 },
Vec2 { x: 0.0, y: 1.0 },
Vec2 { x: 1.0, y: 1.0 },
Vec2 { x: 1.0, y: 0.0 },
// Right
Vec2 { x: 0.0, y: 0.0 },
Vec2 { x: 0.0, y: 1.0 },
Vec2 { x: 1.0, y: 1.0 },
Vec2 { x: 1.0, y: 0.0 },
// Top
Vec2 { x: 0.0, y: 0.0 },
Vec2 { x: 0.0, y: 1.0 },
Vec2 { x: 1.0, y: 1.0 },
Vec2 { x: 1.0, y: 0.0 },
// Bottom
Vec2 { x: 0.0, y: 0.0 },
Vec2 { x: 0.0, y: 1.0 },
Vec2 { x: 1.0, y: 1.0 },
Vec2 { x: 1.0, y: 0.0 },
Vertex {
position: Vec3 { x: -0.5, y: -0.5, z: 0.5 },
normal: Vec3 { x: 0.0, y: -1.0, z: 0.0 },
tex_coord: Vec2 { x: 0.0, y: 0.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: -0.5, y: -0.5, z: -0.5 },
normal: Vec3 { x: 0.0, y: -1.0, z: 0.0 },
tex_coord: Vec2 { x: 0.0, y: 1.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: 0.5, y: -0.5, z: -0.5 },
normal: Vec3 { x: 0.0, y: -1.0, z: 0.0 },
tex_coord: Vec2 { x: 1.0, y: 1.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
Vertex {
position: Vec3 { x: 0.5, y: -0.5, z: 0.5 },
normal: Vec3 { x: 0.0, y: -1.0, z: 0.0 },
tex_coord: Vec2 { x: 1.0, y: 0.0 },
tangent: Vec4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 },
},
];
data.indices = vec![
@@ -287,15 +309,13 @@ impl Drop for SurfaceSharedData {
}
}
type SurfaceSharedDataRef = Rc<RefCell<SurfaceSharedData>>;
pub struct Surface {
pub(crate) data: SurfaceSharedDataRef,
pub(crate) data: Rc<RefCell<SurfaceSharedData>>,
pub(crate) texture: Option<Rc<RefCell<Resource>>>,
}
impl Surface {
pub fn new(data: &SurfaceSharedDataRef) -> Self {
pub fn new(data: &Rc<RefCell<SurfaceSharedData>>) -> Self {
Self {
data: data.clone(),
texture: Option::None,
+527 -235
View File
@@ -1,12 +1,12 @@
use std::{rc::Rc, path::*, fs::File, io::Read, cell::RefCell, collections::HashMap};
use crate::utils::pool::*;
use std::path::*;
use std::fs::File;
use std::io::Read;
use crate::math::vec3::*;
use crate::math::vec2::*;
use crate::math::mat4::*;
use std::collections::HashMap;
use crate::scene::*;
use crate::math::{vec4::*, vec3::*, vec2::*, mat4::*, quat::*};
use crate::scene::{*, node::*};
use crate::resource::fbx::FbxAnimationCurveNodeType::Rotation;
use crate::renderer::surface::{SurfaceSharedData, Surface, Vertex};
use crate::math::triangulator::triangulate;
use crate::engine::ResourceManager;
use core::borrow::Borrow;
pub enum FbxAttribute {
Double(f64),
@@ -18,47 +18,67 @@ pub enum FbxAttribute {
}
impl FbxAttribute {
pub fn as_int(&self) -> i32 {
pub fn as_int(&self) -> Result<i32, String> {
match self {
FbxAttribute::Double(val) => *val as i32,
FbxAttribute::Float(val) => *val as i32,
FbxAttribute::Integer(val) => *val,
FbxAttribute::Long(val) => *val as i32,
FbxAttribute::Bool(val) => *val as i32,
FbxAttribute::String(val) => val.parse::<i32>().unwrap(),
FbxAttribute::Double(val) => Ok(*val as i32),
FbxAttribute::Float(val) => Ok(*val as i32),
FbxAttribute::Integer(val) => Ok(*val),
FbxAttribute::Long(val) => Ok(*val as i32),
FbxAttribute::Bool(val) => Ok(*val as i32),
FbxAttribute::String(val) => {
match val.parse::<i32>() {
Ok(i) => Ok(i),
Err(_) => Err(format!("Unable to convert string {} to i32", val))
}
}
}
}
pub fn as_int64(&self) -> i64 {
pub fn as_int64(&self) -> Result<i64, String> {
match self {
FbxAttribute::Double(val) => *val as i64,
FbxAttribute::Float(val) => *val as i64,
FbxAttribute::Integer(val) => *val as i64,
FbxAttribute::Long(val) => *val as i64,
FbxAttribute::Bool(val) => *val as i64,
FbxAttribute::String(val) => val.parse::<i64>().unwrap(),
FbxAttribute::Double(val) => Ok(*val as i64),
FbxAttribute::Float(val) => Ok(*val as i64),
FbxAttribute::Integer(val) => Ok(*val as i64),
FbxAttribute::Long(val) => Ok(*val as i64),
FbxAttribute::Bool(val) => Ok(*val as i64),
FbxAttribute::String(val) => {
match val.parse::<i64>() {
Ok(i) => Ok(i),
Err(_) => Err(format!("Unable to convert string {} to i64", val))
}
}
}
}
pub fn as_double(&self) -> f64 {
pub fn as_double(&self) -> Result<f64, String> {
match self {
FbxAttribute::Double(val) => *val,
FbxAttribute::Float(val) => *val as f64,
FbxAttribute::Integer(val) => *val as f64,
FbxAttribute::Long(val) => *val as f64,
FbxAttribute::Bool(val) => (*val as i64) as f64,
FbxAttribute::String(val) => val.parse::<f64>().unwrap(),
FbxAttribute::Double(val) => Ok(*val),
FbxAttribute::Float(val) => Ok(*val as f64),
FbxAttribute::Integer(val) => Ok(*val as f64),
FbxAttribute::Long(val) => Ok(*val as f64),
FbxAttribute::Bool(val) => Ok((*val as i64) as f64),
FbxAttribute::String(val) => {
match val.parse::<f64>() {
Ok(i) => Ok(i),
Err(_) => Err(format!("Unable to convert string {} to f64", val))
}
}
}
}
pub fn as_float(&self) -> f32 {
pub fn as_float(&self) -> Result<f32, String> {
match self {
FbxAttribute::Double(val) => *val as f32,
FbxAttribute::Float(val) => *val,
FbxAttribute::Integer(val) => *val as f32,
FbxAttribute::Long(val) => *val as f32,
FbxAttribute::Bool(val) => (*val as i32) as f32,
FbxAttribute::String(val) => val.parse::<f32>().unwrap(),
FbxAttribute::Double(val) => Ok(*val as f32),
FbxAttribute::Float(val) => Ok(*val),
FbxAttribute::Integer(val) => Ok(*val as f32),
FbxAttribute::Long(val) => Ok(*val as f32),
FbxAttribute::Bool(val) => Ok((*val as i32) as f32),
FbxAttribute::String(val) => {
match val.parse::<f32>() {
Ok(i) => Ok(i),
Err(_) => Err(format!("Unable to convert string {} to f32", val))
}
}
}
}
@@ -98,10 +118,32 @@ struct FbxTexture {
filename: String,
}
impl FbxTexture {
fn read(texture_node_hanle: &Handle<FbxNode>, nodes: &Pool<FbxNode>,
stack: &mut Vec<Handle<FbxNode>>) -> Result<FbxTexture, String> {
let mut texture = FbxTexture {
filename: String::new()
};
if let Ok(relative_file_name_node) = find_and_borrow_node(nodes, stack, texture_node_hanle, "RelativeFilename") {
texture.filename = relative_file_name_node.get_attrib(0)?.as_string();
println!("{}", texture.filename);
}
Ok(texture)
}
}
struct FbxMaterial {
diffuse_texture: Handle<FbxComponent>
}
impl FbxMaterial {
fn read(material_node_hanle: &Handle<FbxNode>) -> Result<FbxMaterial, String> {
Ok(FbxMaterial {
diffuse_texture: Handle::none()
})
}
}
struct FbxDeformer {
sub_deformers: Vec<Handle<FbxComponent>>
}
@@ -122,6 +164,7 @@ struct FbxAnimationCurveNode {
curves: Vec<Handle<FbxComponent>>,
}
#[derive(Copy, Clone, PartialEq)]
enum FbxMapping {
Unknown,
ByPolygon,
@@ -131,6 +174,7 @@ enum FbxMapping {
AllSame,
}
#[derive(Copy, Clone, PartialEq)]
enum FbxReference {
Unknown,
Direct,
@@ -139,30 +183,37 @@ enum FbxReference {
struct FbxNode {
name: String,
attributes: Vec<FbxAttribute>,
attribs: Vec<FbxAttribute>,
parent: Handle<FbxNode>,
children: Vec<Handle<FbxNode>>,
}
impl FbxNode {
fn get_vec3_at(&self, n: usize) -> Result<Vec3, &'static str> {
if n + 3 <= self.attributes.len() {
return Ok(Vec3 {
x: self.attributes[n].as_float(),
y: self.attributes[n + 1].as_float(),
z: self.attributes[n + 2].as_float(),
});
}
return Err("FBX: Attribute index out of bounds");
fn get_vec3_at(&self, n: usize) -> Result<Vec3, String> {
return Ok(Vec3 {
x: self.get_attrib(n)?.as_float()?,
y: self.get_attrib(n + 1)?.as_float()?,
z: self.get_attrib(n + 2)?.as_float()?,
});
}
fn get_vec3_at_unchecked(&self, n: usize) -> Vec3 {
Vec3 {
x: self.attributes[n].as_float(),
y: self.attributes[n + 1].as_float(),
z: self.attributes[n + 2].as_float(),
fn get_vec2_at(&self, n: usize) -> Result<Vec2, String> {
return Ok(Vec2 {
x: self.get_attrib(n)?.as_float()?,
y: self.get_attrib(n + 1)?.as_float()?,
});
}
fn get_attrib(&self, n: usize) -> Result<&FbxAttribute, String> {
match self.attribs.get(n) {
Some(attrib) => Ok(attrib),
None => Err(format!("Unable to get {} attribute because index out of bounds.", n))
}
}
fn attrib_count(&self) -> usize {
self.attribs.len()
}
}
struct FbxGeometry {
@@ -196,7 +247,7 @@ struct FbxGeometry {
impl FbxGeometry {
pub fn read(geom_node_handle: &Handle<FbxNode>,
nodes: &Pool<FbxNode>,
stack: &mut Vec<Handle<FbxNode>>) -> Result<FbxGeometry, &'static str> {
stack: &mut Vec<Handle<FbxNode>>) -> Result<FbxGeometry, String> {
let mut geom = FbxGeometry {
vertices: Vec::new(),
indices: Vec::new(),
@@ -220,59 +271,81 @@ impl FbxGeometry {
};
// Read vertices
if let Some(vertices_node_handle) = find_node(nodes, stack, geom_node_handle, "Vertices") {
if let Some(vertices_array_node) = find_and_borrow_node(nodes, stack, &vertices_node_handle, "a") {
let vertex_count = vertices_array_node.attributes.len() / 3;
geom.vertices = Vec::with_capacity(vertex_count);
for i in 0..vertex_count {
geom.vertices.push(vertices_array_node.get_vec3_at_unchecked(i * 3));
}
} else {
return Err("FBX: Unable to find array node of vertices");
}
} else {
return Err("FBX: Unable to find vertices node");
let vertices_node_handle = find_node(nodes, stack, geom_node_handle, "Vertices")?;
let vertices_array_node = find_and_borrow_node(nodes, stack, &vertices_node_handle, "a")?;
let vertex_count = vertices_array_node.attrib_count() / 3;
geom.vertices = Vec::with_capacity(vertex_count);
for i in 0..vertex_count {
geom.vertices.push(vertices_array_node.get_vec3_at(i * 3)?);
}
// Read faces
if let Some(indices_node_handle) = find_node(nodes, stack, geom_node_handle, "PolygonVertexIndex") {
if let Some(indices_array_node) = find_and_borrow_node(nodes, stack, &indices_node_handle, "a") {
let index_count = indices_array_node.attributes.len();
geom.indices = Vec::with_capacity(index_count);
for i in 0..index_count {
geom.indices.push(indices_array_node.attributes[i].as_int());
}
} else {
return Err("FBX: Unable to find array node of indices");
}
} else {
return Err("FBX: Unable to find indices node");
let indices_node_handle = find_node(nodes, stack, geom_node_handle, "PolygonVertexIndex")?;
let indices_array_node = find_and_borrow_node(nodes, stack, &indices_node_handle, "a")?;
let index_count = indices_array_node.attrib_count();
geom.indices = Vec::with_capacity(index_count);
for i in 0..index_count {
let index = indices_array_node.get_attrib(i)?.as_int()?;
geom.indices.push(index);
}
// read normals
if let Some(layer_element_normal_node_handle) = find_node(nodes, stack, geom_node_handle, "LayerElementNormal") {
if let Some(map_type_node) = find_and_borrow_node(nodes, stack, &layer_element_normal_node_handle, "MappingInformationType") {
geom.normal_mapping = string_to_mapping(&map_type_node.attributes[0].as_string());
}
if let Some(ref_type_node) = find_and_borrow_node(nodes, stack, &layer_element_normal_node_handle, "ReferenceInformationType") {
geom.normal_reference = string_to_reference(&ref_type_node.attributes[0].as_string());
}
// finally read normals
if let Some(normals_node_handle) = find_node(nodes, stack, &layer_element_normal_node_handle, "Normals") {
if let Some(normals_array_node) = find_and_borrow_node(nodes, stack, &normals_node_handle, "a") {
let count = normals_array_node.attributes.len() / 3;
for i in 0..count {
geom.normals.push(normals_array_node.get_vec3_at_unchecked(i * 3));
}
}
// Read normals (normals can not exist)
if let Ok(layer_element_normal_node_handle) = find_node(nodes, stack, geom_node_handle, "LayerElementNormal") {
let map_type_node = find_and_borrow_node(nodes, stack, &layer_element_normal_node_handle, "MappingInformationType")?;
geom.normal_mapping = string_to_mapping(&map_type_node.get_attrib(0)?.as_string());
let ref_type_node = find_and_borrow_node(nodes, stack, &layer_element_normal_node_handle, "ReferenceInformationType")?;
geom.normal_reference = string_to_reference(&ref_type_node.get_attrib(0)?.as_string());
let normals_node_handle = find_node(nodes, stack, &layer_element_normal_node_handle, "Normals")?;
let normals_array_node = find_and_borrow_node(nodes, stack, &normals_node_handle, "a")?;
let count = normals_array_node.attrib_count() / 3;
for i in 0..count {
geom.normals.push(normals_array_node.get_vec3_at(i * 3)?);
}
}
// todo: read tangents
// todo: read uvs
// Read UVs
if let Ok(layer_element_uv_node_handle) = find_node(nodes, stack, geom_node_handle, "LayerElementUV") {
let map_type_node = find_and_borrow_node(nodes, stack, &layer_element_uv_node_handle, "MappingInformationType")?;
geom.uv_mapping = string_to_mapping(&map_type_node.get_attrib(0)?.as_string());
// todo: read materials
let ref_type_node = find_and_borrow_node(nodes, stack, &layer_element_uv_node_handle, "ReferenceInformationType")?;
geom.uv_reference = string_to_reference(&ref_type_node.get_attrib(0)?.as_string());
let uvs_node_handle = find_node(nodes, stack, &layer_element_uv_node_handle, "UV")?;
let uvs_array_node = find_and_borrow_node(nodes, stack, &uvs_node_handle, "a")?;
let count = uvs_array_node.attrib_count() / 2;
for i in 0..count {
let uv = uvs_array_node.get_vec2_at(i * 2)?;
geom.uvs.push(Vec2{x:uv.x, y: -uv.y}); // Hack
}
if geom.uv_reference == FbxReference::IndexToDirect {
let uv_index_node = find_node(nodes,stack, &layer_element_uv_node_handle, "UVIndex")?;
let uv_index_array_node = find_and_borrow_node(nodes, stack, &uv_index_node, "a")?;
for i in 0..uv_index_array_node.attrib_count() {
geom.uv_index.push(uv_index_array_node.get_attrib(i)?.as_int()?);
}
}
}
// Read materials
if let Ok(layer_element_material_node_handle) = find_node(nodes, stack, geom_node_handle, "LayerElementMaterial") {
let map_type_node = find_and_borrow_node(nodes, stack, &layer_element_material_node_handle, "MappingInformationType")?;
geom.material_mapping = string_to_mapping(&map_type_node.get_attrib(0)?.as_string());
let ref_type_node = find_and_borrow_node(nodes, stack, &layer_element_material_node_handle, "ReferenceInformationType")?;
geom.material_reference = string_to_reference(&ref_type_node.get_attrib(0)?.as_string());
let materials_node_handle = find_node(nodes, stack, &layer_element_material_node_handle, "Materials")?;
let materials_array_node = find_and_borrow_node(nodes, stack, &materials_node_handle, "a")?;
for i in 0..materials_array_node.attrib_count() {
geom.materials.push(materials_array_node.get_attrib(i)?.as_int()?);
}
}
return Ok(geom);
}
@@ -329,12 +402,12 @@ struct FbxModel {
impl FbxModel {
pub fn read(model_node_handle: &Handle<FbxNode>,
nodes: &Pool<FbxNode>,
stack: &mut Vec<Handle<FbxNode>>) -> Result<FbxModel, &'static str> {
stack: &mut Vec<Handle<FbxNode>>) -> Result<FbxModel, String> {
let mut name = String::from("Unnamed");
if let Some(model_node) = nodes.borrow(&model_node_handle) {
if let Some(name_attrib) = model_node.attributes.get(1) {
name = name_attrib.as_string();
}
let model_node = nodes.borrow(&model_node_handle).unwrap();
if let Ok(name_attrib) = model_node.get_attrib(1) {
name = name_attrib.as_string();
}
// Remove prefix
@@ -364,40 +437,27 @@ impl FbxModel {
light: Handle::none(),
};
if let Some(properties70_node_handle) = find_node(nodes, stack, model_node_handle, "Properties70") {
if let Some(properties70_node) = nodes.borrow(&properties70_node_handle) {
for property_handle in properties70_node.children.iter() {
if let Some(property_node) = nodes.borrow(&property_handle) {
if let Some(name_attrib) = property_node.attributes.get(0) {
if let FbxAttribute::String(name) = &name_attrib {
match name.as_str() {
"Lcl Translation" => model.translation = property_node.get_vec3_at(4)?,
"Lcl Rotation" => model.rotation = property_node.get_vec3_at(4)?,
"Lcl Scaling" => model.scale = property_node.get_vec3_at(4)?,
"PreRotation" => model.pre_rotation = property_node.get_vec3_at(4)?,
"PostRotation" => model.post_rotation = property_node.get_vec3_at(4)?,
"RotationOffset" => model.rotation_offset = property_node.get_vec3_at(4)?,
"RotationPivot" => model.rotation_pivot = property_node.get_vec3_at(4)?,
"ScalingOffset" => model.scaling_offset = property_node.get_vec3_at(4)?,
"ScalingPivot" => model.scaling_pivot = property_node.get_vec3_at(4)?,
"GeometricTranslation" => model.geometric_translation = property_node.get_vec3_at(4)?,
"GeometricScaling" => model.geometric_scale = property_node.get_vec3_at(4)?,
"GeometricRotation" => model.geometric_rotation = property_node.get_vec3_at(4)?,
_ => () // Unused properties
}
}
}
} else {
return Err("FBX: Invalid property handle");
}
}
} else {
return Err("FBX: Invalid fbx node handle");
let properties70_node_handle = find_node(nodes, stack, model_node_handle, "Properties70")?;
let properties70_node = nodes.borrow(&properties70_node_handle).unwrap();
for property_handle in properties70_node.children.iter() {
let property_node = nodes.borrow(&property_handle).unwrap();
let name_attrib = property_node.get_attrib(0)?;
match name_attrib.as_string().as_str() {
"Lcl Translation" => model.translation = property_node.get_vec3_at(4)?,
"Lcl Rotation" => model.rotation = property_node.get_vec3_at(4)?,
"Lcl Scaling" => model.scale = property_node.get_vec3_at(4)?,
"PreRotation" => model.pre_rotation = property_node.get_vec3_at(4)?,
"PostRotation" => model.post_rotation = property_node.get_vec3_at(4)?,
"RotationOffset" => model.rotation_offset = property_node.get_vec3_at(4)?,
"RotationPivot" => model.rotation_pivot = property_node.get_vec3_at(4)?,
"ScalingOffset" => model.scaling_offset = property_node.get_vec3_at(4)?,
"ScalingPivot" => model.scaling_pivot = property_node.get_vec3_at(4)?,
"GeometricTranslation" => model.geometric_translation = property_node.get_vec3_at(4)?,
"GeometricScaling" => model.geometric_scale = property_node.get_vec3_at(4)?,
"GeometricRotation" => model.geometric_rotation = property_node.get_vec3_at(4)?,
_ => () // Unused properties
}
} else {
return Err("FBX: Properties70 not found!");
}
return Ok(model);
}
}
@@ -449,46 +509,48 @@ pub struct Fbx {
/// borrow references to actual nodes.
nodes: Pool<FbxNode>,
/// Pool for FBX components, filled in "prepare" method
components: Pool<FbxComponent>,
component_pool: Pool<FbxComponent>,
root: Handle<FbxNode>,
/// Map used for fast look up of components by their fbx-indices
index_to_component: HashMap<i64, Handle<FbxComponent>>,
/// Actual list of created components
components: Vec<Handle<FbxComponent>>
}
/// Searches node by specified name and returns its handle if found
/// Uses provided stack to do depth search
fn find_node(pool: &Pool<FbxNode>, stack: &mut Vec<Handle<FbxNode>>, root: &Handle<FbxNode>, name: &str) -> Option<Handle<FbxNode>> {
fn find_node(pool: &Pool<FbxNode>, stack: &mut Vec<Handle<FbxNode>>, root: &Handle<FbxNode>, name: &str) -> Result<Handle<FbxNode>, String> {
stack.clear();
stack.push(root.clone());
while let Some(handle) = stack.pop() {
if let Some(node) = pool.borrow(&handle) {
if node.name == name {
return Some(handle);
return Ok(handle);
}
for child_handle in node.children.iter() {
stack.push(child_handle.clone());
}
}
}
None
Err(format!("Unable to find {} node", name))
}
/// Searches node by specified name and borrows a reference to it
/// Uses provided stack to do depth search
fn find_and_borrow_node<'a>(pool: &'a Pool<FbxNode>, stack: &mut Vec<Handle<FbxNode>>, root: &Handle<FbxNode>, name: &str) -> Option<&'a FbxNode> {
fn find_and_borrow_node<'a>(pool: &'a Pool<FbxNode>, stack: &mut Vec<Handle<FbxNode>>, root: &Handle<FbxNode>, name: &str) -> Result<&'a FbxNode, String> {
stack.clear();
stack.push(root.clone());
while let Some(handle) = stack.pop() {
if let Some(node) = pool.borrow(&handle) {
if node.name == name {
return Some(node);
return Ok(node);
}
for child_handle in node.children.iter() {
stack.push(child_handle.clone());
}
}
}
None
Err(format!("Unable to find {} node", name))
}
/// Links child component with parent component so parent will know about child
@@ -540,13 +602,13 @@ fn link_child_with_parent_component(parent: &mut FbxComponent, child_handle: &Ha
}
}
fn read_ascii(path: &Path) -> Result<Fbx, &'static str> {
fn read_ascii(path: &Path) -> Result<Fbx, String> {
let mut nodes: Pool<FbxNode> = Pool::new();
let root_handle = nodes.spawn(FbxNode {
name: String::from("__ROOT__"),
children: Vec::new(),
parent: Handle::none(),
attributes: Vec::new(),
attribs: Vec::new(),
});
let mut parent_handle: Handle<FbxNode> = root_handle.clone();
let mut node_handle: Handle<FbxNode> = Handle::none();
@@ -579,7 +641,7 @@ fn read_ascii(path: &Path) -> Result<Fbx, &'static str> {
}
}
} else {
return Err("unexpected end of file");
return Err(String::from("unexpected end of file"));
}
}
if end {
@@ -605,9 +667,9 @@ fn read_ascii(path: &Path) -> Result<Fbx, &'static str> {
}
if symbol == ':' && !read_value {
read_value = true;
let mut node = FbxNode {
let node = FbxNode {
name: name.iter().collect(),
attributes: Vec::new(),
attribs: Vec::new(),
parent: parent_handle.clone(),
children: Vec::new(),
};
@@ -623,9 +685,9 @@ fn read_ascii(path: &Path) -> Result<Fbx, &'static str> {
if value.len() > 0 {
if let Some(node) = nodes.borrow_mut(&node_handle) {
let attrib = FbxAttribute::String(value.iter().collect());
node.attributes.push(attrib);
node.attribs.push(attrib);
} else {
return Err("FBX: Failed to fetch node by handle when entering child scope");
return Err(String::from("FBX: Failed to fetch node by handle when entering child scope"));
}
value.clear();
}
@@ -642,9 +704,9 @@ fn read_ascii(path: &Path) -> Result<Fbx, &'static str> {
if let Some(node) = nodes.borrow_mut(&node_handle) {
let attrib = FbxAttribute::String(value.iter().collect());
node.attributes.push(attrib);
node.attribs.push(attrib);
} else {
return Err("FBX: Failed to fetch node by handle when committing attribute");
return Err(String::from("FBX: Failed to fetch node by handle when committing attribute"));
}
value.clear();
} else {
@@ -661,7 +723,8 @@ fn read_ascii(path: &Path) -> Result<Fbx, &'static str> {
Ok(Fbx {
nodes,
root: root_handle,
components: Pool::new(),
component_pool: Pool::new(),
components: Vec::new(),
index_to_component: HashMap::new(),
})
}
@@ -687,94 +750,189 @@ fn string_to_reference(value: &String) -> FbxReference {
}
}
/// Input angles in degrees
fn quat_from_euler(euler: Vec3) -> Quat {
Quat::from_euler(
Vec3::make(euler.x.to_radians(), euler.y.to_radians(), euler.z.to_radians()),
RotationOrder::XYZ)
}
/// Fixes index that is used as indicator of end of a polygon
/// FBX stores array of indices like so 0,1,2,1,2,-4,... where -4
/// is actually index 3 but it xor'ed using -1.
fn fix_index(index: i32) -> usize {
if index < 0 {
(-index - 1) as usize
} else {
index as usize
}
}
/// Triangulates polygon face if needed.
/// Returns number of processed indices.
fn prepare_next_face(geom: &FbxGeometry,
start: usize,
temp_vertices: &mut Vec<Vec3>,
out_triangles: &mut Vec<(usize, usize, usize)>,
out_relative_triangles: &mut Vec<(usize, usize, usize)>) -> usize {
out_triangles.clear();
out_relative_triangles.clear();
// Find out how much vertices do we have per face.
let mut vertex_per_face = 0;
for i in start..geom.indices.len() {
vertex_per_face += 1;
if geom.indices[i] < 0 {
break;
}
}
if vertex_per_face == 3 {
let a = fix_index(geom.indices[start]);
let b = fix_index(geom.indices[start + 1]);
let c = fix_index(geom.indices[start + 2]);
// Ensure that we have valid indices here. Some exporters may fuck up indices
// and they'll blow up loader.
if a < geom.vertices.len() && b < geom.vertices.len() && c < geom.vertices.len() {
// We have a triangle
out_triangles.push((a, b, c));
out_relative_triangles.push((0, 1, 2));
}
} else if vertex_per_face > 3 {
// Triangulate a polygon. Triangulate it!
temp_vertices.clear();
for i in 0..vertex_per_face {
temp_vertices.push(geom.vertices[fix_index(geom.indices[start + i])]);
}
triangulate(&temp_vertices.as_slice(), out_relative_triangles);
for triangle in out_relative_triangles.iter() {
out_triangles.push((
fix_index(geom.indices[start + triangle.0]),
fix_index(geom.indices[start + triangle.1]),
fix_index(geom.indices[start + triangle.2])));
}
}
return vertex_per_face;
}
fn convert_vertex(geom: &FbxGeometry,
mesh: &mut Mesh,
geometric_transform: &Mat4,
material_index: usize,
origin: usize,
index: usize,
relative_index: usize) {
let position = geometric_transform.transform_vector(geom.vertices[index]);
let normal = geometric_transform.transform_vector_normal(match geom.normal_mapping {
FbxMapping::ByPolygonVertex => geom.normals[origin + relative_index],
FbxMapping::ByVertex => geom.normals[index],
_ => Vec3 { x: 0.0, y: 1.0, z: 0.0 }
});
let tangent = geometric_transform.transform_vector_normal(match geom.tangent_mapping {
FbxMapping::ByPolygonVertex => geom.tangents[origin + relative_index],
FbxMapping::ByVertex => geom.tangents[index],
_ => Vec3 { x: 0.0, y: 1.0, z: 0.0 }
});
let uv = match geom.uv_mapping {
FbxMapping::ByPolygonVertex => {
match geom.uv_reference {
FbxReference::Direct => geom.uvs[origin + relative_index],
FbxReference::IndexToDirect => geom.uvs[geom.uv_index[origin + relative_index] as usize],
_ => Vec2 { x: 0.0, y: 0.0 }
}
}
_ => Vec2 { x: 0.0, y: 0.0 }
};
let material = match geom.material_mapping {
FbxMapping::AllSame => geom.materials[0] as usize,
FbxMapping::ByPolygon => geom.materials[material_index] as usize,
_ => 0
};
let surface = mesh.get_surfaces_mut().get_mut(material).unwrap();
surface.data.borrow_mut().insert_vertex(Vertex {
position,
normal,
tex_coord: uv,
tangent: Vec4 { x: tangent.x, y: tangent.y, z: tangent.z, w: 1.0 },
})
}
impl Fbx {
/// Parses FBX DOM and filling internal lists to prepare
/// for conversion to engine format
fn prepare(&mut self) -> Result<(), &'static str> {
fn prepare(&mut self) -> Result<(), String> {
// Search-stack for internal routines
let mut traversal_stack: Vec<Handle<FbxNode>> = Vec::new();
// Check version
if let Some(header_handle) = find_node(&self.nodes, &mut traversal_stack, &self.root, "FBXHeaderExtension") {
if let Some(version) = find_and_borrow_node(&self.nodes, &mut traversal_stack, &header_handle, "FBXVersion") {
if let Some(version_attrib) = version.attributes.get(0) {
if version_attrib.as_int() < 7100 {
return Err("FBX: Unsupported version. Version must be >= 7100");
}
} else {
return Err("FBX: Version attribute not found");
}
}
} else {
return Err("FBX: Unable to find header");
let header_handle = find_node(&self.nodes, &mut traversal_stack, &self.root, "FBXHeaderExtension")?;
let version = find_and_borrow_node(&self.nodes, &mut traversal_stack, &header_handle, "FBXVersion")?;
let version = version.get_attrib(0)?.as_int()?;
if version < 7100 {
return Err(format!("FBX: Unsupported {} version. Version must be >= 7100", version));
}
// Read objects
if let Some(objects_node) = find_and_borrow_node(&self.nodes, &mut traversal_stack, &self.root, "Objects") {
for object_handle in objects_node.children.iter() {
if let Some(object) = self.nodes.borrow(&object_handle) {
let index: i64 = object.attributes[0].as_int64();
let mut component_handle: Handle<FbxComponent> = Handle::none();
match object.name.as_str() {
"Geometry" => {
component_handle = self.components.spawn(FbxComponent::Geometry(
FbxGeometry::read(object_handle, &self.nodes, &mut traversal_stack)?))
}
"Model" => {
component_handle = self.components.spawn(FbxComponent::Model(
FbxModel::read(object_handle, &self.nodes, &mut traversal_stack)?))
}
"Material" => {
println!("reading a Material");
}
"Texture" => {
println!("reading a Texture");
}
"NodeAttribute" => {
println!("reading a NodeAttribute");
}
"AnimationCurve" => {
println!("reading a AnimationCurve");
}
"AnimationCurveNode" => {
println!("reading a AnimationCurveNode");
}
"Deformer" => {
println!("reading a Deformer");
}
_ => ()
}
if !component_handle.is_none() {
self.index_to_component.insert(index, component_handle);
}
let objects_node = find_and_borrow_node(&self.nodes, &mut traversal_stack, &self.root, "Objects")?;
for object_handle in objects_node.children.iter() {
let object = self.nodes.borrow(&object_handle).unwrap();
let index: i64 = object.get_attrib(0)?.as_int64()?;
let mut component_handle: Handle<FbxComponent> = Handle::none();
match object.name.as_str() {
"Geometry" => {
component_handle = self.component_pool.spawn(FbxComponent::Geometry(
FbxGeometry::read(object_handle, &self.nodes, &mut traversal_stack)?));
}
"Model" => {
component_handle = self.component_pool.spawn(FbxComponent::Model(
FbxModel::read(object_handle, &self.nodes, &mut traversal_stack)?));
}
"Material" => {
component_handle = self.component_pool.spawn(FbxComponent::Material(
FbxMaterial::read(object_handle)?));
}
"Texture" => {
component_handle = self.component_pool.spawn(FbxComponent::Texture(
FbxTexture::read(object_handle, &self.nodes, &mut traversal_stack)?));
}
"NodeAttribute" => {
//println!("reading a NodeAttribute");
}
"AnimationCurve" => {
//println!("reading a AnimationCurve");
}
"AnimationCurveNode" => {
//println!("reading a AnimationCurveNode");
}
"Deformer" => {
//println!("reading a Deformer");
}
_ => ()
}
if !component_handle.is_none() {
self.index_to_component.insert(index, component_handle.clone());
self.components.push(component_handle.clone());
}
} else {
return Err("FBX: Objects missing");
}
// Read connections
if let Some(connections_node) = find_and_borrow_node(&self.nodes, &mut traversal_stack, &self.root, "Connections") {
for connection_handle in connections_node.children.iter() {
if let Some(connection) = self.nodes.borrow(&connection_handle) {
if connection.attributes.len() < 3 {
continue;
}
let child_index = connection.attributes[1].as_int64();
let parent_index = connection.attributes[2].as_int64();
if let Some(parent_handle) = self.index_to_component.get(&parent_index) {
if let Some(child_handle) = self.index_to_component.get(&child_index) {
let mut child_type_id = FbxComponentTypeId::Unknown;
if let Some(child) = self.components.borrow(child_handle) {
child_type_id = child.type_id();
}
if let Some(parent) = self.components.borrow_mut(parent_handle) {
link_child_with_parent_component(parent, child_handle, child_type_id);
}
}
}
let connections_node = find_and_borrow_node(&self.nodes, &mut traversal_stack, &self.root, "Connections")?;
for connection_handle in connections_node.children.iter() {
let connection = self.nodes.borrow(&connection_handle).unwrap();
let child_index = connection.get_attrib(1)?.as_int64()?;
let parent_index = connection.get_attrib(2)?.as_int64()?;
if let Some(parent_handle) = self.index_to_component.get(&parent_index) {
if let Some(child_handle) = self.index_to_component.get(&child_index) {
let child_type_id = self.component_pool.borrow(child_handle).unwrap().type_id();
let parent = self.component_pool.borrow_mut(parent_handle).unwrap();
link_child_with_parent_component(parent, child_handle, child_type_id);
}
}
}
@@ -782,28 +940,162 @@ impl Fbx {
return Ok(());
}
fn convert_light(&self, light: &mut Light, fbx_light: &FbxLight) {
light.set_color(Vec3::make(fbx_light.color.r as f32 / 255.0,
fbx_light.color.g as f32 / 255.0,
fbx_light.color.b as f32 / 255.0));
light.set_radius(fbx_light.radius);
}
fn create_surfaces(&self, mesh: &mut Mesh, model: &FbxModel, resource_manager: &mut ResourceManager) {
// Create surfaces per material
if model.materials.is_empty() {
let surface_data = SurfaceSharedData::new();
mesh.add_surface(Surface::new(&Rc::new(RefCell::new(surface_data))));
} else {
for material_handle in model.materials.iter() {
let surface_data = SurfaceSharedData::new();
let mut surface = Surface::new(&Rc::new(RefCell::new(surface_data)));
if let FbxComponent::Material(material) = self.component_pool.borrow(&material_handle).unwrap() {
if let Some(texture_handle) = self.component_pool.borrow(&material.diffuse_texture) {
if let FbxComponent::Texture(texture) = texture_handle {
if !texture.filename.is_empty() {
if let Some(texture_resource) =resource_manager.request_texture(Path::new(texture.filename.as_str())) {
println!("here 1");
surface.set_texture(texture_resource);
}
}
}
}
}
mesh.add_surface(surface);
}
}
}
fn convert_mesh(&self, mesh: &mut Mesh, model: &FbxModel, scene: &mut Scene, resource_manager: &mut ResourceManager) {
let geometric_transform = Mat4::translate(model.geometric_translation) *
Mat4::from_quat(quat_from_euler(model.geometric_rotation)) *
Mat4::scale(model.geometric_scale);
let mut temp_vertices: Vec<Vec3> = Vec::new();
let mut triangles: Vec<(usize, usize, usize)> = Vec::new();
let mut relative_triangles: Vec<(usize, usize, usize)> = Vec::new();
for geom_handle in &model.geoms {
let geom_component = self.component_pool.borrow(&geom_handle).unwrap();
if let FbxComponent::Geometry(geom) = geom_component {
self.create_surfaces(mesh, model, resource_manager);
let mut material_index = 0;
let mut n = 0;
while n < geom.indices.len() {
let origin = n;
n += prepare_next_face(geom, n, &mut temp_vertices, &mut triangles, &mut relative_triangles);
for i in 0..triangles.len() {
let triangle = &triangles[i];
let relative_triangle = &relative_triangles[i];
convert_vertex(geom, mesh, &geometric_transform, material_index, origin, triangle.0, relative_triangle.0);
convert_vertex(geom, mesh, &geometric_transform, material_index, origin, triangle.1, relative_triangle.1);
convert_vertex(geom, mesh, &geometric_transform, material_index, origin, triangle.2, relative_triangle.2);
}
if geom.material_mapping == FbxMapping::ByPolygon {
material_index += 1;
}
}
}
}
}
fn convert_model(&self, model: &FbxModel, scene: &mut Scene, resource_manager: &mut ResourceManager) ->
Result<Handle<Node>, String> {
// Create node with of correct kind.
let mut node =
if model.geoms.len() != 0 {
Node::new(NodeKind::Mesh(Mesh::default()))
} else if !model.light.is_none() {
Node::new(NodeKind::Light(Light::default()))
} else {
Node::new(NodeKind::Base)
};
node.set_name(model.name.clone());
node.set_local_rotation(quat_from_euler(model.rotation));
node.set_local_scale(model.scale);
node.set_local_position(model.translation);
node.set_post_rotation(quat_from_euler(model.post_rotation));
node.set_pre_rotation(quat_from_euler(model.pre_rotation));
node.set_rotation_offset(model.rotation_offset);
node.set_rotation_pivot(model.rotation_pivot);
node.set_scaling_offset(model.scaling_offset);
node.set_scaling_pivot(model.scaling_pivot);
match node.borrow_kind_mut() {
NodeKind::Light(light) => {
let fbx_light_component = self.component_pool.borrow(&model.light).unwrap();
if let FbxComponent::Light(fbx_light) = fbx_light_component {
self.convert_light(light, fbx_light);
}
}
NodeKind::Mesh(mesh) => {
self.convert_mesh(mesh, model, scene, resource_manager);
}
_ => ()
}
Ok(scene.add_node(node))
}
///
/// Converts FBX DOM to native engine representation.
///
pub fn convert(&self, scene: &mut Scene, resource_manager: &mut ResourceManager)
-> Result<Handle<Node>, String> {
let root = scene.add_node(Node::new(NodeKind::Base));
let mut fbx_model_to_node_map: HashMap<Handle<FbxComponent>, Handle<Node>> = HashMap::new();
for component_handle in self.components.iter() {
if let Some(component) = self.component_pool.borrow(&component_handle) {
if let FbxComponent::Model(model) = component {
if let Ok(node) = self.convert_model(model, scene, resource_manager) {
scene.link_nodes(&node, &root);
fbx_model_to_node_map.insert(component_handle.clone(), node.clone());
}
}
}
}
// Link according to hierarchy
for (fbx_model_handle, node_handle) in fbx_model_to_node_map.iter() {
if let FbxComponent::Model(fbx_model) = self.component_pool.borrow(&fbx_model_handle).unwrap() {
for fbx_child_handle in fbx_model.children.iter() {
if let Some(child_handle) = fbx_model_to_node_map.get(fbx_child_handle) {
scene.link_nodes(&child_handle, &node_handle);
}
}
}
}
Ok(root)
}
/// TODO: format trait maybe?
pub fn print(&mut self) {
let mut stack: Vec<Handle<FbxNode>> = Vec::new();
stack.push(self.root.clone());
while let Some(handle) = stack.pop() {
if let Some(node) = self.nodes.borrow(&handle) {
println!("{}", node.name);
let node = self.nodes.borrow(&handle).unwrap();
println!("{}", node.name);
// Continue printing children
for child_handle in node.children.iter() {
stack.push(child_handle.clone());
}
// Continue printing children
for child_handle in node.children.iter() {
stack.push(child_handle.clone());
}
}
}
}
pub fn load_to_scene(scene: &mut Scene, path: &Path) {
if let Ok(ref mut fbx) = read_ascii(path) {
if let Ok(_) = fbx.prepare() {
}
}
pub fn load_to_scene(scene: &mut Scene, resource_manager: &mut ResourceManager, path: &Path)
-> Result<Handle<Node>, String> {
let ref mut fbx = read_ascii(path)?;
fbx.prepare()?;
fbx.convert(scene, resource_manager)
}
+71 -1
View File
@@ -22,6 +22,14 @@ impl Light {
color: Vec3 { x: 1.0, y: 1.0, z: 1.0 },
}
}
pub fn set_radius(&mut self, radius: f32) {
self.radius = radius;
}
pub fn set_color(&mut self, color: Vec3) {
self.color = color;
}
}
pub struct Camera {
@@ -73,7 +81,7 @@ impl Camera {
}
pub struct Mesh {
pub(crate) surfaces: Vec<Surface>
surfaces: Vec<Surface>
}
impl Mesh {
@@ -94,6 +102,18 @@ impl Mesh {
surface.set_texture(tex.clone());
}
}
pub fn get_surfaces(&self) -> &Vec<Surface> {
&self.surfaces
}
pub fn get_surfaces_mut(&mut self) -> &mut Vec<Surface> {
&mut self.surfaces
}
pub fn add_surface(&mut self, surface: Surface) {
self.surfaces.push(surface);
}
}
pub enum NodeKind {
@@ -163,30 +183,77 @@ impl Node {
scale_offset * scale_pivot * scale * scale_pivot_inv;
}
#[inline]
pub fn borrow_kind(&self) -> &NodeKind {
&self.kind
}
#[inline]
pub fn borrow_kind_mut(&mut self) -> &mut NodeKind {
&mut self.kind
}
#[inline]
pub fn set_local_position(&mut self, pos: Vec3) {
self.local_position = pos;
}
#[inline]
pub fn set_local_rotation(&mut self, rot: Quat) {
self.local_rotation = rot;
}
#[inline]
pub fn set_pre_rotation(&mut self, pre_rotation: Quat) {
self.pre_rotation = pre_rotation;
}
#[inline]
pub fn set_post_rotation(&mut self, post_rotation: Quat) {
self.post_rotation = post_rotation;
}
#[inline]
pub fn set_rotation_offset(&mut self, rotation_offset: Vec3) {
self.rotation_offset = rotation_offset;
}
#[inline]
pub fn set_rotation_pivot(&mut self, rotation_pivot: Vec3) {
self.rotation_pivot = rotation_pivot;
}
#[inline]
pub fn set_scaling_offset(&mut self, scaling_offset: Vec3) {
self.scaling_offset = scaling_offset;
}
#[inline]
pub fn set_scaling_pivot(&mut self, scaling_pivot: Vec3) {
self.scaling_pivot = scaling_pivot;
}
#[inline]
pub fn set_name(&mut self, name: String) {
self.name = name;
}
#[inline]
pub fn get_name(&self) -> &str {
self.name.as_str()
}
#[inline]
pub fn set_local_scale(&mut self, scl: Vec3) {
self.local_scale = scl;
}
#[inline]
pub fn offset(&mut self, vec: Vec3) {
self.local_position += vec;
}
#[inline]
pub fn get_global_position(&self) -> Vec3 {
Vec3 {
x: self.global_transform.f[12],
@@ -195,6 +262,7 @@ impl Node {
}
}
#[inline]
pub fn get_look_vector(&self) -> Vec3 {
Vec3 {
x: self.global_transform.f[8],
@@ -203,6 +271,7 @@ impl Node {
}
}
#[inline]
pub fn get_side_vector(&self) -> Vec3 {
Vec3 {
x: self.global_transform.f[0],
@@ -211,6 +280,7 @@ impl Node {
}
}
#[inline]
pub fn get_up_vector(&self) -> Vec3 {
Vec3 {
x: self.global_transform.f[4],
+50 -29
View File
@@ -1,22 +1,32 @@
use std::marker::PhantomData;
use std::hash::{Hash, Hasher};
struct PoolRecord<T: Sized> {
stamp: u32,
generation: u32,
payload: Option<T>,
}
///
/// Pool allows to create as many objects as you want in contiguous memory
/// block. It allows to create and delete objects very fast.
///
pub struct Pool<T: Sized> {
records: Vec<PoolRecord<T>>,
free_stack: Vec<u32>
}
///
/// Handle is some sort of non-owning reference to content in a pool.
/// It stores index of object and additional information that
/// allows to ensure that handle is still valid.
///
pub struct Handle<T> {
pub(crate) index: u32,
index: u32,
stamp: u32,
type_marker: PhantomData<T>,
}
struct PoolRecord<T: Sized> {
stamp: u32,
generation: u32,
payload: Option<T>,
}
impl<T> Clone for Handle<T> {
fn clone(&self) -> Handle<T> {
Handle {
@@ -33,7 +43,19 @@ impl<T> PartialEq for Handle<T> {
}
}
impl<T> Eq for Handle<T> {
}
impl<T> Hash for Handle<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.index.hash(state);
self.stamp.hash(state);
}
}
impl<T> Handle<T> {
#[inline]
pub fn none() -> Self {
Handle {
index: 0,
@@ -42,12 +64,14 @@ impl<T> Handle<T> {
}
}
#[inline]
pub fn is_none(&self) -> bool {
self.index == 0 && self.stamp == 0
}
}
impl<T> Pool<T> {
#[inline]
pub fn new() -> Self {
Pool {
records: Vec::<PoolRecord<T>>::new(),
@@ -55,6 +79,7 @@ impl<T> Pool<T> {
}
}
#[inline]
pub fn spawn(&mut self, payload: T) -> Handle<T> {
if let Some(free_index) = self.free_stack.pop() {
let record = &mut self.records[free_index as usize];
@@ -85,38 +110,31 @@ impl<T> Pool<T> {
handle
}
#[inline]
pub fn borrow(&self, handle: &Handle<T>) -> Option<&T> {
let index = handle.index as usize;
if index < self.records.len() {
unsafe {
// _unchecked here because we already checked index
let record = self.records.get_unchecked(index);
if record.stamp == handle.stamp {
if let Some(payload) = &record.payload {
return Some(payload);
}
if let Some(record) = self.records.get(handle.index as usize) {
if record.stamp == handle.stamp {
if let Some(payload) = &record.payload {
return Some(payload);
}
}
}
None
}
#[inline]
pub fn borrow_mut(&mut self, handle: &Handle<T>) -> Option<&mut T> {
let index = handle.index as usize;
if index < self.records.len() {
unsafe {
// _unchecked here because we already checked index
let record = self.records.get_unchecked_mut(index);
if record.stamp == handle.stamp {
if let Some(payload) = &mut record.payload {
return Some(payload);
}
if let Some(record) = self.records.get_mut(handle.index as usize) {
if record.stamp == handle.stamp {
if let Some(payload) = &mut record.payload {
return Some(payload);
}
}
}
None
}
#[inline]
pub fn free(&mut self, handle: Handle<T>) {
let index = handle.index as usize;
if index < self.records.len() {
@@ -126,22 +144,25 @@ impl<T> Pool<T> {
}
}
#[inline]
pub fn capacity(&self) -> usize {
self.records.len()
}
#[inline]
pub fn at_mut(&mut self, n: usize) -> Option<&mut T> {
if n < self.records.len() {
if let Some(payload) = &mut self.records[n].payload {
if let Some(record) = self.records.get_mut(n) {
if let Some(ref mut payload) = record.payload {
return Some(payload);
}
}
None
}
#[inline]
pub fn at(&self, n: usize) -> Option<&T> {
if n < self.records.len() {
if let Some(payload) = &self.records[n].payload {
if let Some(record) = self.records.get(n) {
if let Some(ref payload) = record.payload {
return Some(payload);
}
}