views:

129

answers:

5

I have Camera class, which handles camera behavior. Among it's fields is a reference to the target's Cube class (Cube is just one of the object, but I won't mention others to keep it simple). In order to calculate the View matrix, I need the camera's position and target's position, so I can explain to my program that: "the camera is placed here, and from here it's looking at this cube". Should the cube happen to move around, so too would the camera's point of view change automatically.

So far, everything is good: there is a Camera class which depends on the Cube class, and there's the Cube class which depends on nothing (in this example).

I get to a problem when I need to draw a cube, or anything else -- in order to draw something, among the required values it the View matrix of the Camera; that's the one that I've just calculated in the first paragraph. In essence, this means when I get to the point to draw things on-screen, the Cube class becomes dependant on the Camera class as well, and they're now dependant on each other. That would mean that I either:

  1. need to make the View matrix field of the Camera class static, so I can access it directly from the Cube class.
  2. need to make a method (eg. SetView) in Cube class, which I can then invoke from the Camera class (since I already have it's reference there).
  3. need to keep a View matrix in outside scope.
  4. need to make a bidirectional dependency.

But, I don't like either of these:

  1. there are more cameras which handle multiple views (currently there are 3 of them on-screen) and there may be more (or less).
  2. this makes the code slightly (sometimes, maybe, very) unreadable -- for example when I'm drawing the cube, it's not quite clear where the View matrix came from, you just kinda use it and don't look back.
  3. I would access the outside scope from the camera class, or the outside scope would access the camera, and I wouldn't like this because the outside scope is only used to handle the execution mechanics.
  4. I like to keep my reference fields "readonly" as it's currently everywhere in this system -- the references are set in the constructor, and only used to get data from referenced classes.

And, if I haven't made it clear, let me just repeat that there are multiple Camera objects, and multiple Cube objects; whereas any Camera may or may not depend on any Cube, but usually there is at least one Camera dependent on a Cube.

Any suggestions would be appreciated :)

+1  A: 

Assuming your DrawWorld() routine already knows about Cubes and Cameras, I would pass the view matrix to the Cube's Draw() method:

foreach (Cube cube in cubes) {
    cube.Draw(..., mainCamera.ViewMatrix, ...);
}

That way Cube only "depends" on Matrix and not on Camera. Then again, maybe that violates rule 3 above. I can't do much better without seeing some of your code, though.

Frédéric Hamidi
This is what I have been using from the start -- that was when I had only one camera. I got to this problem when I introduced multiple cameras (think of this as a rear-view mirror in racing games). So it became tricky to handle it this way :)
avance70
+1  A: 

Two alternate options:

  1. Create base classes for the Camera and Cube that don't link to each other but still contain most of the logic you want to use. Then you can add a BaseCamera reference to Cube, to which you would assign a Camera object, not a BaseCamera object. (And a Camera with a BaseCube field.) This is the power of polymorphism.
  2. Define an ICamera and ICube interface. The Camera class would then use an ICube field to link to the cube and vice versa.

Both solutions will require you to take care when creating and freeing new camera and cube objects, though. My personal preference would be the use of interfaces. Do keep in mind that the ICube and ICamera interfaces should not link to each others. Their related classes will link to the other interface, but not the interfaces.

Workshop Alex
Thanks, it's a bit tricky to work on the object hierarchy (let's just say it's not in *my* domain to go into the matter), but you are right if you think there's not much of a object hierarchy in the solution. This is something I would have to discuss with the other people involved, thoigh I think we got to a point where a better hierarchy could be established, since right now we just have a few interfaces.
avance70
A: 

When doing XNA i hav had a sililar problem.

I soolved it by adding an interface to the camera into my Draw method interface.

Its not pretty and a camera gets passed around everywhere, but it worked well.

The real thing to get is that your update and draw loops are seperate.

when drawing you ahve a list of objects to draw and your draw routine has some camera class passed to it.

the alterative to to code in a way to your classes to produce a list of all their objects that require rendering. Pass this to the renderer which contains the camera.

The point being that a list of cameras is maintained, along with a list of drawable objects despite all of these objects also belonging to a logical pattern describing game state.

Read about inversion of control. It is all I am describing really.

John Nicholas
+1  A: 

I made each object class responsible for it's own rendering.

In your case, you would have to pass each rendering method the graphics instance and the viewpoint relative to the object.

A drawing class would have access to the instances of all the object classes, and call the drawing method of each object in whatever order makes sense. Your object classes would probably have to have another method that determines the distance from the viewpoint, so that you can call the drawing methods in a furthest to closest order.

Gilbert Le Blanc
I also made each class responsible for it's own rendering :) thanks for reminding me of the distance issues, I think I didn't transfer that part of the code into the new solution.
avance70
+1  A: 

If your Cube must know how to render itself with respect to a Camera (and therefore must know about the Camera), then it probably doesn't make sense for the Camera to know how to align itself to a Cube. The alignment behavior that's currently in Camera probably belongs in a higher-level class like a CameraDirector that knows about both Cubes and Cameras. This improves class cohesion, as it splits off some of the responsibilities of Camera into a different, tightly-focused CameraDirector class. This lets the Camera focus on its core job and makes it easier to understand and maintain.

Dan Bryant
Thanks for noticing... I'll have to do a few test before accepting this reply, but you now gave me the idea on what I should do -- make something like `Camera.Attach(IAttachable attachTo)` method in the Camera class, where I can order the camera to follow that object... and in that case, I will invert the current dependancy.
avance70
Yeah, I recoded this part and it seems to me like the best solution so far.
avance70