Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


Hodgman

Member Since 14 Feb 2007
Online Last Active Today, 04:52 AM

#5044446 Game/Controller Idea (I don't think its been said before)

Posted by Hodgman on 18 March 2013 - 08:38 PM

I'm pretty sure hundreds of people have had this same idea, but it's pretty darn costly to implement biggrin.png

 

VR and motion capture keep getting cheaper though, so maybe one day soon it would be feasible. Like you say though, you'd also need to rent a huge space to host the game, which would have to be close to a metropolitan area in order to get customers, which is another huge expense. Then on top of that, there's the actual game development part!

 

I had the same idea when I was a teenager, but as an FPS instead of a melee game -- other players could be in the same arena as you, and the VR goggles could draw 3D models for them using their exact poses, so they line up with reality. You could then play with a laser-tag gun, which is registering shots against their real-world body.

Having walls and obstacles in the arena would be fine, as long as your motion capture and VR tech is accurate enough that it can draw virtual walls in the exact same places as the real walls are.

 

To build this, you would need an existing, talented games studio that can build the software, and you would need a bunch of hardware engineers to concoct your VR environment for you. Each of those teams would then need millions of dollars in each of their budgets... And then you'd need to attract enough players, and charge a high enough price to make back your money.

At the moment, it's probably cheaper to scrap the whole VR part and just use reality, like Patient 0 did: 




#5044199 multiple threads, OpenGL, and worker threads...

Posted by Hodgman on 18 March 2013 - 07:12 AM

@cr88192, with all your mutexes about the place, how much of a performance increase have you measured over your original single-threaded GL code?




#5044197 3ds max plugin which allows me to upload to a git repository

Posted by Hodgman on 18 March 2013 - 07:01 AM

You don't neeed cool.png   a plugin for 3DS max to use Git -- a plugin would just make it easier. You can use the git command line, or the TortoiseGit GUI from windows explorer to commit your changes to the repository. 

 

Personally, I prefer to use Git from Windows explorer and/or the command line, rather than having it integrated into my code editor, so that my interactions with the repository are more explicit.

 

 

Echoing what Simon said though, the reason that it's hard to find a 3ds integration with Git, is because Git is actually a really poor solution for game art files. It's fantastic for text source code (really fantastic), as it's really smart when it comes to merging different versions of text files together... but none of those features works with 3DS Max files, so they're useless to you.

If you ever do end up in a situation where two people have edited the same art file, then Git will be less than useful, as it can't even prevent that situation from occurring  and can only give you the option of choosing which person's work gets deleted.

 

Also, a large part of Git's power comes from the fact that it stores the entire history of all files on every user's PC. With text files, this is generally only a few megabytes, which is no problem at all... but with art files, this could be gigabytes to terabytes, depending on the size of your project, and how many changes to each file you have to make.

 

I would talk to your programmer and check that they're really sure that they want to use Git to store game art...




#5044165 C++ Concurrency Library

Posted by Hodgman on 18 March 2013 - 04:23 AM

TBB seems to be a very common choice.
 
