From e868d332814011b13b16b072de7633fb06b266ef Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Sat, 24 Jan 2026 01:14:40 -0600 Subject: [PATCH] initial collada mesh rendering --- Makefile | 6 +- collada/cube_material.py | 580 +++++++++++++++++++++++++++ collada/mesh.py | 95 +++++ collada/types.py | 8 +- include/collada.hpp | 12 + main.rc | 2 + models/skinned_cube/skinned_cube.DAE | 265 ++++++++++++ models/skinned_cube/skinned_cube.max | Bin 0 -> 208896 bytes src/collada.cpp | 244 +++++++++++ src/effect/collada.fx | 60 +++ src/main.cpp | 63 ++- 11 files changed, 1314 insertions(+), 21 deletions(-) create mode 100644 collada/cube_material.py create mode 100644 collada/mesh.py create mode 100644 include/collada.hpp create mode 100755 models/skinned_cube/skinned_cube.DAE create mode 100755 models/skinned_cube/skinned_cube.max create mode 100644 src/collada.cpp create mode 100644 src/effect/collada.fx diff --git a/Makefile b/Makefile index 219b9fd..9aafe07 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,8 @@ SHADERS = \ $(BUILD_TYPE)/effect/font.fxo \ $(BUILD_TYPE)/effect/volume.fxo \ $(BUILD_TYPE)/effect/bloom.fxo \ - $(BUILD_TYPE)/effect/static.fxo + $(BUILD_TYPE)/effect/static.fxo \ + $(BUILD_TYPE)/effect/collada.fxo $(BUILD_TYPE)/%.res: %.rc $(SHADERS) @mkdir -p $(@D) @@ -57,13 +58,14 @@ $(BUILD_TYPE)/%.obj: src/%.cpp $(CXX) $(CXXSTD) $(CFLAGS) $(CXXFLAGS) $(WOPT) $(OPT) -o $@ -c $< OBJS = \ + $(BUILD_TYPE)/main.res \ $(BUILD_TYPE)/robot_player.obj \ $(BUILD_TYPE)/cube.obj \ $(BUILD_TYPE)/main.obj \ $(BUILD_TYPE)/print.obj \ $(BUILD_TYPE)/render_state.obj \ $(BUILD_TYPE)/input.obj \ - $(BUILD_TYPE)/main.res + $(BUILD_TYPE)/collada.obj $(BUILD_TYPE)/d3d10.exe: $(OBJS) @mkdir -p $(@D) diff --git a/collada/cube_material.py b/collada/cube_material.py new file mode 100644 index 0000000..642b1cd --- /dev/null +++ b/collada/cube_material.py @@ -0,0 +1,580 @@ +collada.types.Collada( + library_animations=[], + library_controllers=[], + library_effects=[ + collada.types.LibraryEffects( + id=None, + name=None, + effects=[ + collada.types.Effect( + id='CubeMaterialTextured', + name=None, + profile_common=[ + collada.types.ProfileCommon( + id=None, + newparam=[ + collada.types.Newparam( + sid='troll_cleric29_max2010_jpg-surface', + parameter_type=collada.types.Surface( + type=collada.types.FxSurfaceType._2D, + init_from=collada.types.InitFrom(uri='troll_cleric29_max2010_jpg') + ) + ), + collada.types.Newparam( + sid='troll_cleric29_max2010_jpg-sampler', + parameter_type=collada.types.Sampler2D( + source=collada.types.SourceFX(sid='troll_cleric29_max2010_jpg-surface') + ) + ) + ], + technique=collada.types.TechniqueFX( + id=None, + sid='common', + shader=collada.types.Blinn( + emission=collada.types.Color(value=(0.0, 0.0, 0.0, 1.0)), + ambient=collada.types.Color( + value=(0.8588236, 0.254902, 0.9137256, 1.0) + ), + diffuse=collada.types.Texture( + texture='troll_cleric29_max2010_jpg-sampler', + texcoord='CHANNEL1' + ), + specular=collada.types.Color(value=(0.0, 0.0, 0.0, 1.0)), + shininess=collada.types.Float(value=10.0), + reflective=collada.types.Color(value=(0.0, 0.0, 0.0, 1.0)), + reflectivity=None, + transparent=collada.types.Color(value=(1.0, 1.0, 1.0, 1.0)), + transparency=collada.types.Float(value=1.0), + index_of_refraction=None + ) + ) + ) + ] + ) + ] + ) + ], + library_materials=[ + collada.types.LibraryMaterials( + id=None, + name=None, + materials=[ + collada.types.Material( + id='CubeMaterialTextured-material', + name='CubeMaterialTextured', + instance_effect=collada.types.InstanceEffect( + sid=None, + name=None, + url='#CubeMaterialTextured' + ) + ) + ] + ) + ], + library_geometries=[ + collada.types.LibraryGeometries( + id=None, + name=None, + geometries=[ + collada.types.Geometry( + id='geom-Cube', + name='Cube', + geometric_element=collada.types.Mesh( + sources=[ + collada.types.SourceCore( + id='geom-Cube-positions', + name=None, + array_element=collada.types.FloatArray( + count=24, + id='geom-Cube-positions-array', + name=None, + digits=6, + magnitude=38, + floats=[ + -0.5, + -0.5, + 0.0, + 0.5, + -0.5, + 0.0, + -0.5, + 0.5, + 0.0, + 0.5, + 0.5, + 0.0, + -0.5, + -0.5, + 1.0, + 0.5, + -0.5, + 1.0, + -0.5, + 0.5, + 1.0, + 0.5, + 0.5, + 1.0 + ] + ), + technique_common=collada.types.TechniqueCommon_SourceCore( + accessor=collada.types.Accessor( + count=8, + offset=0, + source='#geom-Cube-positions-array', + stride=3, + params=[ + collada.types.Param(name='X', sid=None, type='float', semantic=None), + collada.types.Param(name='Y', sid=None, type='float', semantic=None), + collada.types.Param(name='Z', sid=None, type='float', semantic=None) + ] + ) + ) + ), + collada.types.SourceCore( + id='geom-Cube-normals', + name=None, + array_element=collada.types.FloatArray( + count=72, + id='geom-Cube-normals-array', + name=None, + digits=6, + magnitude=38, + floats=[ + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 1.0, + 0.0, + -1.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + -1.0, + 0.0, + 1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 1.0, + 0.0, + -1.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0 + ] + ), + technique_common=collada.types.TechniqueCommon_SourceCore( + accessor=collada.types.Accessor( + count=24, + offset=0, + source='#geom-Cube-normals-array', + stride=3, + params=[ + collada.types.Param(name='X', sid=None, type='float', semantic=None), + collada.types.Param(name='Y', sid=None, type='float', semantic=None), + collada.types.Param(name='Z', sid=None, type='float', semantic=None) + ] + ) + ) + ), + collada.types.SourceCore( + id='geom-Cube-map1', + name=None, + array_element=collada.types.FloatArray( + count=36, + id='geom-Cube-map1-array', + name=None, + digits=6, + magnitude=38, + floats=[ + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 1.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 1.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 1.0, + 1.0, + 0.0 + ] + ), + technique_common=collada.types.TechniqueCommon_SourceCore( + accessor=collada.types.Accessor( + count=12, + offset=0, + source='#geom-Cube-map1-array', + stride=3, + params=[ + collada.types.Param(name='S', sid=None, type='float', semantic=None), + collada.types.Param(name='T', sid=None, type='float', semantic=None), + collada.types.Param(name='P', sid=None, type='float', semantic=None) + ] + ) + ) + ) + ], + vertices=collada.types.Vertices( + id='geom-Cube-vertices', + name=None, + inputs=[ + collada.types.InputUnshared( + semantic='POSITION', + source='#geom-Cube-positions' + ) + ] + ), + primitive_elements=[ + collada.types.Triangles( + name=None, + count=12, + material='CubeMaterialTextured', + inputs=[ + collada.types.InputShared( + offset=0, + semantic='VERTEX', + source='#geom-Cube-vertices', + set=None + ), + collada.types.InputShared( + offset=1, + semantic='NORMAL', + source='#geom-Cube-normals', + set=None + ), + collada.types.InputShared( + offset=2, + semantic='TEXCOORD', + source='#geom-Cube-map1', + set=0 + ) + ], + p=[ + 0, + 0, + 9, + 2, + 1, + 11, + 3, + 2, + 10, + 3, + 2, + 10, + 1, + 3, + 8, + 0, + 0, + 9, + 4, + 4, + 8, + 5, + 5, + 9, + 7, + 6, + 11, + 7, + 6, + 11, + 6, + 7, + 10, + 4, + 4, + 8, + 0, + 8, + 4, + 1, + 9, + 5, + 5, + 10, + 7, + 5, + 10, + 7, + 4, + 11, + 6, + 0, + 8, + 4, + 1, + 12, + 0, + 3, + 13, + 1, + 7, + 14, + 3, + 7, + 14, + 3, + 5, + 15, + 2, + 1, + 12, + 0, + 3, + 16, + 4, + 2, + 17, + 5, + 6, + 18, + 7, + 6, + 18, + 7, + 7, + 19, + 6, + 3, + 16, + 4, + 2, + 20, + 0, + 0, + 21, + 1, + 4, + 22, + 3, + 4, + 22, + 3, + 6, + 23, + 2, + 2, + 20, + 0 + ] + ) + ] + ) + ) + ] + ) + ], + library_lights=[ + collada.types.LibraryLights( + id=None, + name=None, + lights=[ + collada.types.Light( + id='EnvironmentAmbientLight', + name='EnvironmentAmbientLight', + technique_common=collada.types.TechniqueCommon_Light( + light=collada.types.Ambient(color=(0.0, 0.0, 0.0)) + ) + ) + ] + ) + ], + library_images=[ + collada.types.LibraryImages( + id=None, + name=None, + images=[ + collada.types.Image( + id='troll_cleric29_max2010_jpg', + name=None, + format=None, + height=None, + width=None, + depth=None, + image_source=collada.types.InitFrom( + uri='file:///C:/cygwin/home/bilbo/collada/images/0_troll_cleric29_max2010.' + 'jpg' + ) + ) + ] + ) + ], + library_visual_scenes=[ + collada.types.LibraryVisualScenes( + id=None, + name=None, + visual_scenes=[ + collada.types.VisualScene( + id='MaxScene', + name=None, + nodes=[ + collada.types.Node( + id=None, + name='EnvironmentAmbientLight', + sid=None, + type=collada.types.NodeType.NODE, + layer=[], + transformation_elements=[], + instance_geometries=[], + instance_lights=[ + collada.types.InstanceLight( + sid=None, + name=None, + url='#EnvironmentAmbientLight' + ) + ], + nodes=[] + ), + collada.types.Node( + id='node-Cube', + name='Cube', + sid=None, + type=collada.types.NodeType.NODE, + layer=[], + transformation_elements=[], + instance_geometries=[], + instance_lights=[], + nodes=[ + collada.types.Node( + id=None, + name=None, + sid=None, + type=collada.types.NodeType.NODE, + layer=[], + transformation_elements=[ + collada.types.Matrix( + sid=None, + values=( + (1.0, 0.0, 0.0, 0.0), + (0.0, 1.0, -4.37114e-08, 2.18557e-08), + (0.0, 4.37114e-08, 1.0, -0.5), + (0.0, 0.0, 0.0, 1.0) + ) + ) + ], + instance_geometries=[ + collada.types.InstanceGeometry( + sid=None, + name=None, + url='#geom-Cube', + bind_material=collada.types.BindMaterial( + technique_common=collada.types.TechniqueCommon_BindMaterial( + materials=[ + collada.types.InstanceMaterial( + sid=None, + name=None, + target='#CubeMaterialTextured-material', + symbol='CubeMaterialTextured', + bind_vertex_inputs=[ + collada.types.BindVertexInput( + semantic='CHANNEL1', + input_semantic='TEXCOORD', + input_set='0' + ) + ] + ) + ] + ) + ) + ) + ], + instance_lights=[], + nodes=[] + ) + ] + ) + ] + ) + ] + ) + ], + scenes=[ + collada.types.Scene( + instance_visual_scene=collada.types.InstanceVisualScene( + sid=None, + name=None, + url='#MaxScene' + ) + ) + ] +) diff --git a/collada/mesh.py b/collada/mesh.py new file mode 100644 index 0000000..a8ad141 --- /dev/null +++ b/collada/mesh.py @@ -0,0 +1,95 @@ +from collections import defaultdict +from itertools import chain, islice + +from collada import parse +from collada import types + +from prettyprinter import pprint, install_extras +install_extras(include=["dataclasses"]) + +def resolve_input_source(collada, source_uri): + return element + +def find_semantics(inputs, semantic): + return [i for i in inputs if i.semantic == semantic] + +def mesh_vertex_buffer(collada, mesh): + semantic_names = ["NORMAL", "TEXCOORD"] + + assert len(mesh.primitive_elements) == 1 + triangles, = mesh.primitive_elements + assert type(triangles) is types.Triangles + + vertex_input, = find_semantics(triangles.inputs, "VERTEX") + vertices = collada.lookup(vertex_input.source, types.Vertices) + position_input, = find_semantics(vertices.inputs, "POSITION") + position_source = collada.lookup(position_input.source, types.SourceCore) + assert type(position_source.array_element) is types.FloatArray + + by_offset = defaultdict(list) + by_offset[vertex_input.offset].append((vertex_input, position_source)) + + for semantic_name in semantic_names: + for input in find_semantics(triangles.inputs, semantic_name): + source = collada.lookup(input.source, types.SourceCore) + assert type(source.array_element) is types.FloatArray + by_offset[input.offset].append((input, source)) + + max_offset = max(i.offset for i in triangles.inputs) + p_stride = max_offset + 1 + assert len(triangles.p) == triangles.count * 3 * p_stride + + ###################################################################### + # generate the index/vertex buffer + ###################################################################### + vertex_buffer_stride = sum( + source.technique_common.accessor.stride + for input, source in chain.from_iterable(by_offset.values()) + ) + index_table = {} + next_output_index = 0 + index_buffer = [] + vertex_buffer = [] + + used_offsets = [offset for offset in range(p_stride) if offset in by_offset] + + for vertex_ix in range(triangles.count * 3): + index_table_key = tuple(triangles.p[vertex_ix * p_stride + offset] for offset in used_offsets) + print(index_table_key) + if index_table_key in index_table: + index_buffer.append(index_table[index_table_key]) + continue + + index_table[index_table_key] = next_output_index + index_buffer.append(next_output_index) + next_output_index += 1 + + # emit vertex attributes for new output index in vertex buffer + for offset in used_offsets: + p_index = triangles.p[vertex_ix * p_stride + offset] + for input, source in by_offset[offset]: + print(input.semantic, end=" ") + source_stride = source.technique_common.accessor.stride + source_index = p_index * source_stride + array_slice = source.array_element.floats[source_index:source_index+source_stride] + print(array_slice, end=" ") + vertex_buffer.extend(array_slice) + print() + + print("{") + for i in range(triangles.count): + print(", ".join(str(index_buffer[i * 3 + j]) for j in range(3)), end=",\n") + print("}") + print("{") + for i in range(len(index_table)): + print(", ".join(str(vertex_buffer[i * vertex_buffer_stride + j]) + for j in range(vertex_buffer_stride)), end=",\n") + print("}") + +if __name__ == "__main__": + import sys + collada = parse.parse_collada_file(sys.argv[1]) + + mesh = collada.library_geometries[0].geometries[0].geometric_element + assert type(mesh) is types.Mesh + mesh_vertex_buffer(collada, mesh) diff --git a/collada/types.py b/collada/types.py index 7edc385..54bf3a2 100644 --- a/collada/types.py +++ b/collada/types.py @@ -348,7 +348,7 @@ class Vertices: id: ID name: Optional[str] - input: List[InputUnshared] # 1 or more + inputs: List[InputUnshared] # 1 or more @dataclass class Mesh: @@ -534,8 +534,10 @@ class Collada: self.scenes = [] self._lookup = None - def lookup(self, s): + def lookup(self, s, t): assert '/' not in s assert s.startswith("#") id = s[1:] - return self._lookup[id] + value = self._lookup[id] + assert type(value) is t, type(value) + return value diff --git a/include/collada.hpp b/include/collada.hpp new file mode 100644 index 0000000..54f50b4 --- /dev/null +++ b/include/collada.hpp @@ -0,0 +1,12 @@ +#pragma once + +#ifndef COLLADA_HPP_ +#define COLLADA_HPP_ + +namespace collada { + HRESULT LoadEffect(); + HRESULT LoadMesh(); + void Render(); +} + +#endif diff --git a/main.rc b/main.rc index abbc331..32888a1 100644 --- a/main.rc +++ b/main.rc @@ -6,3 +6,5 @@ RES_STATIC_FXO RCDATA "static.fxo" RES_PERLIN RCDATA "texture/perlin.data" RES_ROBOT_PLAYER RCDATA "models/robot_player/robot_player.data" RES_FONT_TERMINUS_6X12 RCDATA "font/terminus_128x64_6x12.data" + +RES_COLLADA_FXO RCDATA "collada.fxo" \ No newline at end of file diff --git a/models/skinned_cube/skinned_cube.DAE b/models/skinned_cube/skinned_cube.DAE new file mode 100755 index 0000000..825b3c8 --- /dev/null +++ b/models/skinned_cube/skinned_cube.DAE @@ -0,0 +1,265 @@ + + + + + bilbo + OpenCOLLADA for 3ds Max; Version: 1.6; Revision: 68 + file:///C:/cygwin/home/bilbo/d3d10/models/skinned_cube/skinned_cube.max + + 2026-01-23T23:56:13 + 2026-01-23T23:56:13 + + Z_UP + + + + + + + + 0.1019608 0.6941176 0.1019608 1 + + + 0.1019608 0.6941176 0.1019608 1 + + + 1 1 1 1 + + + 10 + + + 0 0 0 1 + + + 1 1 1 1 + + + 1 + + + + + + + + + + + + + + + + -5 -5 0 5 -5 0 -5 5 0 5 5 0 -5 -5 20 5 -5 20 -5 5 20 5 5 20 -5 -5 4 5 -5 4 5 5 4 -5 5 4 -5 -5 8 5 -5 8 5 5 8 -5 5 8 -5 -5 12 5 -5 12 5 5 12 -5 5 12 -5 -5 16 5 -5 16 5 5 16 -5 5 16 + + + + + + + + + + 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 1 0 0 1 0 0 1 0 0 1 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 + + + + + + + + + + 0 0 0 1 0 0 0 0.2 0 1 0.2 0 0 0.4 0 1 0.4 0 0 0.6 0 1 0.6 0 0 0.8 0 1 0.8 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0.2 0 1 0.2 0 0 0.4 0 1 0.4 0 0 0.6 0 1 0.6 0 0 0.8 0 1 0.8 0 0 1 0 1 1 0 0 0 0 1 0 0 0 1 0 1 1 0 + + + + + + + + + + + + + + + +

