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 0000000..fd21ecb Binary files /dev/null and b/models/skinned_cube/skinned_cube.max differ 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);