So let's add a virtual cockpit.
Virtual cockpits can dramatically increase the immersion factor of a simulation and a custom cockpit and/or 2d panel is an absolute ust for any vessel that with advanced subsystem modeling. The historical LM had over 160 switches and displays spread across 14 panels and we've only got so many keyboard commands to work with. :lol:
PART 12: Adding a virtual cockpit.
First thing first, we need to declare a mesh for our VC. Add a new mesh handle and index to your class interface...
... and load it in your constructor.
Remember to make sure you've got the correct filepath.
Once you have the mesh loaded we need to add it to our vessel, let's go to clbkSetClassCaps and do so.
NOTE: the VC and Ascent stage meshes were designed with matching coordinate frames so we use "LM_ASC_OFFSET" for both.
Compile and test, Outwardly there is no change, but if we zoom way in...
We will see that the cockpit mesh is there, it's just covered. This is because orbiter ordinarily only renders a vessel's meshes while in an exterior view. What we need to do is tell orbiter that this is a VC mesh. In clbkSetClassCaps add the following lines.
The cockpit mesh will now only be rendered in cockpit views. Also, because I want the legs of the descent stage to be visible through the cockpit windows I've set the descent stage mesh so that it will always rendered regardless of view mode.
If you compile and test again you will see that the cockpit mesh has been vanished.
Now we need to enable the virtual cockpit mode in orbiter. To do this we need to overload yet more callback functions. Back in our class interface declare the following...
the purposes of these 3 functions should be apparent from thier names, if not read the comment along side
Now add them to our source code as stubs
NOTE: clbkLoadVC returns "true" because we want the VC mode to be enabled, clbkVCMouseEvent and clbkVCRedrawEvent return false because we have not given them anything to do yet.
Compile and test...
We're making progress :thumbup: but the current camera position is a little awkward. lets define a new one or rather new ones.
You see, orbiter allows you define multiple VC positions and then cycle between them. In the DG you can cycle between the Pilot's position and the various passengers, in the stock Atlantis you can cycle between the pilot, co-pilot, and cargo bay views.
These views are differentiated by the "id" variable passed to clbkLoadVC by Orbiter's core.
For the LM I have 3 positions in mind as well, The Comander's view (Left window), LMP's view (Right window), and docking view (Looking up through rendevous window).
to declare our three views we will need to add a "switch (id)" statement to clbkLoadVC.
Then for each case we need to declare 4 things...
The position of the of the camera, it's default direction, it's rotation range, and it's neighbours. The first three values should be self explanitory, the last one is used to select a view using the arrow keys. Pressing ctrl + the Left, Right, Up, or Down key in that view will select the listed adjacent view.
So lets get on with it...
Compile and test...
:huh: Seems we forgot to account for the offset position of our mesh.
Now thanks to "shiftCG" our camera will be in the correct position if we jettison the Descent stage but seeing as lying on the floor for half the flight isn't really desireable lets add a variable to compensate for this. Go to the top of "clbkLoadVC" and add the following...
then add "ofs" to each of your camera positions
Let's try that again... Much better yes? :thumbup:
Check out the other views as well
^ Pilot's view
^ Docking view
This concludes part 12.
Next we will be talking about how to add a sub-class to your vessel, and registering VC active areas.
Virtual cockpits can dramatically increase the immersion factor of a simulation and a custom cockpit and/or 2d panel is an absolute ust for any vessel that with advanced subsystem modeling. The historical LM had over 160 switches and displays spread across 14 panels and we've only got so many keyboard commands to work with. :lol:
PART 12: Adding a virtual cockpit.
First thing first, we need to declare a mesh for our VC. Add a new mesh handle and index to your class interface...
Code:
// Meshes
MESHHANDLE mh_ascent,[COLOR="red"] mh_cockpit,[/COLOR] mh_descent; // Mesh handles
UINT mesh_Descent; // Descent stage mesh index
UINT mesh_Ascent; // Ascent stage mesh index
[COLOR="Red"]UINT mesh_Cockpit; // Virtual cockpit mesh index[/COLOR]
... and load it in your constructor.
Code:
// Load meshes
mh_descent = oapiLoadMeshGlobal("UMMU_Apollo/LEM_DescentStage");
mh_ascent = oapiLoadMeshGlobal("UMMU_Apollo/LEM_AscentStage");
[COLOR="red"] mh_cockpit = oapiLoadMeshGlobal("UMMU_Apollo/LEM_VC");[/COLOR]
Remember to make sure you've got the correct filepath.
Once you have the mesh loaded we need to add it to our vessel, let's go to clbkSetClassCaps and do so.
Code:
// Associate meshes for the visual
mesh_Descent = AddMesh (mh_descent, &LM_DES_OFFSET); // Descent stage mesh
mesh_Ascent = AddMesh (mh_ascent, &LM_ASC_OFFSET); // Ascent stage mesh
[COLOR="red"]mesh_Cockpit = AddMesh (mh_cockpit, &LM_ASC_OFFSET); // Virtual cockpit mesh[/COLOR]
Compile and test, Outwardly there is no change, but if we zoom way in...
We will see that the cockpit mesh is there, it's just covered. This is because orbiter ordinarily only renders a vessel's meshes while in an exterior view. What we need to do is tell orbiter that this is a VC mesh. In clbkSetClassCaps add the following lines.
Code:
// Associate meshes for the visual
mesh_Descent = AddMesh (mh_descent, &LM_DES_OFFSET); // Descent stage mesh
mesh_Ascent = AddMesh (mh_ascent, &LM_ASC_OFFSET); // Ascent stage mesh
mesh_Cockpit = AddMesh (mh_cockpit, &LM_ASC_OFFSET); // Virtual cockpit mesh
[COLOR="red"] SetMeshVisibilityMode (mesh_Descent, MESHVIS_ALWAYS); // Set desent stage mesh to be always visible, By default a vessel's own meshes are only visible when in an external view. I want the the descent stage's legs to be visible from the cockpit.
SetMeshVisibilityMode (mesh_Cockpit, MESHVIS_VC); // Set cockpit mesh to be visible in virtual cockpit view [/COLOR]
The cockpit mesh will now only be rendered in cockpit views. Also, because I want the legs of the descent stage to be visible through the cockpit windows I've set the descent stage mesh so that it will always rendered regardless of view mode.
If you compile and test again you will see that the cockpit mesh has been vanished.
Now we need to enable the virtual cockpit mode in orbiter. To do this we need to overload yet more callback functions. Back in our class interface declare the following...
Code:
void clbkPostStep (double simt, double simdt, double mjd); // Manage Animations and Post-Step processes
int clbkConsumeBufferedKey (DWORD key, bool down, char *kstate); // Process keyboard inputs
[COLOR="red"] bool clbkLoadVC (int id); // Load virtual cockpit mode
bool clbkVCMouseEvent (int id, int event, VECTOR3 &p); // Respond to virtual cockpit mouse events
bool clbkVCRedrawEvent (int id, int event, SURFHANDLE surf); // Respond to virtual cockpit area redraw requests[/COLOR]
the purposes of these 3 functions should be apparent from thier names, if not read the comment along side
Now add them to our source code as stubs
Code:
// --------------------------------------------------------------
// Load virtual cockpit mode
// --------------------------------------------------------------
bool LM::clbkLoadVC (int id)
{
return true;
} // End "LM::clbkLoadVC"
// --------------------------------------------------------------
// Respond to virtual cockpit mouse events
// --------------------------------------------------------------
bool LM::clbkVCMouseEvent (int id, int event, VECTOR3 &p)
{
return false;
} // End "LM::clbkLoadVC"
// --------------------------------------------------------------
// Respond to virtual cockpit area redraw requests
// --------------------------------------------------------------
bool LM::clbkVCRedrawEvent (int id, int event, SURFHANDLE surf)
{
return false;
} // End "LM::clbkVCRedrawEvent"
NOTE: clbkLoadVC returns "true" because we want the VC mode to be enabled, clbkVCMouseEvent and clbkVCRedrawEvent return false because we have not given them anything to do yet.
Compile and test...
We're making progress :thumbup: but the current camera position is a little awkward. lets define a new one or rather new ones.
You see, orbiter allows you define multiple VC positions and then cycle between them. In the DG you can cycle between the Pilot's position and the various passengers, in the stock Atlantis you can cycle between the pilot, co-pilot, and cargo bay views.
These views are differentiated by the "id" variable passed to clbkLoadVC by Orbiter's core.
For the LM I have 3 positions in mind as well, The Comander's view (Left window), LMP's view (Right window), and docking view (Looking up through rendevous window).
to declare our three views we will need to add a "switch (id)" statement to clbkLoadVC.
Code:
bool LM::clbkLoadVC (int id)
{
[COLOR="red"] // Register Camera (view) properties
switch (id)
{
case 0: // Commander's position
break;
case 1: // Pilot's position
break;
case 2: // Commander's position (looking up through COAS Reticle)
break;
} // end "switch (id)"[/COLOR]
return true;
} // End "LM::clbkLoadVC"
Then for each case we need to declare 4 things...
The position of the of the camera, it's default direction, it's rotation range, and it's neighbours. The first three values should be self explanitory, the last one is used to select a view using the arrow keys. Pressing ctrl + the Left, Right, Up, or Down key in that view will select the listed adjacent view.
So lets get on with it...
Code:
// Register Camera (view) properties
switch (id)
{
case 0: // Commander's position
[COLOR="red"] SetCameraOffset (_V(-0.57, 0.68, 1.12)); // Set camera position (x,y,z)
SetCameraDefaultDirection (_V( 0, 0, 1)); // Set camera direction (x,y,z)
SetCameraRotationRange (RAD*120, RAD*120, RAD*60, RAD*60); // Set camera range of motion (Left, Right, Up, Down)
oapiVCSetNeighbours (-1, 1, 2,-1); // Set adjacent cameras (Left, Right, Top, Bottom)
break;[/COLOR]
case 1: // Pilot's position
[COLOR="red"] SetCameraOffset (_V( 0.57, 0.68, 1.12)); // Set camera position (x,y,z)
SetCameraDefaultDirection (_V( 0, 0, 1)); // Set camera direction (x,y,z)
SetCameraRotationRange (RAD*120, RAD*120, RAD*60, RAD*60); // Set camera range of motion (Left, Right, Up, Down)
oapiVCSetNeighbours ( 0,-1,-1,-1); // Set adjacent cameras (Left, Right, Top, Bottom)[/COLOR]
break;
case 2: // Commander's position (looking up through COAS Reticle)
[COLOR="red"] SetCameraOffset (_V(-0.59, 0.68, 1.12)); // Set camera position (x,y,z)
SetCameraDefaultDirection (_V( 0, 1, 0)); // Set camera direction (x,y,z)
SetCameraRotationRange (RAD*15, RAD*15, RAD*15, RAD*15); // Set camera range of motion (Left, Right, Up, Down)
oapiVCSetNeighbours (-1, 1,-1, 0); // Set adjacent cameras (Left, Right, Top, Bottom)[/COLOR]
break;
} // end "switch (id)"
Compile and test...
:huh: Seems we forgot to account for the offset position of our mesh.
Now thanks to "shiftCG" our camera will be in the correct position if we jettison the Descent stage but seeing as lying on the floor for half the flight isn't really desireable lets add a variable to compensate for this. Go to the top of "clbkLoadVC" and add the following...
Code:
bool LM::clbkLoadVC (int id)
{
[COLOR="red"] // Check CG offset
VECTOR3 ofs;
if (CGshifted == false) ofs = LM_ASC_OFFSET;
else ofs = _V( 0, 0, 0);[/COLOR]
// Register Camera (view) properties
switch (id)
{
then add "ofs" to each of your camera positions
Code:
case 0: // Commander's position
SetCameraOffset (_V(-0.57, 0.68, 1.12)[COLOR="red"] + ofs[/COLOR]); // Set camera position (x,y,z)
SetCameraDefaultDirection (_V( 0, 0, 1)); // Set camera direction (x,y,z)
SetCameraRotationRange (RAD*120, RAD*120, RAD*60, RAD*60); // Set camera range of motion (Left, Right, Up, Down)
oapiVCSetNeighbours (-1, 1, 2,-1); // Set adjacent cameras (Left, Right, Top, Bottom)
break;
Let's try that again... Much better yes? :thumbup:
Check out the other views as well
^ Pilot's view
^ Docking view
This concludes part 12.
Next we will be talking about how to add a sub-class to your vessel, and registering VC active areas.