0 0 25 2 1 27 3 2 26 3 2 26 1 3 24 0 0 25 4 4 24 5 5 25 7 6 27 7 6 27 6 7 26 4 4 24 0 8 12 1 9 13 9 10 15 9 10 15 8 11 14 0 8 12 8 11 14 9 10 15 13 12 17 13 12 17 12 13 16 8 11 14 12 13 16 13 12 17 17 14 19 17 14 19 16 15 18 12 13 16 16 15 18 17 14 19 21 16 21 21 16 21 20 17 20 16 15 18 20 17 20 21 16 21 5 18 23 5 18 23 4 19 22 20 17 20 1 20 0 3 21 1 10 22 3 10 22 3 9 23 2 1 20 0 9 23 2 10 22 3 14 24 5 14 24 5 13 25 4 9 23 2 13 25 4 14 24 5 18 26 7 18 26 7 17 27 6 13 25 4 17 27 6 18 26 7 22 28 9 22 28 9 21 29 8 17 27 6 21 29 8 22 28 9 7 30 11 7 30 11 5 31 10 21 29 8 3 32 12 2 33 13 11 34 15 11 34 15 10 35 14 3 32 12 10 35 14 11 34 15 15 36 17 15 36 17 14 37 16 10 35 14 14 37 16 15 36 17 19 38 19 19 38 19 18 39 18 14 37 16 18 39 18 19 38 19 23 40 21 23 40 21 22 41 20 18 39 18 22 41 20 23 40 21 6 42 23 6 42 23 7 43 22 22 41 20 2 44 0 0 45 1 8 46 3 8 46 3 11 47 2 2 44 0 11 47 2 8 46 3 12 48 5 12 48 5 15 49 4 11 47 2 15 49 4 12 48 5 16 50 7 16 50 7 19 51 6 15 49 4 19 51 6 16 50 7 20 52 9 20 52 9 23 53 8 19 51 6 23 53 8 20 52 9 4 54 11 4 54 11 6 55 10 23 53 8

