Jump to content
    1. Past hour
    2. Using the older platform toolset should suffice. And obviously you may have to look out for API calls that are only available in newer Windows'. I've used VS 2015 with the XP toolset (and statically linked CRT) for a game which runs fine on XP.
    3. Today
    4. Yes. Working as a tester. Applying for a game job. Changing careers into games.
    5. I'm using a library for gizmos (translate, rotate, scale) so that I can control my objects in a scene. I'm using this https://github.com/CedricGuillemet/ImGuizmo. There is a function called Manipulate that takes const float* as the type for a projection and view matrix. also float* for a matrix. I have those Matrices stored in a dx11 XMMATRIX. How do I pass that data?
    6. Hello friends! I've been working on some pretty simplistic pixel art lately, so I put together a picture of the parts of a tile set I'm making. In the picture, you can see grass (one patch with a lighter shade), a stone path, and some cliffs/hills. I've uploaded it to the post. I'm hoping to get a little bit of feedback on it - is it too simplistic that it doesn't do a good job of portraying what it's supposed to be? Is there anything you would recommend changing to make it look a little more realistic? Thanks so much, have a great rest of your day!
    7. Dirk Gregorius

      FBX SDK skinned animation

      Here is my cluster code void RnCluster::Read( fbxsdk::FbxCluster* Cluster ) { FbxCluster::ELinkMode LinkMode = Cluster->GetLinkMode(); if ( LinkMode != FbxCluster::eNormalize ) { return; } FbxNode* Link = Cluster->GetLink(); if ( !Link ) { return; } int ControlPointIndexCount = Cluster->GetControlPointIndicesCount(); const int* ControlPointIndices = Cluster->GetControlPointIndices(); const double* ControlPointWeights = Cluster->GetControlPointWeights(); if ( ControlPointIndexCount <= 0 || !ControlPointIndices || !ControlPointWeights ) { return; } FbxAMatrix TransformLinkMatrix; Cluster->GetTransformLinkMatrix( TransformLinkMatrix ); mBindPose = RnMatrix4( TransformLinkMatrix ); mVertexCount = ControlPointIndexCount; mVertexIndices.Resize( ControlPointIndexCount ); mVertexWeights.Resize( ControlPointIndexCount ); for ( int Index = 0; Index < mVertexCount; ++Index ) { mVertexIndices[ Index ] = static_cast< int >( ControlPointIndices[ Index ] ); mVertexWeights[ Index ] = static_cast< float >( ControlPointWeights[ Index ] ); } } Here is my mesh code (only control points for clarity) void RnModelMesh::Read( FbxMesh* Mesh ) { // Geometric transform FbxNode* Node = Mesh->GetNode(); FbxVector4 GeometricTranslation = Node->GetGeometricTranslation( FbxNode::eSourcePivot ); FbxVector4 GeometricRotation = Node->GetGeometricRotation( FbxNode::eSourcePivot ); FbxVector4 GeometricScaling = Node->GetGeometricScaling( FbxNode::eSourcePivot ); FbxAMatrix OffsetMatrix( GeometricTranslation, GeometricRotation, GeometricScaling ); // Topology mTriangleCount = Mesh->GetPolygonCount(); mTriangleIndices = static_cast<int*>( rnAlloc( 3 * mTriangleCount * sizeof( int ) ) ); for ( int Index = 0; Index < mTriangleCount; ++Index ) { mTriangleIndices[ 3 * Index + 0 ] = Mesh->GetPolygonVertex( Index, 0 ); mTriangleIndices[ 3 * Index + 1 ] = Mesh->GetPolygonVertex( Index, 1 ); mTriangleIndices[ 3 * Index + 2 ] = Mesh->GetPolygonVertex( Index, 2 ); } // Vertex attributes mVertexCount = Mesh->GetControlPointsCount(); mVertexPositions = static_cast<RnVector3*>( rnAlloc( mVertexCount * sizeof( RnVector3 ) ) ); for ( int Index = 0; Index < mVertexCount; ++Index ) { FbxVector4 ControPoint = OffsetMatrix.MultT( Mesh->GetControlPointAt( Index ) ); mVertexPositions[ Index ] = RnVector3( ControPoint ); } }
    8. Hello, I'm working on developing a 2D platformer. In the game, the player can run/jump/etc, and they can also often shoot at the same time that they're performing these other actions. For programming these actions, I have no issue constructing the relevant FSMs and getting them to behave as intended. My issue comes when I need to find the right frames or animations for the sprite to show. Should the game just check if the player is shooting and what state they're in and then have the right animations hardcoded in to play in each possible outcome of that if statement? I've considered some potentially more elegant solutions like having a normal sprite sheet and then a shooting sprite sheet where the shooting sheet has the corresponding shooting frame at the same position in the sheet. Then the animator would just have to load the correct frame of its current sheet no matter what, and whenever the player is shooting, it simply swaps out the regular sprite sheet for the shooting one. Basically I can think of a few different ideas that sort of solve this problem, but none of them seem ideal. I wanted to know what the generally accepted best practices are for this type of problem. Any advice would be appreciated.
    9. Consider worst case of roughly 12 vertices against 12 vertices. That’s 144 loops. However this will operate on memory inside of a very small space in L1 cache. Pretty much, it’s going to be extremely fast.
    10. Last week, support was added to Orx for gamepad controller mapping as well as half-axes, analog thresholds and stick/button/trigger controls remapping. This is made possible by utilizing the SDL Game Controller Database initiative in order to standardize controller sticks and buttons. What this means for games is that no matter what type of controller you plug in, JOY_LX_1 means the X axis on the Left Stick of the first controller. This is much better than the previous JOY_X_1 which meant the same thing, but no guarantee which stick on your controller this would be. This greatly removes the need for creating a re-mapper screen to your games (though still good for convenience). An example of use would look like the following. Firstly the config: [MainInput] JOY_LX_1 = LeftRight Then in code: if (orxInput_IsActive("LeftRight")) { orxFLOAT x = orxInput_GetValue("LeftRight"); //do something } There are a number of joystick tutorials that cover the new features.
    11. MJP

      Silly Input Layout Problem

      The OP's VS code is fine, the shader compiler automatically converts a float4x4 to to 4 float4 attributes in the input signature (with sequential semantic indices).
    12. Yesterday
    13. MJP

      Move view(camera) matrix

      Your view matrix is just the inverse of a matrix representing the world-space transform for your camera. "LookAt" functions will automatically invert the transform for you, but you can also build a "normal" transformation matrix for your camera and then compute the inverse to get a view matrix.
    14. your input implementation just sucks alot, you need to implement your own system
    15. The problem You’re building a game-world that is big, so big in a fact that not all of it can be loaded into memory at once. You also don’t want to introduce portals or level loading. You want the player to have an uninterrupted experience. For true continuous streaming, a typical scenario would be something like this: The world is partitioned into tiles (Quad-tree) When the Camera moves, tile-data is read from disk and pre-processed in the background. We need to render meshes for each tile. There can be more than 1000 tiles in the AOI, more than 100 different meshes and up to 10000 instances per mesh on one tile. How to improve from worst-case 1000000000 draw calls to best-case 1 draw call? Introduction To focus on the render-data preparation specifically, I assume the reader is familiar with the following concepts: Instanced mesh rendering Compute Shaders AOI (Area Of Interest) Quad-tree tile-based space partitioning For an introduction I recommend this BLOG entry on our website:http://militaryoperationshq.com/dev-blog-a-global-scope/ I will use OpenGL to demonstrate details because we use it ourselves and because it is the platform independent alternative. The technique however can be adapted for any modern graphics API that supports compute shaders. The solution The solution is to do the work on the GPU. This is the type of processing a GPU is particularly good at. The diagrams below show memory layout. Each colour represents a different type of instance data, stored non-interleaved. For example, position, texture-array layer-index or mesh scale-factor etc. Within each instance-data-type (colour) range, a sub-range (grey) will be used for storing data for instances of a particular mesh. In this example, there are 4 different meshes that can be instanced. Within the sub-range, there is room to store instance-data for “budget” amount of instances. After loop-stage step 4, we know exactly where to store instance data of each type (pos, tex-index, scale, etc.) for a particular mesh-type. In this example, the scene contains no mesh-type 2 instances and many mesh-type 3 instances. Prepare once at start-up Load all mesh data of the models you want to be able to show in one buffer. Prepare GL state by creating a Vertex Array Object containing all bindings. Create a command-buffer containing Indirect-Structures, one structure for each mesh that you want to be able to render. Fill the Indirect-Structure members that point to (non-instance) mesh vertex data. Steps for one new tile entering the AOI Read geometry from disk Rasterize geometry into a material-map Generate instance-points covering the tile. Select a grid-density and randomise points inside their grid-cell to make it look natural if you’re doing procedural instancing. Whole papers have been written about this topic alone. Sample from the material-map at the grid-point to cull points and decorate data. Store the result in a buffer per tile. Keep the result-buffer of a tile for as long as it is in the AOI Step 1, 2, 3 and 4 may well be replaced by simply loading points from disk if they are pre-calculated offline. In our case we cover the entire planet, so we need to store land-use data in vector form and convert it into raster data online, to keep the install size manageable. Steps for each loop This is where things get interesting. Do frustum and other culling of the tiles so you know what tiles are visible and contain meshes that need rendering. Clear instance-count and base-instance fields of indirect-structures in the command buffer. Run a simple compute shader for this. If you would map the buffer or use glBufferData to allow access from the CPU, you introduce an expensive upload and synchronisation which we want to prevent. Run a compute shader over the tile-set in view to determine which meshes to render. Just count instances per mesh in the instance-count member of the Indirect_structure. This may require sampling from the material map again or doing other calculations to pick a mesh LOD or reflect game-state. It may very well require procedural math to “randomly” spawn meshes. This all depends on your particular game requirements. Fill-in the base-instance member of the Indirect-Structures by launching a single compute shader instance. Run a compute shader to prepare render data. Do the calculations that determine what mesh to select, again. Claim a slot in the vertex-attributes buffer and store render data. since at this point we already know exactly how many instances of each mesh will need rendering (all counts and offsets), we know in what range a particular mesh instance needs to store instance data. The order within the range for a particular mesh doesn’t matter. The important, maybe counterintuitive thing here is, that we do all calculation to determine what mesh to instance, twice. We don’t store the results from the first time. It would be complicated, memory consuming and slow to remember what mesh instance of what tile ends-up at what vertex-data location in the render buffer, just so we can look up an earlier stored result. It may feel wasteful to do the same work twice, but that is procedural thinking. On the GPU it is often faster to recalculate something then to store and read back an earlier result. Now everything is done on the GPU and we only need to add some memory-barriers to make sure data is actually committed before a next step is using it. Atomic operations Note that step 3 and 5 of the loop-stage require the compute shader to use atomic operations. They are guaranteed to not conflict with other shader-instances when writing to the same memory location. Instance budget You need to select a budget for the maximum number of meshes that can be drawn at once. It defines the size of the instance-data buffer. This budget may not cover certain extreme situations. This means we need to make sure we do not exceed the budget. Step 4 updates the base-instance of the indirect-structure. At that point, we can detect if we exceed the budget. We can simply force instance-counts to zero when we reach the budget. But this will have the effect of potentially very visible mesh instances to be in or excluded from the render-set each loop. To solve this, sort the indirect-structures, representing meshes, in the command-buffer from high to low detail. This is only needed once at start-up. That way the first meshes that will be dropped are low LOD and should have the least impact. If you’re using tessellation to handle LOD, you’ll have to solve this differently or make sure your budget can handle the extreme cases. Ready to render We now have one buffer containing all render data needed to render all instances of all meshes on all tiles, in one call. We simply do a single Render call using the buffer that contains the indirect-structures. In fact, we render all possible meshes. If for the current situation, some meshes do not need to be rendered, their instance-count in the indirect-structure will be zero and it will be skipped with very little to no overhead. How it used to be In a traditional scenario, we may have filled an indirect-structure buffer with only structures for the meshes that need rendering. Then copying all render data in a vertex-attribute buffer, in an order to match the order of indirect-structures in the command buffer. Which means we need a sorting step. Next, an upload of this render data to the GPU is required. Since the upload is slow, we will probably need to double or, even better, triple buffer this to hide transfer and driver stages so we don’t end up waiting before we can access/render a buffer. Summary Key points Preprocess and store intermediate data on the GPU Make mesh instance render order fixed and render all meshes always Use a 2 pass approach, first count instances so we can predict memory layout the second time. Benefits No upload of render data each render-loop No need to refill/reorder the command-buffer (indirect-structures) every loop No sort needed to pack vertex-data for mesh instances No need for double/triple buffering Improvements The most performance is gained by selecting the best design for your software implementation. Nevertheless, there is some low hanging fruit to be picked before going into proper profiling and tackling bottlenecks. Memory allocation You should use glBufferStorage to allocate GPU memory for buffers. Since we never need to access GPU memory from the CPU, we can do this: glBufferStorage(GL_ARRAY_BUFFER, data_size, &data[0], 0); The last parameter tells the GL how we want to access the memory. In our case we simple pass 0 meaning we will only access it from the GPU. This can make a substantial difference depending on vendor, platform and driver. It allows the implementation to make performance critical assumptions when allocating GPU memory. Storing data This article describes vertex-data that is stored non-interleaved. We are in massively parallel country now, not OO. Without going into details, the memory access patterns make it more efficient if, for example, all positions of all vertices/instances are packed. The same goes for all other attributes. Frustum Culling In this example, tile frustum-culling is done on the CPU. A tile, however, may contain many mesh instances and it makes good sense to do frustum culling for those as well. It can be easily integrated into step 3 and performed on the GPU. Launching compute shaders The pseudo-code example shows how compute shaders are launched for the number of points on each tile. This means the number of points needs to be known on the CPU. Even though this is determined in the background, downloading this information requires an expensive transfer/sync. We can store this information on the GPU and use a glDispatchComputeIndirect call that reads the launch size from GPU memory. A trend This article shows how more work can be pushed to the GPU. We took this notion to the extreme by designing an engine from the ground up, that is completely running on the GPU. The CPU is only doing I/O, user interaction and starting GPU jobs. You can read more about our “Metis Tech” on our blog page: http://militaryoperationshq.com/blog/ The main benefits are the lack of large data up/downloads and profiting from the huge difference in processing power between GPU and CPU. At some point, this gap will become a limiting bottleneck. According to NVidia, the GPU is expected to be 1000x more powerful than the CPU by 2025! (https://www.nextplatform.com/2017/05/16/embiggening-bite-gpus-take-datacenter-compute/) Appendix A - Pseudo C++ code //! \brief Prepare render data to draw all static meshes in one draw call void prepare_instancing( const std::vector<int32_t>& p_tiles_in_view // Points per tile , const std::vector<GLuint> p_point_buffer , int32_t p_mesh_count , GLuint p_scratch_buffer , GLuint p_command_buffer , GLuint p_render_buffer , GLuint p_clear_shader , GLuint p_count_shader , GLuint p_update_shader , GLuint p_prepare_shader) { glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, p_command_buffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, p_scratch_buffer); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, p_render_buffer); // 2. Clear instance base and count glUseProgram(p_clear_shader); glDispatchCompute(p_mesh_count, 1, 1); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); // 3. Count instances per mesh glUseProgram(p_count_shader); for (int32_t l_tile_index = 0; l_tile_index < p_tiles_in_view.size(); ++l_tile_index) { glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, p_point_buffer[l_tile_index]); glDispatchCompute(p_tiles_in_view[l_tile_index], 1, 1); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); } // 4. Update instance base glUseProgram(p_update_shader); glDispatchCompute(1, 1, 1); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); // 5. Prepare render data glUseProgram(p_prepare_shader); for (int32_t l_tile_index = 0; l_tile_index < p_tiles_in_view.size(); ++l_tile_index) { glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, p_point_buffer[l_tile_index]); glDispatchCompute(p_tiles_in_view[l_tile_index], 1, 1); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); } glUseProgram(0); glBindBuffersBase(GL_SHADER_STORAGE_BUFFER, 0, 4, nullptr); } //! \brief Render all instances of all meshes on all tiles in one draw call void render_instanced( GLuint p_vao , GLuint p_command_buffer , GLuint p_render_shader , int32_t p_mesh_count) // Number of different meshes that can be shown { glBindVertexArray(p_vao); glUseProgram(p_render_shader); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, p_command_buffer); glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0, p_mesh_count, 0); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); glUseProgram(0); glBindVertexArray(0); } Appendix B – Compute-shader pseudo-code 2. Clear shader //**************************************************************************** //! \brief 2. p_clear_shader: Clear counts and offsets //**************************************************************************** // The local workgroup size layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; // Input: Contains the indirects-structs for rendering the meshes layout(std430, binding=0) buffer p_command_buffer { uint p_indirect_structs[]; }; // IO: Containing uints for counting point-instance-data per mesh, and claiming slots layout(std430, binding=2) buffer p_scratch_buffer { uint p_instance_counts[]; // Globally for all tiles. Size = number of mesh variants }; void main() { uint l_invocation_id = gl_GlobalInvocationID.x; p_indirect_structs[l_invocation_id * 5 + 1] = 0; // 5 uints, second is the instance-count. p_instance_counts[l_invocation_id] = 0; } 3. Count shader //**************************************************************************** //! \brief 3. p_count_shader: Count instances //**************************************************************************** // The local workgroup size layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; // Output: Contains the indirect-structs for rendering the meshes layout(std430, binding=0) buffer p_command_buffer { uint p_indirect_structs[]; // Globally for all tiles }; layout(std430, binding=1) buffer p_point_buffer { uint p_point_data[]; }; void main() { uint l_invocation_id = gl_GlobalInvocationID.x; //! \note What p_point_data contains is application specific. Probably at least a tile-local position. uint l_data = p_point_data[l_invocation_id]; //! \todo Use data in p_point_data to determine which mesh to render, if at all. uint l_mesh_index = 0; atomicAdd(p_indirect_structs[l_mesh_index], 1); // Count per instance } 4. Update shader //**************************************************************************** //! \brief 4. p_update_shader: Update instance base //**************************************************************************** // The local workgroup size layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; // Input: Contains the indirect-structs for rendering the meshes layout(std430, binding=0) buffer p_command_buffer { uint p_indirect_structs[]; }; uniform uint g_indirect_struct_count = 0; uniform uint g_instance_budget = 0; void main() { uint l_invocation_id = gl_GlobalInvocationID.x; // This compute-shader should have been launched with 1 global instance! if (l_invocation_id > 0) { return; } // Update base-instance values in DrawElementsIndirectCommand int l_index, l_n = 0; p_indirect_structs[l_index * 5 + 4] = 0; // First entry is zero bool l_capacity_reached = false; for (l_index = 1; l_index < g_indirect_struct_count; ++l_index) { l_n = l_index – 1; // Index to the indirect-struct before uint l_base_instance = p_indirect_structs[l_n * 5 + 4] + p_indirect_structs[l_n * 5 + 1]; // If the budget is exceeded, set instance count to zero if (l_base_instance >= g_instance_budget) { p_indirect_structs[l_index * 5 + 1] = 0; p_indirect_structs[l_index * 5 + 4] = p_indirect_structs[l_n * 5 + 4]; } else { p_indirect_structs[l_index * 5 + 4] = l_base_instance; } } } 5. Prepare shader // The local workgroup size layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; // Input: Contains the indirect-structs for rendering the meshes layout(std430, binding=0) buffer p_command_buffer { uint p_indirect_structs[]; }; // Input: Containing point data layout(std430, binding=1) buffer p_point_buffer { uint p_point_data[]; }; // IO: Containing mesh-counts for claiming slots layout(std430, binding=2) buffer p_scratch_buffer { uint p_instance_counts[]; // Globally for all tiles. Size = g_indirect_struct_count }; // Output: Containing render data layout(std430, binding=3) buffer p_render_buffer { uint p_render_data[]; }; uniform uint g_indirect_struct_count = 0; uniform uint g_instance_budget = 0; void main() { uint l_invocation_id = gl_GlobalInvocationID.x; uint l_data = p_point_data[l_invocation_id]; //! \todo Use data in p_point_data to determine which mesh to render, if at all. Again. uint l_mesh_index = 0; // This should never happen! if ( l_mesh_index >= g_IndirectStructCount) { return; } // Only process meshes that have an instance count > 0 if (p_indirect_structs[l_mesh_index * 5 + 1] == 0) { return; } // Reserve a spot to copy the instance data to uint l_slot_index = atomicAdd(p_instance_counts[l_mesh_index], 1); // From mesh-local to global instance-index l_slot_index += p_indirect_structs[l_mesh_index * 5 + 4]; // Make sure to not trigger rendering for more instances than there is budget for. if (l_slot_index >= g_instance_budget) { return; } //! \todo Write any data you prepare for rendering to p_render_data using l_slot_index } PDF format: Efficient instancing in a streaming scenario.pdf [Wayback Machine Archive]
    16. My understanding of behavior trees is that you define a whole bunch of functions in your game code that return a boolean. These can be functions that get information about the situation (Is there an enemy nearby? Do I have ammo? Is my health above 60%?) or functions that actually do something and return whether they succeeded (Move to take cover. Shoot at the weakest enemy within range. Say "Halt!"). A behavior tree is then an expression that joins these functions with the equivalent of the operators || and && from C. The strength of this paradigm is that it's impossible for the game designer to go crazy with the complexity of the behaviors. If you need to define a whole bunch of variables in a blackboard, perhaps this very simple architecture is not a good fit for your task.
    17. Irlan Robson

      FBX SDK skinned animation

      While Dirk is searching his beautiful code you can try reading this code for becoming familiar with skeletal animation and skinning. However, this code ignores the geometric transform. Since most of my test models are from mixamo, I haven't needed such a transform. If you need this transform then simply transform the mesh vertices and normals using it, as Dirk pointed out.
    18. I've been using Sutherland-Hodgman for years with good results. Yes, it's fast enough and simple to implement. The good thing is that it preserves the polygon vertex order. Not informed about temporal coherency in the context of clipping. However, in the context of contact creation, temporal coherency can be exploited by reclipping the touching features. If two faces are chosen as the touching features in one frame, you run clipping and cache these features. If these two faces still are the touching features in the next frame, you check if the relative orientation of the shapes has changed up to some small tolerance. If not, you reclip those features. Of course we assume you can detect the touching features using an algorithm such as the SAT.
    19. Hi, Most people seem to prefer some version of Sutherland–Hodgman clipping when generating one-shot contacts. Sutherland–Hodgman has O(n*m) time complexity. Is this fast enough for most practical purposes or is there a compelling reason to pick a different algorithm with better time complexity? I guess I could always profile, but I'm also asking in case there are other considerations that I may have overlooked... Is there for example some case of temporal coherency that can be exploited? Thanks!
    20. Awoken

      Moving the Masses

      I'm very pleased to showcase the new functionality I've incorporated allowing the user to select many Simulin at once. This feature was always on the back-burner because there were more pressing things to address. I'll quickly go through the technique I used. But first, please watch the following videos! I created a two faced plane where the opposite corners are defined by the vertices obtained from the right-click down and up events. Then raycaste to the planet twice and I have all four corners for the plane. After that I normalized the vertices and then raycaste from the position of every visible Simulin to the center of the planet. It's not 100% perfect, because the perspective camera obscures things a bit and the box that is drawn is an html element. For this reason Simulin along the edges of the selection box will sometimes not be selected. But really? big deal... Once the target Simulin are identified the user selects the destination. This is where the scripted behaviour of the Simulins movement comes in. Rather than having all the Simulin converge on a single point I created a move-able plane whose vertices are defined in a spiral $cINT.definePositionPlane = function( u ){ // u is the unit scale for the world var a = new THREE.Geometry(); var mat = new THREE.MeshLambertMaterial( { side: THREE.DoubleSide } ); a.vertices.push( $m.v( 0 , 0 , 0 ) ); for( var i=0, j=61, k=61, l=1, q=-1, p=1, b=15; i<121; i+=0 ){ if( l < 11){ for( var n=0; n<l; n++ ){ j += q; a.vertices.push( $m.v( ( j - 61 ) * u * b , 0 , ( k - 61 ) * u * b ) ); i++; } for( var n=0; n<l; n++ ){ k += p; a.vertices.push( $m.v( ( j - 61 ) * u * b , 0 , ( k - 61 ) * u * b ) ); i++; } q*=-1; p*=-1; l++; } else { for( var n=0; n<10; n++ ){ j += q; a.vertices.push( $m.v( ( j - 61 ) * u * b , 0 , ( k - 61 ) * u * b ) ); i++; } i = 121; } } var f = new THREE.Face3( 0 , 10 , 120 ); a.faces.push( f ); f = new THREE.Face3( 0 , 120 , 110 ); a.faces.push( f ); a.computeFaceNormals(); var m = new THREE.Mesh( a , mat ); m.visible = true; return m; }; The plane is moved and then oriented over the point the user chose. Each Simulin requesting a path is given an incremental vertices obtained from the selection plane. A raycaste call is done from that vertices location once the vertices is extrapolated to its global position. From there I get the sphere position and that become the unique goal for the Simulin in question. I think the effect looks awesome. Right now you draw the selection box by holding down the right mouse button and then when you release it the calculations are done. I'm also thinking that in the future I can program a custom routine and color for the direction in which you draw the selection box. If you go left to right, up to down then maybe you select every Simulin. right to left, up to down then maybe you select only hunters or some such idea. Let me know what you think....
    21. Hello all, I'm working on some code to position an arrow in the direction of the left thumb stick. I believe I cannot get the behavior I want do to imprecise hardware. What do you think? Is there a way to solve this? Here is what I want to happen: - As the player does a full 360 degree rotation with a full push on the left thumb stick I want the aim arrow to do a smooth 360 degree rotation. Here is what happens: - As the player does the full 360 degree rotation the arrow sticks in the angles of 45, 135, -42, -135 degrees (four cournrs). Why this happens: - The raw input I get for the analog stick hits a value of 1 well before full extension. This means that there is a large region where x and y's absolute value will be greater than one. This in turn leads to that stickiness. My thoughts: - because this happens at the hardware level and the value's max is one there is nothing I can do about it. What do you think? Is there a way to get the behavior I want, that is a nearly exact mapping of a extended joystick angle to angle I get from the input.
    22. phil67rpg

      shooting bullets

      glPushMatrix(); glTranslatef(-4.5f, 0.5625f,0.0f); glRotatef(angle, 0.0f, 0.0f, 1.0f); glTranslatef(4.5f, -0.5625f, 0.0f); glBegin(GL_POLYGON); glTexCoord3f(0.0f, 0.0f, 0.0f); glVertex3f(-4.4375f, 0.625f+up+vertical, 0.0f); glTexCoord3f(1.0f, 0.0f, 0.0f); glVertex3f(-4.4375f, 0.5f+up+vertical, 0.0f); glTexCoord3f(1.0f, 1.0f, 0.0f); glVertex3f(-4.5625f, 0.5f+up+vertical, 0.0f); glTexCoord3f(0.0f, 1.0f, 0.0f); glVertex3f(-4.5625f, 0.625f+up+vertical, 0.0f); glEnd(); glPopMatrix(); I am trying to draw a bullet down but it can only draw an up bullet
    23. Consider following code: std::string function() { std::string test("This is some very long string..."); // ... use test return test; } I know that string literals in pointers (char* psz = "some string";) are stored in .rodata of an exe file and that string literals defined in an array are stored locally or wherever the array is stored, on stack if array is on stack or in object heap if object is stored on heap. This can be seen here. What about the code above. For long strings std::string stores chars on the heap. But before they get to the heap, is the above string "This is some very..." stored somewhere? Just by intuition I would say no. If it would be stored somewhere, let's say .rodata, it would just clutter unnecessarily the exe file so it doesn't make a lot sense. Am I right? I know that it might be implementation defined but I'm asking only for x86 system.
    24. I appreciate the feedback and have done some more testing with it in mind... The "touch" seems to work fine with connection with the tips of my thumbs, but not so much on the undersides - as you would with a gamepad. I notice this is easier to do with a smaller device, and with my Huawei y300, where its not so much a problem and actually works very well... However, it is harder to do on my Nexus 7 Tablet...which is because its clamped into a sodding protective cover! Taking it out of the cover and suddenly its not so much a problem and a far better experience... Sigh, if there was ever a time for face-palm then its definitely now! So really, the problem appears to be a matter of thumb reach of the buttons. Improvements I can think of is placing the left & right buttons closer to the left-hand side of the screen, and instead of the three buttons current "corner" arrangement I shall try them in a vertical arrangement alongside the right-hand side of the screen... Once again, thank you all for the feed back and your time. I feel I am much closer to a far better control system for my game. Cheers! Steve.
    25. Hi, unfortunately i don't really have any programming experience which i feel will be something that potentially holds me back. My current background is electrical engineering and ideally i'd love to make it up to game development level one day and have control over making something and producing games. Thanks for the reply
    26. Do you have any programming experience? Even though I think it's not mandatory, I've heard that QA positions in general (I guess in gaming industry as well) have started to consider at least basic scripting programming a valuable skill. I guess probably Python is a good technology to learn. Is your current job related at all with tech? What is your target position? I mean, what job would you like to get to after X years in the industry? Regards!
    27. Timothy Sharp

      Launchpad Games Discord

      Alright https://discord.gg/9HTVyWg
    28. Hi guys, let me introduce my new project - Just Smash It! It's all about destruction! Break your way smashing objects with aimed shots! * Realistic physics of destruction * Smooth game flow * Pleasant graphic and sound design * Infinite mode after passing the basic set of levels * Small size, great time-killer! Play Market: https://play.google.com/store/apps/details?id=com.blackspoongames.smashworld Feedback are welcome!
    29. I3DI

      Water Realism

      Just a little preview of the water in our game at night. It's a work in progress. Since down the road I wish to do simulations, the water material takes light and calculates the color. The opacity is based on muck and various particles in the water, which changes. The ripples will generally travel more in the direction of the wind. The wind is determined by barometric pressure in the varying layers in the atmosphere, and temperature is determined by the angle of a geographic location and the distance from the sun, lack of sunlight getting thru, clouds, surface temps, and time of day. Hope you enjoyed this little preview. Getting water to look like this was no simple task!
    30. I have made a simple 2D game supposed to run on Windows only using SFML. The executable is built using Visual Studio 2017. I would like to make sure that it can run on as many Windows machines as possible (even on Windows 7/8 if possible). What steps can I take to ensure that? I have done the following: Build for Win32 (x86) not x64 platform In Project Properties->C/C++->Code Generation, I set Runtime Library to Multi-threaded (runtime library should thus be statically packed with the exe) not Multi-Threaded DLL Would the following help with compatibility (and not cause problems with forward compatibility)? Using Windows SDK version 8.1? Use older platform toolset (not Visual Studio 2017 v141 but perhaps VS 2015 v140 or even VS 2015 Windows XP) What else can I do, and what should I be aware of? Thanks.
    31. Hi all, I'm looking for a career change as the job that i currently do is neither a passion or something that i really want to be doing for the rest of my life. I would ideally like to begin a career in the gaming industry as like most others i have a strong passion for gaming and all things related. I have been looking into a junior test analyst QA job and was wondering if this is the correct place to start. I'm a dedicated worker so don't mind working my way up and I love being hands on with things. I was wondering if anyone had any advice regarding this or how i can go about gaining experience in this field to give myself the best chance. I'm more than willing to do either weekend work or free work to get my foot in the door so if there is any advice or help anyone could give me that would be great. Thanks for reading, Dan
    32. mellinoe

      Renderdoc can see my model but...

      For me, the next step is usually to rule out depth/stencil/backface issues. I'd go over to the "Texture Viewer" tab, select the color/depth output textures, and check these "Overlay" visualizations: Highlight drawcall. It should show something since your mesh is visible in the VS Output window. Depth test + Stencil Test (if you're using stencil). It should be green. If it's red, then you have something wrong with your depth buffer or depth test settings. Backface Cull. It should be green. Red means it's being culled.
    33. mrMatrix

      FBX SDK skinned animation

      Thank you and take your time . The skeletal problem was """fixed""" by putting both the old code and your 'Read' function back into ProcessJointsAndAnimations() function and switching between them. Note the discrepancies between the two approaches, though. The top is your 'Read' function, the bottom is TLang1991 void FBXtoAbj::ProcessJointsAndAnimations(FbxNode *inNode) { FbxMesh *currMesh = inNode->GetMesh(); uint numDeformers = currMesh->GetDeformerCount(); for (uint i = 0; i < numDeformers; ++i) { FbxSkin *currSkin = reinterpret_cast<FbxSkin *>(currMesh->GetDeformer(i, FbxDeformer::eSkin)); if (!currSkin) continue; uint numClusters = currSkin->GetClusterCount(); for (uint j = 0; j < numClusters; ++j) { FbxCluster *currCluster = currSkin->GetCluster(j); string currJointName = currCluster->GetLink()->GetName(); uint currJointIndex = FindJointIndexUsingName(currJointName); FbxAMatrix transformMatrix, transformLinkMatrix; FbxAMatrix geometryTransform = GetGeometryTransformation(inNode); //geometryTransform.SetIdentity(); currCluster->GetTransformMatrix(transformMatrix); //the xform of the mesh at binding time currCluster->GetTransformLinkMatrix(transformLinkMatrix); // the xform of the cluster(jnt) at binding time from joint space to world space mJoints[currJointIndex].mGlobalBindpose = transformLinkMatrix * transformMatrix * geometryTransform; mJoints[currJointIndex].mGlobalBindposeInverse = transformLinkMatrix.Inverse() * transformMatrix * geometryTransform; //mJoints[currJointIndex].mNode = currCluster->GetLink(); //associate each joint with the ctrl pts it affects uint numIndices = currCluster->GetControlPointIndicesCount(); for (uint k = 0; k < numIndices; ++k) { BlendingIndexWeightPair currBlendingIndexWeightPair; currBlendingIndexWeightPair.mBlendingIndex = currJointIndex; currBlendingIndexWeightPair.mBlendingWeight = currCluster->GetControlPointWeights()[k]; mControlPoints[currCluster->GetControlPointIndices()[k]]->mBlendingInfo.push_back(currBlendingIndexWeightPair); } /* get animation info (for 1 "take") */ //for (uint i = 0; i < mJoints.size(); ++i) { FbxTime::SetGlobalTimeMode(FbxTime::eFrames24); FbxAnimStack *currAnimStack = mScene->GetSrcObject<FbxAnimStack>(0); mScene->SetCurrentAnimationStack(currAnimStack); FbxString Name = currAnimStack->GetNameOnly(); FbxString TakeName = currAnimStack->GetName(); FbxTakeInfo* TakeInfo = mScene->GetTakeInfo(TakeName); FbxTimeSpan LocalTimeSpan = TakeInfo->mLocalTimeSpan; FbxTime Start = LocalTimeSpan.GetStart(); FbxTime Stop = LocalTimeSpan.GetStop(); FbxTime Duration = LocalTimeSpan.GetDuration(); FbxTime::EMode TimeMode = FbxTime::GetGlobalTimeMode(); FbxLongLong FrameCount = Duration.GetFrameCount(TimeMode); double FrameRate = FbxTime::GetFrameRate(TimeMode); for (FbxLongLong f = Start.GetFrameCount(TimeMode); f <= Stop.GetFrameCount(TimeMode); ++f) { FbxTime Time; Time.SetFrame(f, TimeMode); bool useDirk = 0; //bool useDirk = 1; if (useDirk) { for (FbxNode *Node : allJointsOnFBX) { //if (Node->GetName() == mJoints[i].mName) if (Node->GetName() == mJoints[currJointIndex].mName) { FbxAMatrix LocalTransform = Node->EvaluateGlobalTransform(Time); //is there a parent bone? If so, need to apply that parents global inverse transform to this node's transform if (FbxNode *Parent = Node->GetParent()) { FbxNodeAttribute *ParentAttribute = Parent->GetNodeAttribute(); if (ParentAttribute && ParentAttribute->GetAttributeType() == FbxNodeAttribute::eSkeleton) { FbxAMatrix GlobalParentTransform = Parent->EvaluateGlobalTransform(Time); LocalTransform = GlobalParentTransform.Inverse() * LocalTransform; } } mJoints[currJointIndex].keyframes.push_back(LocalTransform); } } } else { FbxAMatrix currentTransformOffset = inNode->EvaluateGlobalTransform(Time) * geometryTransform; FbxAMatrix LocalTransform = currentTransformOffset.Inverse() * currCluster->GetLink()->EvaluateGlobalTransform(Time); mJoints[currJointIndex].keyframes.push_back(LocalTransform); } } } } }
    34. Dirk Gregorius

      FBX SDK skinned animation

      Vector is a 3D vector and the std:fill initializes them to zero. This is so I can correctly accumulate. I need to search through my repository to find the FBX cluster and mesh extraction code. Then I will post it here, but this might take until tomorrow. Sorry for the delay, I switched to exporting directly from Maya since I added ragdolls and cloth and wrote my own plug-ins. It didn't make sense to use FBX for me anymore. I need to dig it up if I find time later today...
    35. Vilem Otte

      Beginning developing

      To further continue on question what happens when your games fail (or generally you fail business side miserably) - I will post a real world example - Telltale Games. https://twitter.com/telltalegames/status/1043252010999410689 The studio recently terminated majority of the positions, and seems to be closing up.
    36. RidiculousName

      Programming and Higher Mathematics

      Everyone, thank you for responding. I was wondering, can I see a code example of how much easier it is to do something with knowledge of Calculus/Trigonometry? Preferably in Java or some other C-Like language? Currently, I am learning about logarithms and graphing in my college Precalculus class.
    37. Setup Game 2 was supposed to be a 6-player game, choose whatever race you wanted, balanced map. That dropped to a 5-player game when one of the players couldn't make it. Then a 5th player bailed last minute and his phone didn't send the message. It's worth noting that he felt terrible about this and apologized multiple times. So instead of having the map setup and ready to rock and roll right at game time. We started 30 minutes late and had to build the map the old fashioned way. I think it's a testament to the streamlined improvements that we were still able to finish in a reasonable 8.5 hours (including pizza phase). Here's what happened... Race selection method - choose whatever you want. Speaker - roll randomly and Sardakk N'orr got it. Devin - Mentak (green) - Playing Mentak again. Damn pirates Dalton - Federation of Sol (blue) - New player - came super prepared and even had notes for early strategies after listening to Space Cats and Peace Turtles. Javi - Letnev (purple) - New player Eck - Sardakk N'orr (black/me) - I won the last game, so for this game I was going to go for more role-playish fun. I planned to go combat focused and support others who did the same. The 5th player - no show was supposed to play Embers of Muat. I was hoping to trade the War Sun tech with him, and I'd have payed silly prices to make that happen. Ah well... Some other time! Instead we randomly built the map, and I didn't take a clean pic of it because I was focused on analyzing the new board. Sorry about that! One thing to keep in mind for a 4-player game is every strategy card gets picked so every secondary action is possible on your turn. This is super useful for counting on secondaries as part of your grand plans. I only mention this cause I took too long to write up this after action report, so I don't recall all my strategy card picks. Round 1 - I told the table my idea of me wanting to take the game a little less seriously. I'd still try to win but my goal was to be a warlike bug race. Everyone else was welcome (and encouraged) to play their best. They were game so the first proclamation I made was - whoever wins the first combat, gets my support for the throne! The table snickered and agreed. Other than that, it was a pretty standard early turn, Sardaak N'orr (black/me) got Warfare and expanded towards Letnev (purple) for some early trading partners. Everyone else expanded a bit. 0 - Mentak (green/Devin) 0 - Federation of Sol (blue/Dalton) 1 - Letnev (purple/Javi) 0 - Sardakk N'orr (black/Eck/me) Round 1 end Round 2 - Federation of Sol (blue) was poised to take Mecatol this turn and chose Imperial. The rest of the table agreed this was a bad idea (once Sol gets on Mecatol, it's hell to kick him off) so Mentak (green) blocked him with a couple of cruisers. Blue took our shared border planet without even talking about it. Though I respected the move as a combat-focused-space-bug, I planned my counter strike for this transgression. 1 - Mentak (green/Devin) 0 - Federation of Sol (blue/Dalton) 2 - Letnev (purple/Javi) 0 - Sardakk N'orr (black/Eck/me) Round 2 end Someone offered me a stick of gum... It made me laugh pretty hard. Round 3 - This was an exciting turn. Lots of combat so the space-bugs were pleased! The Federation (blue) kicked those pesky Mentak (green) pirates off of Mecatol. A bug of my word, I gave him my support for the throne. Letnev (purple) lost two ground forces trying to take a border world I said he could have. Blue had blocked the only access into his undefended world... That is, it was the only way if you were unwilling to risk the Gravity Rift... Sardakk N'orr (black/me) hurled a carrier past the gravity rift successfully to take the Federation's (blue's) richest world. For those that are unfamiliar with the rule, every ship you send out of or through a Gravity Rift gets a +1 to their speed. However on a 1d10 roll of 1-3, the ship is destroyed. It could have been the Federation's undefended homeworld, but Blue was a new player and I didn't want to be THAT mean. 3 - Mentak (green/Devin) 4 - Federation of Sol (blue/Dalton) 2 - Letnev (purple/Javi) 1 - Sardakk N'orr (black/Eck/me) Gravity Rift Snipe Round 3 end Round 4 - I forgot to take a picture cause so much stuff was going on. And it's been too long to remember ALL the details. Sardakk N'orr (black/me) managed to kick the Federation (blue) off of Mecatol through a combination of action cards, bombardment, and a ton of ground forces. I got back, gave up, and got back my Support for the Throne. I think it wound up in Mentak's (green's) hands. This time I think it was for destroying someone's Dreadnaught? Sardakk N'orr (black/me) had a massive fleet on and around Mecatol Rex when the agenda Ixthian Artifact came up. I had lots of influence but definitely not enough to win the vote. I put down 19 against, other people put 24 for. Then I played the action card to get +5 votes. Since I was the speaker, I broke ties... We rolled the die anyway as a what-if and it came up 5. WHEW! Mentak (green) snagged a poorly defended Federation (blue) world and blew up a space dock. And people also started building up their fleets.<score guess> 6 - Mentak (green/Devin) 5 - Federation of Sol (blue/Dalton) 4 - Letnev (purple/Javi) 3 - Sardakk N'orr (black/Eck/me) <pic missing> Round 5 - Lots of fleet massing! Sardakk N'orr (black/me) had nearly ALL their plastic out on the board at one point. More massive battles, Mentak (green) jumped ahead to 8 during the round, but I used the Silence of Space action card to sneak through the overly defended wormhole and snipe his homeworld. Now Mentak(green) was in a weird position. To get his homeworld back he'd have to attack me, which would lose his support for the throne... 8- Mentak (green/Devin) 6 - Federation of Sol (blue/Dalton) 6 - Letnev (purple/Javi) 5 - Sardakk N'orr (black/Eck/me) Round 5 end Round 6 - Sadakk N'orr (black/me) wound up playing Diplomacy on Mentak(green's) home system, meaning he couldn't take it back this round. He still scored a secret objective though which brought him up to 9. People tried desperately to kick Sardakk N'orr (black/me) off of Mecatol, but just couldn't do it. There was too much plastic on the board. 9 - Mentak (green/Devin) 7 - Federation of Sol (blue/Dalton) 6 - Letnev (purple/Javi) 7 - Sardakk N'orr (black/Eck/me) Round 6 end Round 7 - With a point for mecatol, and a 2 point tech objective, Sardaak N'orr(black/me) was able to clinch the victory. Had I been unable to score mid-turn, Mentak (green) would have won without owning his home system by scoring his last secret objective. The picture of the board was pretty much the same, since my first action ended the game. Final score 9 - Mentak (green/Devin) 7 - Federation of Sol (blue/Dalton) 7 - Letnev (purple/Javi) 10 - Sardakk N'orr (black/Eck/me) VICTORY!!! Final thoughts This was a long and crazy ride. I think I wound up giving my support for the throne away about 4 times? I really shouldn't have won this game, but the second half of the game lined up perfectly as far as agendas and objectives were concerned. Other people just couldn't score those big 2 point objectives and I barely managed to eek out a victory. I am now 2 for 2 in my Twilight Imperium 4th games! Wish me luck for the next game. Other Notes Here was our cool 5 player map setup. This took quite a while to balance and even though we didn't actually use it, I thought others might be interested in a balanced Twilight Imperium 5 player map. The red hexes are impassible, and the 2 trade goods were a suggestion online. I'm not sure the trade goods are necessary though. Special thanks to my daughter for helping me tweak the board.
    38. mrMatrix

      FBX SDK skinned animation

      What you have on the last bit of code is CPU skinning, yes? Could you go into that in a bit more detail...when you say std::vector<Vector> I assume you mean vector4 and are doing the std::Fill with the mesh position vec4 elements? Here is some snippets of my code. I'm making progress but putting your Read() function in has made my skeletal debug not function properly. I assume I need to switch and store both local and absolute coordinates? Looking at my code below in that section, how would that be added? From this picture of the skinning on the mesh you can see that it is squished lengthwise and doesnt deform correctly. This is what I have: //get skeleton hierarchy with DFS //get inverse bindpose for joint //joints are associated with control points //get keyframe poses with your function based on readAnimation //generate / write out keyframe poses with your function 'readanimation' to XML //read from XML file //calculate skinning interpolation //send to gbuffer animation shader struct Joint { string mName; int mParentIndex; FbxAMatrix mGlobalBindposeInverse; FbxAMatrix mGlobalBindpose; FbxNode *mNode; }; ProcessSkeletonHierarchy(mScene->GetRootNode()); void FBXtoAbj::ProcessSkeletonHierarchy(FbxNode *inRootNode) { cout << "inRootNode->GetChildCount() = " << inRootNode->GetChildCount() << endl; for (int i = 0; i < inRootNode->GetChildCount(); ++i) { FbxNode *currNode = inRootNode->GetChild(i); ProcessSkeletonHierarchyRecursively(currNode, 0, -1); } } void FBXtoAbj::ProcessSkeletonHierarchyRecursively(FbxNode *inNode, int myIndex, int inParentIndex) { if (inNode->GetNodeAttribute() && inNode->GetNodeAttribute()->GetAttributeType() && inNode->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eSkeleton) { Joint currJoint; currJoint.mParentIndex = inParentIndex; currJoint.mName = inNode->GetName(); mJoints.push_back(currJoint); allJointsOnFBX.push_back(inNode); } for (int i = 0; i < inNode->GetChildCount(); ++i) ProcessSkeletonHierarchyRecursively(inNode->GetChild(i), int(mJoints.size()), myIndex); } //GET INVERSE BINDPOSE FOR JOINT / JOINTS ARE ASSOCIATED WITH CONTROL POINTS ProcessJointsAndAnimations(inNode); ProcessMesh(inNode); void FBXtoAbj::ProcessJointsAndAnimations(FbxNode *inNode) { FbxMesh *currMesh = inNode->GetMesh(); uint numDeformers = currMesh->GetDeformerCount(); for (uint i = 0; i < numDeformers; ++i) { FbxSkin *currSkin = reinterpret_cast<FbxSkin *>(currMesh->GetDeformer(i, FbxDeformer::eSkin)); if (!currSkin) continue; uint numClusters = currSkin->GetClusterCount(); for (uint j = 0; j < numClusters; ++j) { FbxCluster *currCluster = currSkin->GetCluster(j); string currJointName = currCluster->GetLink()->GetName(); uint currJointIndex = FindJointIndexUsingName(currJointName); FbxAMatrix transformMatrix, transformLinkMatrix; FbxAMatrix geometryTransform = GetGeometryTransformation(inNode); //geometryTransform.SetIdentity(); currCluster->GetTransformMatrix(transformMatrix); //the xform of the mesh at binding time currCluster->GetTransformLinkMatrix(transformLinkMatrix); // the xform of the cluster(jnt) at binding time from joint space to world space mJoints[currJointIndex].mGlobalBindpose = transformLinkMatrix * transformMatrix * geometryTransform; mJoints[currJointIndex].mGlobalBindposeInverse = transformLinkMatrix.Inverse() * transformMatrix * geometryTransform; //JOINTS ARE ASSOCIATED WITH CONTROL POINTS uint numIndices = currCluster->GetControlPointIndicesCount(); for (uint k = 0; k < numIndices; ++k) { BlendingIndexWeightPair currBlendingIndexWeightPair; currBlendingIndexWeightPair.mBlendingIndex = currJointIndex; currBlendingIndexWeightPair.mBlendingWeight = currCluster->GetControlPointWeights()[k]; mControlPoints[currCluster->GetControlPointIndices()[k]]->mBlendingInfo.push_back(currBlendingIndexWeightPair); } } } } struct VertexBlendingInfo { uint mBlendingIndex; double mBlendingWeight; bool operator < (const VertexBlendingInfo &rhs) { return (mBlendingWeight > rhs.mBlendingWeight); } }; void FBXtoAbj::ProcessMesh(FbxNode *inNode) { ../ PNTIWVertex temp; temp.mPosition = currCtrlPoint->mPosition; temp.mUV = UV[j][0]; temp.mTangent = tangent[j]; temp.mNormal = normal[j]; for (uint k = 0; k < currCtrlPoint->mBlendingInfo.size(); ++k) { VertexBlendingInfo currBlendingInfo; currBlendingInfo.mBlendingWeight = currCtrlPoint->mBlendingInfo[k].mBlendingWeight; currBlendingInfo.mBlendingIndex = currCtrlPoint->mBlendingInfo[k].mBlendingIndex; temp.mVertexBlendingInfos.push_back(currBlendingInfo); } temp.SortBlendingInfoByWeight(); } struct PNTIWVertex { glm::vec3 mPosition, mNormal, mTangent; glm::vec2 mUV; vector<VertexBlendingInfo> mVertexBlendingInfos; void SortBlendingInfoByWeight() { sort(mVertexBlendingInfos.begin(), mVertexBlendingInfos.end()); } bool operator == (PNTIWVertex &rhs) { bool sameBlendingInfo = 1; //only compare the blending infos when there is any if (!(mVertexBlendingInfos.empty() && rhs.mVertexBlendingInfos.empty())) { //each vert should have 4 index-weight blending info pairs because games typically distribute weights to 4 joints for (uint i = 0; i < 4; ++i) { if (mVertexBlendingInfos[i].mBlendingIndex != rhs.mVertexBlendingInfos[i].mBlendingIndex || abs(mVertexBlendingInfos[i].mBlendingWeight - rhs.mVertexBlendingInfos[i].mBlendingWeight) > .001 ) { sameBlendingInfo = 0; break; } } } bool result0 = (mPosition == rhs.mPosition); bool result1 = (mNormal == rhs.mNormal); bool result2 = (mUV == rhs.mUV); bool result3 = (mTangent == rhs.mTangent); return result0 && result1 && result2 && result3 && sameBlendingInfo; } }; //GENERATE / WRITE OUT KEYFRAME POSES WITH YOUR FUNCTION 'READ' TO XML void FBXtoAbj::WriteAnimationToStream(ostream& inStream) { inStream << fixed << setprecision(3); inStream << "\t\t<animation name='" << mAnimationName << "' length='" << mAnimationLength << "' numJoints='" << mJoints.size() << "'>\n"; for (uint i = 0; i < mJoints.size(); ++i) { string usableParentName = (i == 0) ? "ROOT" : mJoints[mJoints[i].mParentIndex].mName; //inStream << "\t\t\t<track id='" << i << "' name='" << mJoints[i].mName << "'>\n"; inStream << "\t\t\t<track id='" << i << "' name='" << mJoints[i].mName << "' parent='" << usableParentName << "'>\n"; FbxTime::SetGlobalTimeMode(FbxTime::eFrames24); FbxAnimStack *currAnimStack = mScene->GetSrcObject<FbxAnimStack>(0); mScene->SetCurrentAnimationStack(currAnimStack); FbxString Name = currAnimStack->GetNameOnly(); FbxString TakeName = currAnimStack->GetName(); FbxTakeInfo* TakeInfo = mScene->GetTakeInfo(TakeName); FbxTimeSpan LocalTimeSpan = TakeInfo->mLocalTimeSpan; FbxTime Start = LocalTimeSpan.GetStart(); FbxTime Stop = LocalTimeSpan.GetStop(); FbxTime Duration = LocalTimeSpan.GetDuration(); FbxTime::EMode TimeMode = FbxTime::GetGlobalTimeMode(); FbxLongLong FrameCount = Duration.GetFrameCount(TimeMode); double FrameRate = FbxTime::GetFrameRate(TimeMode); for (FbxLongLong f = Start.GetFrameCount(TimeMode); f <= Stop.GetFrameCount(TimeMode); ++f) { FbxTime Time; Time.SetFrame(f, TimeMode); for (FbxNode *Node : allJointsOnFBX) { if (Node->GetName() == mJoints[i].mName) { inStream << "\t\t\t\t <frame num='" << f << "'>\n"; FbxAMatrix LocalTransform = Node->EvaluateGlobalTransform(Time); //is there a parent bone? If so, need to apply that parents global inverse transform to this node's transform if (FbxNode *Parent = Node->GetParent()) { FbxNodeAttribute *ParentAttribute = Parent->GetNodeAttribute(); if (ParentAttribute && ParentAttribute->GetAttributeType() == FbxNodeAttribute::eSkeleton) { FbxAMatrix GlobalParentTransform = Parent->EvaluateGlobalTransform(Time); LocalTransform = GlobalParentTransform.Inverse() * LocalTransform; } FbxVector4 Translation(LocalTransform.GetT()); inStream << "\t\t\t\t\t"; inStream << "<decompT>" << static_cast<float>(Translation.mData[0]) << "," << static_cast<float>(Translation.mData[1]) << "," << static_cast<float>(Translation.mData[2]) << "</decompT>\n"; FbxQuaternion Rotation(LocalTransform.GetQ()); inStream << "\t\t\t\t\t"; inStream << "<decompR>" << static_cast<float>(Rotation.mData[0]) << "," << static_cast<float>(Rotation.mData[1]) << "," << static_cast<float>(Rotation.mData[2]) << "," << static_cast<float>(Rotation.mData[3]) << "</decompR>\n"; } inStream << "\t\t\t\t </frame>\n"; } } } inStream << "\t\t\t </track>\n"; } inStream << "\t\t</animation>\n"; } //read from XML file //calculate skinning interpolation //apply pose to mesh ApplyPose(AnimationTime, myAbj.allAnims[0].trackData[0], glm::mat4(1.f)); // void Object::ApplyPose(float AnimationTime, TrackData track, const glm::mat4 &ParentTransform) { glm::quat RotationQ; CalcInterpolatedRotationGLM_solo(AnimationTime, track, RotationQ); glm::mat4 RotationM = glm::toMat4(RotationQ); glm::vec3 Translation; CalcInterpolatedPositionGLM_solo(AnimationTime, track, Translation); glm::mat4 TranslationM = glm::translate(glm::mat4(1.f), Translation); // // Combine the above transformations glm::mat4 NodeTransform = TranslationM * RotationM; for (int i = 0; i < myAbj.allBindSkeletons[0].skeletonCt; ++i) { if (myAbj.allBindSkeletons[0].skeletonData[i].name == track.name) { string gBonesName; gBonesName.append("gBones["); gBonesName.append(to_string(track.id)); gBonesName.append("]"); NameGBones2 xformNameCombo; xformNameCombo.animatedXform = ParentTransform * NodeTransform * myAbj.allBindSkeletons[0].skeletonData[i].inverseBindpose; //xformNameCombo.animatedXform = glm::mat4(1.f); xformNameCombo.name = gBonesName; xformNameCombo.nameMesh = name->val_s; myAbj.aiGbones2.push_back(xformNameCombo); } } for (auto &i : myAbj.allAnims[0].trackData) { if (i.parent == track.name) { //cout << "found parent / child for : " << track.name << " " << i.name << endl; ApplyPose(AnimationTime, i, ParentTransform * NodeTransform); } } }
    39. The idea isn't necessarily the problem, but it looks like we need to improve the way it's implemented. Alternatively and as a temporary fix, follow the Challenges blog and the Forum.
    40. romashka911

      Move view(camera) matrix

      I see world much difficult than it is...
    41. Koen

      Move view(camera) matrix

      You have to translate by the vector between pos and m_pos, so use m_pos - pos instead of just m_pos. (But in this case I'd simply call D3DXMatrixLookAtRH again with m_pos instead of pos.)
    42. Hodgman

      DirectX interfaces

      The idea of information hiding via interfaces is a very general concept that exists far beyond the scope of OOP. It's a common recurring concept in almost every different software paradigm. It's a key technique to manage complexity of software, by reducing the number of moving parts to be considered at any one time... Within OOP languages, there tends to be specific keywords that make creation of "interfaces" (the general idea) easy -- e.g. in C# the "interface" keyword, or in C++ the "class" and "virtual" keywords. Within OOD, there's a lot of thought given to how interfaces (the general idea, not the language-specific features) should be used in your software architecture. e.g. "smaller interfaces are better than big ones", or "Decouple modules by creating interfaces that sit in between them", or "If using polymorphic interfaces, implementations must always behave according to the base interface", or "Try to make interfaces that aren't going to need to be changed by future programmers, and then put the bits that will change over time inside the implementations of those interfaces"... You could use these bits of advice in any language -- even ones that don't have a "class" or an "interface" keyword. e.g. in C libraries, it's common to write something that embodies the idea of an interface by using function pointers. They use it for polymorphism too -- e.g. ID3D11Resource is a polymorphic interface (ID3D11Buffer is a ID3D11Resource). When you call CreateTexture2D/etc, internally, it might have some internal class that's called something like CTex2D, which implements ID3D11Texture2D, for all we know... but that's hidden from us. All we know is that it creates some kind of object that implements the ID3D11Texture2D interface, and we can use this interface to talk to the object. Yep. For an example of the first concept -- non polymorphic interfaces, look at PIMPL (aka Opaque pointers).
    43. D3DXVECTOR3 m_pos; D3DXVECTOR3 pos; D3DXVECTOR3 lookAt; D3DXVECTOR3 up; D3DXMATRIX m_cameraMatrix; D3DXMATRIX translate, result; D3DXMatrixLookAtRH(&m_cameraMatrix, &pos, &lookAt, &up); D3DXMatrixIdentity(&translate); D3DXMatrixTranslation(&translate, m_pos.x, m_pos.y, m_pos.z); result = m_cameraMatrix * translate; return result; I want to move camera to m_pos position, as i do it with world matrix, but it seems it doesn't work, any ideas?
    44. Touchscreens do simply suck for a lot of game input, it is odd where we've ended up in a situation where having awful input controls is standard on phones, where there were even portable devices in 1980 that had better input... https://en.wikipedia.org/wiki/Game_%26_Watch It is one of those odd things, I don't know whether it is because google haven't encouraged game controllers, or that the market hasn't been buying devices with buttons. You could say that dedicated gamepads are the ideal solution, but then loads of games don't support gamepads, probably simply because they aren't standard, a chicken and the egg situation (and google makes it overly difficult to support them, they aren't even in the emulator for instance). Another 'odd' decision is that android APIs don't seem to support right clicking with mice. Everything is touchscreen orientated, your mouse is a finger. Which makes it a challenge to make any kind of 'desktop like' app on android. I've love to know the (presumably commercial) reasoning behind actively degrading experience with mouse. One cynical reason is that google presumably make a lot of their money by people mistakenly clicking adverts by mistake with touchscreens, and this is less likely with mouse.
    45. For this case you don't need the distance and angle, only the direction. As @Lactose sad you can calculate it direction = enemy - player (direction toward enemy) and normalize it. Since enemy moves at some speed, by doing this calculation you will probably miss it. If you want to hit it every time you will have to shoot in front of the enemy which complicates a bit the calculation.
    46. Migrating all my code to another engine would be close to impossible for this project unfortunately... What pixel sizes should I make the window to avoid the problem? Im unsure on how to progress. Just setting it to much larger doesnt help (which seems to me would mean there is enough pixels to not need to press the screen together, thus avoiding it skipping lines? But doesnt work either).
    47. Could you please explain this a bit further as I think I have not grasped it fully yet? So by this you are saying we would use an interface for two possible scenarios. In one case to hide the implementation and to provide only the "public" interface and in other to use it for polymorphism. I always kinda connected the two concepts. For DirectX part I guess they use the interfaces only for the first scenario, if I understood you correctly? Where in the second scenario we would create a class interface to be able to use a base pointer for inherited classes, for polymorphism.
    48. On my phone I noticed holding one point, then touching another while still holding, will make it forget the first, though it might depend on the app. Maybe you are experiencing something similar and could work around it?
    49. vinterberg

      Silly Input Layout Problem

      You don't get access to them by a float4x4 in your shader, you retrieve your ins. matrix by four "float4 INSTANCEx" and then you assemble those into a matrix again Something like this: struct VS_INPUT { ..... float4 World0 : MWORLD0; float4 World1 : MWORLD1; float4 World2 : MWORLD2; float4 World3 : MWORLD3; }; cbuffer Buffer1 : register(b0) { float4x4 MatrixWorld; ..... }; VS_OUTPUT main(VS_INPUT Input) { VS_OUTPUT Output; float4x4 mworld = float4x4(Input.World0, Input.World1, Input.World2, Input.World3); mworld = mul(MatrixWorld, mworld); .....
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!