[Provided you've had practice with memory re-ordering issues and esoteric C language rules, then] Writing your own isn't that hard.
I like to use a SPMD style of programming quite a bit these days. What I do is:

  • Create a bunch of threads -- typically 1 per core.
  • Assign each thread a number from 0 to numThreads-1. Store this number using TLS so it can be retrieved like a global variable at any time.
  • Write a pure function that can distrubute a range of a problem between threads, e.g.
inline void DistributeTask( uint workerIndex, uint numWorkers, uint items, uint &begin, uint& end )
{
	uint perWorker = items / numWorkers;
	begin = perWorker * workerIndex;
	end = (workerIndex==numWorkers-1)
		? items                      //ensure last thread covers whole range
		: begin + perWorker;
	begin = perWorker ? begin : min(workerIndex, (u32)items);   //special case,
	end   = perWorker ? end   : min(workerIndex+1, (u32)items); //less items than workers
}
  • Run the same main loop on all threads. Upon reaching a processing loop, use this function to determine the range of the loop that should be processed.
  • If the results of one loop become the inputs to another loop, then make sure you synchronize the workers appropriately. e.g. increment an atomic counter as you leave the first loop, and before the second loop, wait until counter == numThreads.
  • In my implementation, I combine this SPMD model with a job-based model, where while any thread is busy-waiting on a condition such as the above, they continually try to pop 'job packets' from a shared queue for processing, to make good use of this waiting time.



#5044134 Loaded scene form COLLADA is inverted in DirectX

Posted by Hodgman on 17 March 2013 - 11:44 PM

In 3DS, is Y your "up" axis, or is "Z" up?

You probably shouldn't be multiplying individual components of the matrix by -1, but should be scaling an entire axis of the matrix by (-1,-1,-1,-1).

 

DirectX uses whatever handedness you choose to use. You can use it with left handed or right handed matrices.

 

Transposing a matrix does not convert between handedness; it converts between column-major storage and row-major storage. D3D's HLSL and GL's GLSL both operate on column-major storage by default, though fixed-function D3D, and the D3DX helpers often use row-major storage.

 

It also converts matrices that are designed to operate on row-vectors to ones that will work on column-vectors, and vice versa.

Whether you're using row-vectors or column-vectors depends on whether you write vector * matrix, or matrix * vector in your shader code.




#5044125 Light Prepass output color differences

Posted by Hodgman on 17 March 2013 - 10:16 PM

To get the same results with deferred-lighting and deferred-shading, your deferred-lighting "lighting accumulation buffer" has to accumulate diffuse and specular light seperately, so that later you can multiply them with the diffuse surface colour and specular surface colour, respectively. As long as you do that, they'll be the same.

 

The reason that many deferred-lighting systems are different, is because the above setup requires 6 channels in the accumulation buffer. As an optimization, you can instead just accumulate 4 channels -- the diffuse light RGB, and the specular light without any colour information. Later on, you can either treat all specular light as monochromatic, or you can 'guess' it's colour by looking at the accumulated diffuse colour.

[edit]

So if an object is affected by multiple lights, it will only apply the surface color to the output once vs the deferred shading approach which multiplies in the surface color for each light

Deferred shading does:

light0 * material + light1 * material + light2 * material

Deferred lighting does

(light0 + light1 + light2) * material

 

Both of these are exactly equivalent.




#5043894 How to build mesh position Matrix from COLLADA file?

Posted by Hodgman on 17 March 2013 - 01:03 AM

You just need to be able to parse the translate/rotate elements and build from them translation matrices and axis-angle rotation matrices, then multiply them all together in order. My parsing code for collada node transforms looks like:
            Matrix4 matrix = Matrix4.identity.Clone();
            XmlNodeList transforms = node.SelectNodes("c:rotate | c:translate | c:scale | c:skew | c:matrix | c:lookat", nsm);
            foreach (XmlNode transform in transforms)
            {
                string type = transform.Name;
                switch (type)
                {
                    case "rotate":
                        Vector4 rotation = Vector4.Parse(transform.InnerText);
                        matrix.MultiplyRotation(rotation);
                        break;
                    case "translate":
                        Vector4 translation = Vector4.Parse(transform.InnerText);
                        matrix.MultiplyTranslation(translation);
                        break;
                    case "scale":
                        Vector4 scaling = Vector4.Parse(transform.InnerText);
                        matrix.MultiplyScaling(scaling);
                        break;
                    case "matrix":
                        Matrix4 transformMatrix = Matrix4.ParseRowMajor(transform.InnerText);
                        matrix.MultiplyInPlace(transformMatrix);
                        break;
                    default:
                    case "skew":
                    case "lookat":
                        throw new ApplicationException(String.Format("The {0} transform type isn't implemented!", type));
                }
            }
            newNode.local = matrix;
            newNode.global = Matrix4.Multiply(global, newNode.local);



#5043020 Magical if-statement

Posted by Hodgman on 14 March 2013 - 06:18 AM

Couldn't foo and bar also be declared volotile?
 

Yeah, without volatile foo==foo compiles to pseudo-asm like:

int reg0 = read(&foo);
bool reg1 = compare( reg0, reg0 );

But with volatile, it would compile to something like:

int reg0 = read(&foo);
int reg1 = read(&foo);
bool reg2 = compare( reg0, reg1 );

So if the memory at &foo is constantly changing, the comparison could possibly be false.

However, that kind of code should probably never be written. Generally if your code contains volatile, then you have a bug tongue.png 

About the only place it's valid to see that keyword used, would be inside the implementation of std::atomic.




#5042968 Task and Timeline management tools?

Posted by Hodgman on 13 March 2013 - 11:24 PM

On my current project, we're using Smart Sheet, which is basically like a browser-based alternative to Excel + Project. The project manager has a paid account, and everyone else just has trial accounts, which let them work inside the manager's files.

 

You can do some decent customization in their spreadsheets, but for some complex reports we export their data and plug it into an Excel book designed to read/analyze it.




#5042720 How to re-orthogonalise vectors

Posted by Hodgman on 13 March 2013 - 09:08 AM

If they were ok before you rotated them, then they should be ok after you rotate them, except for really small numerical errors. These errors are only a problem if you keep applying rotations to a matrix frame after frame, instead of rebuilding it from scratch each time, so most of the time this isn't required.

 

If it is required, you can use the cross product to find a vector that's perpendicular to two others. Pick 2 of your vectors and cross them to regenerate the 3rd. Then use the 1st and the 3rd to regenerate the 2nd. Each time you regenerate one, you can check it's dot product with the original version; it should be very close to 1.0 or -1.0. If it's negative, then flip the regenerated vector so it matches the direction/handedness of the original.




#5042584 Confused on Big Oh

Posted by Hodgman on 12 March 2013 - 10:26 PM

This is completely made-up and a very forced example, but imagine two different algorithms with loops like below, where they both call some inner function (DoAlgorithmInner1/DoAlgorithmInner2) that we assume are both of equal cost.
 
for( i=0; i < n; ++i )
  for( j=0; j < 100; ++j )
    DoAlgorithmInner1( i, j )
 
 
for( i=0; i < n; ++i )
  for( j=0; j < n; ++j )
    DoAlgorithmInner2( i, j );
The first is O(n*100), which is O(n*constant), which is just O(n).
The second is O(n2).
 
Say that n is only 10 -- the first one calls the inner function 10*100 times, the second calls it 10*10 times.
Say that n is 10000 -- the first one calls the inner function 10000*100 times, the second calls it 10000*10000 times.
 
So for any case where n is less than 100, the n^2 algorithm actually does less work.
 
 
For a real world example -- try implementing a comparison sort, like quicksort, which is O(n log n) and also a radix sort, which is O(n).
The constants, which are removed from the big-O analysis are actually very high with the radix sort, which makes it behave like the above example.
e.g. n*1000 might be more expensive than n*n*10.


#5042166 String handling in C

Posted by Hodgman on 11 March 2013 - 08:23 PM

"String handling in C" is a coding horror all on it's own - no further comment is necessary.

I'd say "string manipulation in C" is a coding horror, but consuming read-only strings in C is refreshingly lacking in unnecessary abstraction.

 

In my C++ engine, I don't use any string classes. Instead I choose to use const char* for any strings, simply because I don't do any string manipulation at all, so the simplest solution works fine wink.png

[edit] to clarify, this also means not using any of the C standard library functions that work on strings [/edit]




#5041806 Copyright Compliance - Coding Authentication

Posted by Hodgman on 11 March 2013 - 05:47 AM

In literature academia there are a lot of tools in this area -- to take a suspicious work and have it automatically compared against as much other work as possible for signs of plagiarism.

I don't know of anything like this for code though.

 

In an professional jobs, it's never been an issue. It's up to each team member to not steal code, and their supervisors to not let people circumvent this rule. If you want to use someone else's code, the license terms would be sent upwards to management/legal for approval.

 

I do imagine this could be a problem if you were outsourcing programming work to cheap external contractors though... You should make sure that your contracts with these people are watertight enough that if someone sues you for copyright infringement because these contractors plagiarized work, you can then in turn sue the contractor (or better, have the original victim sue the contractor).

 

However, if you're using low-quality, untrustworthy contractors where this situation is likely to occur, you probably have bigger issues... like your product not being shippable due to crippling bugs and missing features tongue.png wink.png




#5041723 Whats the shader data a Material class holds?

Posted by Hodgman on 10 March 2013 - 11:53 PM

In my renderer, I don't even have a material class. A material is just a bunch of data (cbuffers, textures, shaders) and a bunch of commands that bind that data to the pipeline (PSSetConstantBuffers, etc).
I have classes for resources like cbuffers/textures/etc, and I also have a class called StateGroup, which can hold commands to set rendering states (which includes binding resources).
I can use StateGroup to represent a material, as well as other things, e.g.

StateGroup objectStates;   // binds cbuffer with world matrix
StateGroup materialStates; // binds shader, sets blend mode, binds textures, binds material cbuffer
StateGroup lightingStates; // binds cbuffer with light positions
StateGroup* states[3] = { &objectStates, &materialStates, &lightingStates };
Draw( mesh, states, 3 );

This shader resources a material holds, is it a single permutation of a shader, or a material can access all of the permutation of the shader it references?

I always reference a particular "technique", which internally may have many different permutations that can be chosen by the renderer right before each draw call.

Say I have a cube with a material, if my cube changes environment, so that the number of lights change, do I need to just use another permutation on the material(material holds a permutation info), the shader itself updates its permuation info(so all material with this shader now will use the new permutation),  do I need to change the cube material (another material with the right permutation)? or do I need to update the shader on the material(so the material got a new shader)?

If the lighting environment has changed, I wouldn't make any changes to the material or the shader. The material references a particular shader, and that shader contains techniques for different lighting enironments.
When drawing the cube, with this material/shader/lighting environment, the renderer can select the appropriate premutation at the last moment, when it has all this information available to it.

Also, when is that a material finds out what cbuffers slots to use? This is shader stuff, say you know what cbuffers a shader use cause youre using reflection at asset loading time, materials comes from models right? Not from HLSL files..I fail to see when things get linked up (shader permutations compilation, models loading, environment lighting info being updated to shader cbuffers..)

I do all of this in the tools, during "data compilation" time.
First I compile the shaders, which tells me their cbuffer layouts (which variables are in which cbuffer structures, and which slots/stagse each structure should be bound to).
Then I parse the artists material descriptions (which for me, are in the COLLADA files), and use the above structure information to create byte-arrays of cbuffer data.
Then I create binding commands, to bind these structures to the appropriate slots/stages (e.g. bind cbuffer structure #1 to pixel shader slot #3).
Then I save these cbuffers and binding commands into a "material file", which contains links to other resource files (textures, shaders, etc) and contains StateGroups and cbuffers to be used as "materials".




#5041141 GLSL #pragma optimize(off) has no effect.

Posted by Hodgman on 09 March 2013 - 05:32 AM

As above, make your C++ code more robust tongue.png

 

I've been in this situation before though, where a non-robust game engine would crash due to shader changes, and the workaround that I came up with was to ensure that any uniforms that I "removed" temporarily would still contribute to the result somewhat.

e.g. finalColor.b += clamp(my_uniform,0,1)*0.001;






PARTNERS