+
+
+ + + + 10 + 10 + 20 + 1 + 1 + 5 + 1 + + + +
+
+ + + + 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 + + joint0 joint1 + + + + + + + + -5.11435e-14 3.13916e-7 1 0 -1.74846e-7 1 -3.13916e-7 0 -1 -1.74846e-7 3.74342e-15 0 0 0 0 1 -8.74227e-8 -5.52335e-7 1 -10 -8.74228e-8 1 5.52335e-7 -9.85461e-6 -1 -8.74227e-8 -8.74227e-8 8.74227e-7 0 0 0 1 + + + + + + + + 1 0 0 0 0 0 0 0 0 0.2 0.8 0.2 0.8 0.2 0.8 0.2 0.8 0.4 0.6 0.4 0.6 0.4 0.6 0.4 0.6 0.6 0.4 0.6 0.4 0.6 0.4 0.6 0.4 0.8 0.2 0.8 0.2 0.8 0.2 0.8 0.2 + + + + + + + + + + + + + + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 1 1 0 0 1 2 0 0 1 3 0 0 1 4 0 0 1 0 0 5 1 0 0 6 1 0 0 7 1 0 0 8 1 9 0 10 1 11 0 12 1 13 0 14 1 15 0 16 1 17 0 18 1 19 0 20 1 21 0 22 1 23 0 24 1 25 0 26 1 27 0 28 1 29 0 30 1 31 0 32 1 33 0 34 1 35 0 36 1 37 0 38 1 39 0 40 + + + + + + + + + 0 0 0 + + + + + + + + + + + + #node-Bone001 + + + + + + + + + 1 + 1 + 1 + 1 + + + + + 1.32123e-6 1 -1.49608e-6 -90 + + 10 1.19209e-6 5.69993e-14 + 0 0 1 5.00896e-6 + 0 1 0 -5.00896e-6 + 1 0 0 -5.00896e-6 + + + 1 + 1 + 1 + 1 + + + + + + 1 + 1 + 1 + 1 + + + + + + + + + 0 0.3333333 0.6666667 1 1.333333 + + + + + + + + 180 230 180 130 180 + + + + + + + + -0.3332639 180 0.2222222 213.3333 0.5555556 196.6667 0.8888889 146.6667 1.222222 163.3333 + + + + + + + + + 0.1111111 196.6667 0.4444444 213.3333 0.7777778 163.3333 1.111111 146.6667 1.666597 180 + + + + + + + + + LINEAR LINEAR LINEAR LINEAR LINEAR + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/models/skinned_cube/skinned_cube.max b/models/skinned_cube/skinned_cube.max new file mode 100755 index 0000000000000000000000000000000000000000..fd21ecbbaacd296c592c3da1be69405f9f193468 GIT binary patch literal 208896 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 Mz#?D~$T|Z5A5z1<1poj5 literal 0 HcmV?d00001 diff --git a/src/collada.cpp b/src/collada.cpp new file mode 100644 index 0000000..ba7ba52 --- /dev/null +++ b/src/collada.cpp @@ -0,0 +1,244 @@ +#include +#include + +#include "directxmath/directxmath.h" + +#include "print.hpp" +#include "collada.hpp" + +extern ID3D10Device * g_pd3dDevice; +extern XMMATRIX g_View; +extern XMMATRIX g_Projection; + +namespace collada { + static const float vertex_buffer[] = { + -5.0, -5.0, 0.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0, + -5.0, 5.0, 0.0, 0.0, 0.0, -1.0, 1.0, 1.0, 0.0, + 5.0, 5.0, 0.0, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0, + 5.0, -5.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, + -5.0, -5.0, 20.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, + 5.0, -5.0, 20.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, + 5.0, 5.0, 20.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, + -5.0, 5.0, 20.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, + -5.0, -5.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, + 5.0, -5.0, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0, 0.0, + 5.0, -5.0, 4.0, 0.0, -1.0, 0.0, 1.0, 0.2, 0.0, + -5.0, -5.0, 4.0, 0.0, -1.0, 0.0, 0.0, 0.2, 0.0, + 5.0, -5.0, 8.0, 0.0, -1.0, 0.0, 1.0, 0.4, 0.0, + -5.0, -5.0, 8.0, 0.0, -1.0, 0.0, 0.0, 0.4, 0.0, + 5.0, -5.0, 12.0, 0.0, -1.0, 0.0, 1.0, 0.6, 0.0, + -5.0, -5.0, 12.0, 0.0, -1.0, 0.0, 0.0, 0.6, 0.0, + 5.0, -5.0, 16.0, 0.0, -1.0, 0.0, 1.0, 0.8, 0.0, + -5.0, -5.0, 16.0, 0.0, -1.0, 0.0, 0.0, 0.8, 0.0, + 5.0, -5.0, 20.0, 0.0, -1.0, 0.0, 1.0, 1.0, 0.0, + -5.0, -5.0, 20.0, 0.0, -1.0, 0.0, 0.0, 1.0, 0.0, + 5.0, -5.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 5.0, 5.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, + 5.0, 5.0, 4.0, 1.0, 0.0, 0.0, 1.0, 0.2, 0.0, + 5.0, -5.0, 4.0, 1.0, 0.0, 0.0, 0.0, 0.2, 0.0, + 5.0, 5.0, 8.0, 1.0, 0.0, 0.0, 1.0, 0.4, 0.0, + 5.0, -5.0, 8.0, 1.0, 0.0, 0.0, 0.0, 0.4, 0.0, + 5.0, 5.0, 12.0, 1.0, 0.0, 0.0, 1.0, 0.6, 0.0, + 5.0, -5.0, 12.0, 1.0, 0.0, 0.0, 0.0, 0.6, 0.0, + 5.0, 5.0, 16.0, 1.0, 0.0, 0.0, 1.0, 0.8, 0.0, + 5.0, -5.0, 16.0, 1.0, 0.0, 0.0, 0.0, 0.8, 0.0, + 5.0, 5.0, 20.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, + 5.0, -5.0, 20.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, + 5.0, 5.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, + -5.0, 5.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, + -5.0, 5.0, 4.0, 0.0, 1.0, 0.0, 1.0, 0.2, 0.0, + 5.0, 5.0, 4.0, 0.0, 1.0, 0.0, 0.0, 0.2, 0.0, + -5.0, 5.0, 8.0, 0.0, 1.0, 0.0, 1.0, 0.4, 0.0, + 5.0, 5.0, 8.0, 0.0, 1.0, 0.0, 0.0, 0.4, 0.0, + -5.0, 5.0, 12.0, 0.0, 1.0, 0.0, 1.0, 0.6, 0.0, + 5.0, 5.0, 12.0, 0.0, 1.0, 0.0, 0.0, 0.6, 0.0, + -5.0, 5.0, 16.0, 0.0, 1.0, 0.0, 1.0, 0.8, 0.0, + 5.0, 5.0, 16.0, 0.0, 1.0, 0.0, 0.0, 0.8, 0.0, + -5.0, 5.0, 20.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, + 5.0, 5.0, 20.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, + -5.0, 5.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, + -5.0, -5.0, 0.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, + -5.0, -5.0, 4.0, -1.0, 0.0, 0.0, 1.0, 0.2, 0.0, + -5.0, 5.0, 4.0, -1.0, 0.0, 0.0, 0.0, 0.2, 0.0, + -5.0, -5.0, 8.0, -1.0, 0.0, 0.0, 1.0, 0.4, 0.0, + -5.0, 5.0, 8.0, -1.0, 0.0, 0.0, 0.0, 0.4, 0.0, + -5.0, -5.0, 12.0, -1.0, 0.0, 0.0, 1.0, 0.6, 0.0, + -5.0, 5.0, 12.0, -1.0, 0.0, 0.0, 0.0, 0.6, 0.0, + -5.0, -5.0, 16.0, -1.0, 0.0, 0.0, 1.0, 0.8, 0.0, + -5.0, 5.0, 16.0, -1.0, 0.0, 0.0, 0.0, 0.8, 0.0, + -5.0, -5.0, 20.0, -1.0, 0.0, 0.0, 1.0, 1.0, 0.0, + -5.0, 5.0, 20.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, + }; + + static const int index_buffer[] = { + 0, 1, 2, + 2, 3, 0, + 4, 5, 6, + 6, 7, 4, + 8, 9, 10, + 10, 11, 8, + 11, 10, 12, + 12, 13, 11, + 13, 12, 14, + 14, 15, 13, + 15, 14, 16, + 16, 17, 15, + 17, 16, 18, + 18, 19, 17, + 20, 21, 22, + 22, 23, 20, + 23, 22, 24, + 24, 25, 23, + 25, 24, 26, + 26, 27, 25, + 27, 26, 28, + 28, 29, 27, + 29, 28, 30, + 30, 31, 29, + 32, 33, 34, + 34, 35, 32, + 35, 34, 36, + 36, 37, 35, + 37, 36, 38, + 38, 39, 37, + 39, 38, 40, + 40, 41, 39, + 41, 40, 42, + 42, 43, 41, + 44, 45, 46, + 46, 47, 44, + 47, 46, 48, + 48, 49, 47, + 49, 48, 50, + 50, 51, 49, + 51, 50, 52, + 52, 53, 51, + 53, 52, 54, + 54, 55, 53, + }; + + ID3D10Effect * g_pEffect = NULL; + ID3D10EffectTechnique * g_pTechniqueRender = NULL; + ID3D10InputLayout * g_pVertexLayout = NULL; + + ID3D10Buffer * g_pVertexBuffer; + ID3D10Buffer * g_pIndexBuffer; + + ID3D10EffectMatrixVariable * g_pWorldVariable = NULL; + ID3D10EffectMatrixVariable * g_pViewVariable = NULL; + ID3D10EffectMatrixVariable * g_pProjectionVariable = NULL; + + HRESULT LoadEffect() + { + HRESULT hr; + + HRSRC hRes = FindResource(NULL, L"RES_COLLADA_FXO", RT_RCDATA); + if (hRes == NULL) { + print("FindResource RES_COLLADA_FXO\n"); + return E_FAIL; + } + DWORD dwResSize = SizeofResource(NULL, hRes); + HGLOBAL hData = LoadResource(NULL, hRes); + void * pData = LockResource(hData); + hr = D3D10CreateEffectFromMemory(pData, + dwResSize, + 0, + g_pd3dDevice, + NULL, + &g_pEffect + ); + if (FAILED(hr)) { + print("D3D10CreateEffectFromMemory\n"); + return hr; + } + g_pTechniqueRender = g_pEffect->GetTechniqueByName("Render"); + + // variables + g_pWorldVariable = g_pEffect->GetVariableByName("World")->AsMatrix(); + g_pViewVariable = g_pEffect->GetVariableByName("View")->AsMatrix(); + g_pProjectionVariable = g_pEffect->GetVariableByName("Projection")->AsMatrix(); + + // layout + D3D10_INPUT_ELEMENT_DESC layout[] = { + {"POSITION" , 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0}, + {"NORMAL" , 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0}, + {"TEXCOORD" , 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0}, + }; + UINT numElements = (sizeof (layout)) / (sizeof (layout[0])); + + D3D10_PASS_DESC passDesc; + g_pTechniqueRender->GetPassByIndex(0)->GetDesc(&passDesc); + + hr = g_pd3dDevice->CreateInputLayout(layout, numElements, + passDesc.pIAInputSignature, + passDesc.IAInputSignatureSize, + &g_pVertexLayout); + if (FAILED(hr)) { + print("CreateInputLayout\n"); + return hr; + } + + return S_OK; + } + + HRESULT LoadMesh() + { + HRESULT hr; + + D3D10_BUFFER_DESC bd; + D3D10_SUBRESOURCE_DATA initData; + + bd.Usage = D3D10_USAGE_IMMUTABLE; + bd.ByteWidth = (sizeof (vertex_buffer)); + bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; + bd.CPUAccessFlags = 0; + bd.MiscFlags = 0; + initData.pSysMem = vertex_buffer; + hr = g_pd3dDevice->CreateBuffer(&bd, &initData, &g_pVertexBuffer); + if (FAILED(hr)) { + print("CreateBuffer: D3D10_BIND_VERTEX_BUFFER\n"); + return hr; + } + + bd.Usage = D3D10_USAGE_IMMUTABLE; + bd.ByteWidth = (sizeof (index_buffer)); + bd.BindFlags = D3D10_BIND_INDEX_BUFFER; + bd.CPUAccessFlags = 0; + bd.MiscFlags = 0; + initData.pSysMem = index_buffer; + hr = g_pd3dDevice->CreateBuffer(&bd, &initData, &g_pIndexBuffer); + if (FAILED(hr)) { + print("CreateBuffer: D3D10_BIND_INDEX_BUFFER\n"); + return hr; + } + + return S_OK; + } + + void Render() + { + XMMATRIX World = XMMatrixScaling(0.1, 0.1, 0.1); + + g_pWorldVariable->SetMatrix((float *)&World); + g_pViewVariable->SetMatrix((float *)&g_View); + g_pProjectionVariable->SetMatrix((float *)&g_Projection); + + UINT stride[] = { + 3 * 3 * 4, + }; + UINT offset[] = { 0 }; + g_pd3dDevice->IASetInputLayout(g_pVertexLayout); + g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVertexBuffer, stride, offset); + g_pd3dDevice->IASetIndexBuffer(g_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0); + g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + D3D10_TECHNIQUE_DESC techDesc; + g_pTechniqueRender->GetDesc(&techDesc); + + int indices_length = (sizeof (index_buffer)) / (sizeof (int)); + for (UINT p = 0; p < techDesc.Passes; p++) { + g_pTechniqueRender->GetPassByIndex(p)->Apply(0); + g_pd3dDevice->DrawIndexed(indices_length, 0, 0); + } + } +} diff --git a/src/effect/collada.fx b/src/effect/collada.fx new file mode 100644 index 0000000..f88529e --- /dev/null +++ b/src/effect/collada.fx @@ -0,0 +1,60 @@ +matrix World; +matrix View; +matrix Projection; + +struct VS_INPUT +{ + float4 Pos : POSITION; + float3 Normal : NORMAL; + float2 Tex : TEXCOORD0; +}; + +struct PS_INPUT +{ + float4 Pos : SV_POSITION; + float3 Normal : NORMAL; + float2 Tex : TEXCOORD0; +}; + +PS_INPUT VS(VS_INPUT input) +{ + PS_INPUT output; + + output.Pos = mul(input.Pos, World); + output.Pos = mul(output.Pos, View); + output.Pos = mul(output.Pos, Projection); + + output.Normal = input.Normal; + output.Tex = input.Tex; + + return output; +} + +float4 PS(PS_INPUT input) : SV_Target +{ + //return float4(input.Normal * 0.5 + 0.5, 1); + return float4(input.Tex.xy, 0, 1); +} + +BlendState DisableBlending +{ + BlendEnable[0] = FALSE; +}; + +DepthStencilState EnableDepth +{ + DepthEnable = TRUE; + DepthWriteMask = ALL; +}; + +technique10 Render +{ + pass P0 + { + SetVertexShader(CompileShader(vs_4_0, VS())); + SetGeometryShader(NULL); + SetPixelShader(CompileShader(ps_4_0, PS())); + SetBlendState(DisableBlending, float4(0.0, 0.0, 0.0, 0.0), 0xffffffff); + SetDepthStencilState(EnableDepth, 0); + } +} diff --git a/src/main.cpp b/src/main.cpp index 7d7d394..27844c4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,6 +17,8 @@ #define ROOT_MESH_NODE robot_player::node_39 #include "cube.hpp" +#include "collada.hpp" + HINSTANCE g_hInstance = NULL; HWND g_hWnd = NULL; ID3D10Device * g_pd3dDevice = NULL; @@ -132,8 +134,8 @@ XMVECTOR g_At = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f); HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow); LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); HRESULT InitDirect3DDevice(); -void Render(float t); -void Update(float t); +void Render(float t, float dt); +void Update(float t, float dt); BOOL Resize(); void InitializeNodeInstances(); @@ -186,6 +188,15 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi return 0; } + if (FAILED(collada::LoadEffect())) { + print("collada::LoadEffect\n"); + return 0; + } + if (FAILED(collada::LoadMesh())) { + print("collada::LoadMesh\n"); + return 0; + } + InitializeNodeInstances(); if (FAILED(InitInput(hInstance))) { @@ -193,6 +204,12 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi return 0; } + LARGE_INTEGER frequency; + LARGE_INTEGER start; + LARGE_INTEGER end; + QueryPerformanceFrequency(&frequency); + QueryPerformanceCounter(&start); + MSG msg = {}; while (msg.message != WM_QUIT) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { @@ -214,11 +231,20 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi TranslateMessage(&msg); DispatchMessage(&msg); } else { + QueryPerformanceCounter(&end); + uint64_t elapsed = end.QuadPart - start.QuadPart; + float dt = (double)elapsed / (double)frequency.QuadPart; + elapsed *= 1000000; + elapsed /= frequency.QuadPart; + if (elapsed < 16667) + continue; + start.QuadPart = end.QuadPart; + if (Resize()) { UpdateInput(); float t = GetTime(); - Update(t); - Render(t); + Update(t, dt); + Render(t, dt); } } } @@ -1045,7 +1071,8 @@ HRESULT InitDirect3DDevice() D3D10_RASTERIZER_DESC RSDesc; RSDesc.FillMode = D3D10_FILL_SOLID; - RSDesc.CullMode = D3D10_CULL_BACK; + //RSDesc.CullMode = D3D10_CULL_BACK; + RSDesc.CullMode = D3D10_CULL_NONE; RSDesc.FrontCounterClockwise = FALSE; RSDesc.DepthBias = 0; RSDesc.SlopeScaledDepthBias = 0.0f; @@ -1473,7 +1500,7 @@ static inline int sprint(LPCSTR fmt, ...) return length; } -void RenderFont() +void RenderFont(float dt) { HRESULT hr; @@ -1496,7 +1523,8 @@ void RenderFont() " thumbLX: % 5.3f\n" " thumbLY: % 5.3f\n" " thumbRX: % 5.3f\n" - " thumbRY: % 5.3f", + " thumbRY: % 5.3f\n" + " dt: % 8.5f\n", g_bloomPasses, g_exposure, g_Joystate.triggerL, @@ -1504,7 +1532,8 @@ void RenderFont() g_Joystate.thumbLX, g_Joystate.thumbLY, g_Joystate.thumbRX, - g_Joystate.thumbRY); + g_Joystate.thumbRY, + dt); const char start_advance = 10; int hadvance = start_advance; @@ -1664,7 +1693,7 @@ float deadzone(float f) } } -void Update(float t) +void Update(float t, float dt) { XMVECTOR vLightDirs[2] = { {-0.577f, 0.577f, 0.0, 1.0}, @@ -1681,12 +1710,12 @@ void Update(float t) // view XMMATRIX mRotateView - = XMMatrixRotationY(deadzone(g_Joystate.thumbLX) * 0.002f) - * XMMatrixRotationX(deadzone(g_Joystate.thumbLY) * 0.002f); + = XMMatrixRotationY(deadzone(g_Joystate.thumbLX) * 3.0f * dt) + * XMMatrixRotationX(deadzone(g_Joystate.thumbLY) * 3.0f * dt); - XMMATRIX mTranslateView = XMMatrixTranslation(deadzone(g_Joystate.thumbRX) * 0.002f, + XMMATRIX mTranslateView = XMMatrixTranslation(deadzone(g_Joystate.thumbRX) * 3.0f * dt, 0.0f, - deadzone(g_Joystate.thumbRY) * 0.002f); + deadzone(g_Joystate.thumbRY) * 3.0f * dt); g_Eye = XMVector4Transform(g_Eye, mTranslateView * mRotateView); XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); @@ -1770,7 +1799,7 @@ void RenderVolumeMesh() } } -void Render(float t) +void Render(float t, float dt) { // clear @@ -1794,9 +1823,11 @@ void Render(float t) //RenderBloom(); //print("%f\n", t); //RenderVolume(t); - RenderVolumeMesh(); + //RenderVolumeMesh(); - RenderFont(); + RenderFont(dt); + + collada::Render(); // present g_pSwapChain->Present(0, 0);