- Joined
- Aug 13, 2008
- Messages
- 185
- Reaction score
- 0
- Points
- 31
- Location
- Chicago
- Website
- www.frogisis.com
-----------------------------------------
Click here to download the new version.
-----------------------------------------
Turns out I had the old Blender files on my backup hard drive after all, so I thought I'd give it another go, since I hate the fact that it seemed like such a shoddy add-on, what with the z-fighting making it flicker in and out of existence like a spastic hologram.
I've essentially fixed that problem by deleting some faces on the model, and now it's entirely gone, except for at a few angles in the "cockpit" view, which I've placed inside the colony to give an interior panorama. If you keep the view steady, it doesn't flicker at all, and if you look around, it only flickers a tiny bit in a few places. Hardly noticeable at all. I've improved the mesh a little bit as well, adding "hinges" on the mirrors, and bridges across the windows between the various land areas. Also fixed a few normals that were reversed, but you could hardly see them anyway.
I've also added UMMU capability, but so far have not been able to add the capability to switch active docks, which is something this requires, of course, or add the ability to add crew while the sim is running. I copied all the code from the SDK readmes and examples, but it won't compile, citing various problems with the word "UMmuCrewAddCallback" involving "bool"s and a bunch of "*"s that make absolutely no sense to me. My compiler was saying "use &oneill::UMmuCrewAddCallback" but I've never been able to find a satisfactory explanation of what an "&" means to C++ or where I should put said character, and my trial and error method was getting me nowhere.
So I'm asking for help; here's the entire code for the colony, with the problem sections removed - This is the latest code I have that works:
Code:
// ==============================================================
//O'Neill Colony Source Code
//Taken from the Shuttle PB - I didn't want to mess with anything I didn't have to, so there's
//a lot of meaningless data left over, but hopefully it won't be an issue.
// ==============================================================
#define STRICT
#define ORBITER_MODULE
#include "orbitersdk.h"
#include "math.h"
#include "UmmuSDK.h"
// ==============================================================
// Some vessel parameters
// ==============================================================
// Calculate lift coefficient [Cl] as a function of aoa (angle of attack) over -Pi ... Pi
// Implemented here as a piecewise linear function
// When are you gonna have this thing in an atmosphere? Maybe you could drop it onto a city.
// I dunno, I'm just worried cutting this code will mess things up somehow.
// Adding seemingly unrelated things has all sorts of unanticipated effects in the sim.
double LiftCoeff (double aoa)
{
const int nlift = 9;
static const double AOA[nlift] = {-180*RAD,-60*RAD,-30*RAD,-1*RAD,15*RAD,20*RAD,25*RAD,60*RAD,180*RAD};
static const double CL[nlift] = { 0, 0, -0.1, 0, 0.2, 0.25, 0.2, 0, 0};
static const double SCL[nlift] = {(CL[1]-CL[0])/(AOA[1]-AOA[0]), (CL[2]-CL[1])/(AOA[2]-AOA[1]),
(CL[3]-CL[2])/(AOA[3]-AOA[2]), (CL[4]-CL[3])/(AOA[4]-AOA[3]),
(CL[5]-CL[4])/(AOA[5]-AOA[4]), (CL[6]-CL[5])/(AOA[6]-AOA[5]),
(CL[7]-CL[6])/(AOA[7]-AOA[6]), (CL[8]-CL[7])/(AOA[8]-AOA[7])};
int i;
for (i = 0; i < nlift-1 && AOA[i+1] < aoa; i++);
return CL[i] + (aoa-AOA[i])*SCL[i];
}
// ==============================================================
// O'Neill class interface
// ==============================================================
class oneill: public VESSEL2
{
public:
oneill (OBJHANDLE hVessel, int flightmodel)
: VESSEL2 (hVessel, flightmodel), rotation_angle(0.0), cloud_angle(0.0) {};
void clbkSetClassCaps (FILEHANDLE cfg);
void clbkPreStep (double SimT, double SimDT, double mjd);
void DefineAnimations ();
UINT anim_grav;
UINT anim_cloud;
double rotation_angle;
double cloud_angle;
// UMMU 2.0 DECLARATION (OK, here goes nothing...)
UMMUCREWMANAGMENT Crew;
int iSelectedUmmuMember; // for the SDK demo, select the member to eva
// The HUD display method variable
char cUmmuHudDisplay[255]; // UMmu hud char variable
double dHudMessageDelay; // UMmu hud display delay
char *SendHudMessage(void); // UMmu hud display function
//--------------------------------------------------------------------------------------
//OK, is this how this works? You have to put the headings of the various "blocks" in this "class interface" section?
void clbkDrawHUD (int mode, const HUDPAINTSPEC *hps, HDC hDC);
int clbkConsumeBufferedKey(DWORD key, bool down, char *kstate);
bool UMmuCrewAddCallback(void *id, char *str, void *data);
void clbkSaveState(FILEHANDLE scn);
void clbkLoadStateEx (FILEHANDLE scn, void *status);
int SelectedUmmuMember; // for the SDK demo, select the member to eva
//Did that do the trick? Seriously, I don't get this at all.
//---------------------------------------------------------------------------------------
};
const double rotation_speed = 3.2 / 360.0;
const double cloud_speed = 1.6 / 360.0;
void oneill::DefineAnimations ()
{
static UINT grav_groups[] = {1,2,7,6,8,9,10,3,13};
static UINT cloud_groups[] = {11};
static MGROUP_ROTATE grav (
0,
grav_groups, 7,
_V(0,0,0),
_V(0,0,1),
(float)(2.0*PI)
);
static MGROUP_ROTATE clouds (
0,
cloud_groups, 1,
_V(0,0,0),
_V(0,0,1),
(float)(2.0*PI)
);
anim_grav = CreateAnimation (0.0);
AddAnimationComponent (anim_grav, 0, 1, &grav);
anim_cloud = CreateAnimation (0.0);
AddAnimationComponent (anim_cloud, 0, 1, &clouds);
char logstring[40];
sprintf (logstring, "Created animation");
oapiWriteLog (logstring);
}
void oneill::clbkPreStep (double SimT, double SimDT, double mjd)
{
double da = SimDT * rotation_speed; // Delta angle
rotation_angle += da;
if (rotation_angle > 1.0) rotation_angle -= floor(rotation_angle);
SetAnimation (anim_grav, rotation_angle);
da = SimDT * cloud_speed;
cloud_angle += da;
if (cloud_angle >1.0) cloud_angle -= floor(cloud_angle);
SetAnimation (anim_cloud, cloud_angle);
//sprintf (oapiDebugString(), "Rot Speed: %.4f Delta Time: %.4f Delta Angle: %.4f Rot Angle: %.4f", rotation_speed, SimDT, da, rotation_angle);
//---------------------------------------------------------------------------
// ProcessUniversalMMu
// Here the routine that detect if someone entered the ship (eva or transfer)
// No need to manage anything here all is automatic, crew is added to your ship, ship's weight is updated,
// and UMmu vessel is automatically deleted from Orbiter. You may just look the return
// code to see if someone entered and display wathewer message on panel or other.
// notice it's FPS friendly, function process only 4 time per second not each frame
// and return immediately if airlock closed or no Ummu is detected in vincinity.
int ReturnCode=Crew.ProcessUniversalMMu();
switch(ReturnCode)
{
case UMMU_TRANSFERED_TO_OUR_SHIP:
sprintf(SendHudMessage(),"%s \"%s\" aged %i has entered the Colony - Zero-G tow lines to the Central Hub are available in the Green Area...",
Crew.GetCrewMiscIdByName(Crew.GetLastEnteredCrewName()),Crew.GetLastEnteredCrewName()
,Crew.GetCrewAgeByName(Crew.GetLastEnteredCrewName()));
break;
case UMMU_RETURNED_TO_OUR_SHIP:
sprintf(SendHudMessage(),"%s \"%s\" aged %i has entered the Colony - Zero-G tow lines to the Central Hub are available in the Green Area...",
Crew.GetCrewMiscIdByName(Crew.GetLastEnteredCrewName()),
Crew.GetLastEnteredCrewName(),Crew.GetCrewAgeByName(Crew.GetLastEnteredCrewName()));
break;
}
//----------------------------------------------------------------------------
// SetCrewMemberPulseBySlotNumber
// Now we will kill all our crew aboard if we crash on ground. First we test
// if we have ground contact, then we check vertical speed and if it's more than
// -3 m/s we kill all people aboard. Of course in your code you'll do that only
// one time using a bool flag if(!bCrewAlreadyKilled) for example. Here we do it each
// time step for code ease of read.
if(GroundContact()==TRUE)
{
// we check vertical speed
int I;
VECTOR3 vHorizonAirspeedVector={0};
GetHorizonAirspeedVector (vHorizonAirspeedVector);
double VertSpeed =vHorizonAirspeedVector.y;
if(VertSpeed<-3)
{
// we touched ground with more than -3 m/s, sorry dude, time to kill you all :(
for(I=0;I<Crew.GetCrewTotalNumber();I++)
{
Crew.SetCrewMemberPulseBySlotNumber(I,0); // set cardiac pulse to zero
}
strcpy(SendHudMessage(),"Orbital Drop Operation successful. Tabulating casualty rates and mushroom cloud height...");
}
// TIPS: the vertical speed is often reset to zero when there is ground contact
// this may bug somewhat the death of your crew.
// to have an accurate VertSpeed at touchdown I recommand to record it at very END
// of timestep and use this "old" value. The next frame you'll have the vertspeed value
// of *last frame* just before the crash (GroundContact). This ensure an accurate
// verticalspeed value. (keep this value in your vessel class and don't forget to
// initialize it at zero in setclasscap)
}
//---------------------------------------------------------------------------
// WarnUserUMMUNotInstalled - IMPORTANT helper
// Put here this function and users will be automatically warned if they don't have
// UMMU installed or if it's outdated. Warning text duration is 20 seconds and text is:
// [AddonName] require "Universal MMU" ver 2.0 or higher. Download at www.orbiter.dansteph.com (message countdown in seconds)
// an additonal "your version of UMMU is outdated" is displayed the last 5 seconds if they have version lower than 2.0
Crew.WarnUserUMMUNotInstalled("O'Neill Island 3 Colony");
}
// --------------------------------------------------------------
// Orbiter's HUD callback
// used to display UMMU's message see PDF doc:
// "Example of feedback method by HUD Display"
// --------------------------------------------------------------
void oneill::clbkDrawHUD (int mode, const HUDPAINTSPEC *hps, HDC hDC)
{
// draw the default HUD
VESSEL2::clbkDrawHUD (mode, hps, hDC);
// UMmu display messages
if(dHudMessageDelay>0)
{
TextOut (hDC,5,hps->H/60*15,cUmmuHudDisplay,strlen(cUmmuHudDisplay));
dHudMessageDelay-=oapiGetSimStep();
if(dHudMessageDelay<0)
dHudMessageDelay=0;
}
}
//Another Hud thing. DELETE ME IF THINGS GET MESSED UP.
char *oneill::SendHudMessage()
{
dHudMessageDelay=30;
return cUmmuHudDisplay;
}
// --------------------------------------------------------------
// --------------------------------------------------------------
// Set the capabilities of the vessel class
// --------------------------------------------------------------
void oneill::clbkSetClassCaps (FILEHANDLE cfg)
{
// physical specs, etc. below
SetSize (10000);//Not technically correct, but having it smaller solves some z-fighting issues.
SetAlbedoRGB (_V(1.0,1.0,1.0));
SetVisibilityLimit (1.0e-3, 1.0e-9); //Why doesn't this work, either? I want it to show up as a white dot
//from far away, but no such luck. Is there a maximum visual distance for vessels?
SetEmptyMass (3.9e12);
SetCW (0.3, 0.3, 0.6, 0.9);
SetWingAspect (0.7);
SetWingEffectiveness (2.5);
SetCrossSections (_V(3.0e8,3.0e8,3.0e7));
SetRotDrag (_V(3.0e8,3.0e8,3.0e7));
if (GetFlightModel() >= 1) {
SetPitchMomentScale (1e-4);
SetBankMomentScale (1e-4);
}
SetPMI (_V(3.0e8,3.0e8,3.0e7));
SetTrimScale (0.0);
SetCameraOffset (_V(0,0,0));
SetLiftCoeffFunc (LiftCoeff);
SetTouchdownPoints (_V(-1000,-3000,-20000), _V(1000,-3000,-20000), _V(0,-3000,20000));
DefineAnimations();
//Docks
CreateDock (_V(81.74,189.56,21699.40),_V(0,0,1),_V(0,1,0));
CreateDock (_V(-277.8,-161.5,21655.64),_V(0,0,1),_V(0,1,0));
CreateDock (_V(323.983,72.23,21455.67),_V(0,0,1),_V(0,1,0));
CreateDock (_V(323.8,-161.75,21455.67),_V(0,0,1),_V(0,1,0));
CreateDock (_V(-277.8,189.16,21456.98),_V(0,0,1),_V(0,1,0));
// visual specs
AddMesh ("oneill");
SetMeshVisibilityMode (0,MESHVIS_ALWAYS);
Crew.InitUmmu(GetHandle());// Must always be the first one
Crew.DefineAirLockShape(TRUE,-3,3,-4,4,-7,7);// Airlock open, 6 meter large 8 meter high 14 meter long
Crew.SetMembersPosRotOnEVA(_V(0,0,3),_V(0,0,0));// position when EVA, 3 meter in front of ship
Crew.SetMaxSeatAvailableInShip(50);// Max Numbers of UMMU for this ship
// Add default members for when the ship is spawned by scenario editor
Crew.AddCrewMember("Governer Myles",41,65,74,"Capt");
Crew.AddCrewMember("Adrianne Myles",37,67,55,"Eng");
Crew.AddCrewMember("Achmed Velina",29,70,45,"Doc");
Crew.AddCrewMember("Shion Yamagishi",25,70,45,"Sci");
Crew.AddCrewMember("Karl Magnum",19,70,45);
Crew.AddCrewMember("Peter Ngolo",32,70,45);
Crew.AddCrewMember("ChunLam Cheng",61,70,45);
Crew.AddCrewMember("Francois Zelig",48,70,45);
Crew.AddCrewMember("Terra MacLeod",31,70,45,"Eng");
Crew.AddCrewMember("Johannes Ivonovich",38,70,45);
Crew.AddCrewMember("Isidor Kolontai",26,70,45);
Crew.AddCrewMember("Lyra Esposito",23,70,45,"Eng");
iSelectedUmmuMember=0; // Initialize of select member variable
// The HUD display method variables
cUmmuHudDisplay[0] =0;// Initialisation of UMmu hud char variable
dHudMessageDelay =0;// Initialisation of UMmu delay variable
strcpy(SendHudMessage(),"Spacedock on line six, transferring control now... E=EVA, 1/2=Select personnel A=Open/Close airlock S=info M=Add personnel");
}
int oneill::clbkConsumeBufferedKey(DWORD key, bool down, char *kstate)
{
// only process keydown events
if (!down)
return 0;
//---------------------------------------------------------------------------
// Ummu Key "E" perform the EVA of the selected member
//
// ADD REALISM: It's your responsabilities also to set ship's control accordingly to crew aboard.
// If you want to disable control if no one is aboard have a look at "SetADCtrlMode()"
// and "SetAttitudeMode()" functions of Orbiter. To disable thrusters set their fuel
// ressource to NULL.
if(key==OAPI_KEY_E&&!KEYMOD_SHIFT(kstate)&&!KEYMOD_CONTROL (kstate))
{
// PERFORM THE EVA, first we get is name with "GetCrewNameBySlotNumber" then we perform EVA with "EvaCrewMember"
int Returned=Crew.EvaCrewMember(Crew.GetCrewNameBySlotNumber(SelectedUmmuMember));
// we provide feedback to user (You can display a message on panel or wathewer)
// here below all the return code possible:
switch(Returned)
{
case TRANSFER_TO_DOCKED_SHIP_OK:
sprintf(SendHudMessage(),"Airlock pressure stable - %s is boarding the docked ship. Caution, tow line ends at airlock inner door...",
Crew.GetLastEvaedCrewName());SelectedUmmuMember=0;
break;
case EVA_OK:
sprintf(SendHudMessage(),"EVA OK - %s commencing spacewalk. All traffic, be advised.",
Crew.GetLastEvaedCrewName());SelectedUmmuMember=0;
break;
case ERROR_NO_ONE_ON_BOARD:
strcpy(SendHudMessage(),"Error: No qualified personnel in Spacedock area. Unable to EVA.");
break;
case ERROR_AIRLOCK_CLOSED:
strcpy(SendHudMessage(),"Error: Airlock is closed. Unable to EVA.");
break;
case ERROR_DOCKED_SHIP_HAVE_AIRLOCK_CLOSED:
strcpy(SendHudMessage(),"Error: Docked ship's airlock is closed. Unable to board.");
break;
case ERROR_DOCKED_SHIP_IS_FULL:
strcpy(SendHudMessage(),"Error: Docked ship is already full. Please contact the appropriate personnel already aboard.");
break;
case ERROR_CREW_MEMBER_NOT_FOUND:
strcpy(SendHudMessage(),"Error: No one by this name in Spacedock area. Repeat, %s please report to information kiosk...");
break;
case ERROR_DOCKEDSHIP_DONOT_USE_UMMU:
strcpy(SendHudMessage(),"Error: Docked ship do not use UMMU 2.0. Please ask author to add it.");
break;
case ERROR_MISC_ERROR_EVAFAILED:
strcpy(SendHudMessage(),"Misc error with UMMU - Please reinstall.");
break;
}
return TRUE;
}
//---------------------------------------------------------------------------
// Ummu Key "1" Select next member This is just internal to the demo
// you may do your own selection system by panel button, name etc etc
if(key==OAPI_KEY_1&&!KEYMOD_SHIFT(kstate)&&!KEYMOD_CONTROL (kstate))
{
// we test there is someone aboard
if(Crew.GetCrewTotalNumber()==0)
{
strcpy(SendHudMessage(),"No personnel available in Spacedock area - Please add to roster. Trams to Hab Section are standing by.");
return 1;
}
// we test that we select existing member
if(SelectedUmmuMember<Crew.GetCrewTotalNumber()-1)
SelectedUmmuMember++;
char * Name=Crew.GetCrewNameBySlotNumber(SelectedUmmuMember);
sprintf(SendHudMessage(),"Position %i %s \"%s\" aged %i Selected for EVA or Transfer - Press \"E\" to EVA.",
SelectedUmmuMember,Crew.GetCrewMiscIdBySlotNumber(SelectedUmmuMember),
Name,Crew.GetCrewAgeBySlotNumber(SelectedUmmuMember));
return 1;
}
//---------------------------------------------------------------------------
// Ummu Key "2" Select previous member This is just internal to the demo
// you may do your own selection system by panel button
if(key==OAPI_KEY_2&&!KEYMOD_SHIFT(kstate)&&!KEYMOD_CONTROL (kstate))
{
// we test there is someone aboard
if(Crew.GetCrewTotalNumber()==0)
{
strcpy(SendHudMessage(),"No personnel available in Spacedock area - Please add to roster. Trams to Hab Section are standing by.");
return 1;
}
if(SelectedUmmuMember>0)
SelectedUmmuMember--;
char * Name=Crew.GetCrewNameBySlotNumber(SelectedUmmuMember);
sprintf(SendHudMessage(),"Slot %i %s \"%s\" aged %i Selected for EVA or Transfer"
", please press \"E\" to EVA",SelectedUmmuMember,
Crew.GetCrewMiscIdBySlotNumber(SelectedUmmuMember),Name,
Crew.GetCrewAgeBySlotNumber(SelectedUmmuMember));
return 1;
}
//---------------------------------------------------------------------------
// Ummu Key "A" Switch the virtual UMMU airlock door on/off
if(key==OAPI_KEY_A&&!KEYMOD_SHIFT(kstate)&&!KEYMOD_CONTROL (kstate))
{
// switch state
Crew.SetAirlockDoorState(!Crew.GetAirlockDoorState());
// display state
if(Crew.GetAirlockDoorState()==TRUE)
strcpy(SendHudMessage(),"Airlock is now open");
else
strcpy(SendHudMessage(),"Airlock is now closed");
return 1;
}
//---------------------------------------------------------------------------
// Get some infos Name of ship and total soul aboard
if(key==OAPI_KEY_S)
{
sprintf(SendHudMessage(),"Currently %i personnel available in %s Spacedock, with %i positions available.",
Crew.GetCrewTotalNumber(),GetName(),50-Crew.GetCrewTotalNumber());
return 1;
}
//---------------------------------------------------------------------------
// Use a different Mesh (type "C" then EVA someone)
// better idea is to use the new UMMU Id definition
// look readme.txt in folder "config/UMMUIdConfig"
if(key==OAPI_KEY_C)
{
Crew.SetAlternateMeshToUseForEVASpacesuit("mmu"); // the stock mmu of orbiter located in "meshes/mmu.msh"
strcpy(SendHudMessage(),"Mesh changed");
return 1;
}
return 0;
}
// --------------------------------------------------------------
// Write status to scenario file. THIS IS NEW - DELETE ME IF THIS DOESN'T WORK
// --------------------------------------------------------------
void oneill::clbkSaveState(FILEHANDLE scn)
{
// ORBITER, default vessel parameters
SaveDefaultState (scn);
// UMmu, this will save all our members of crew in scenario
// as airlock state depend of your ship (you may have a real animated airlock)
// it's your responsabilites to save and reload UMmu's airlock state.
Crew.SaveAllMembersInOrbiterScenarios(scn);
}
///////////////////////////////////////////////////////////////////////////////////////////
// clbkLoadStateEx function of Orbiter - Load Orbiter scenario !REQUIRED!
// ---------------
// Here we'll reload all crew member of our ship.
// notice the function will ERASE all defaults member set in clbkSetClassCaps.
// If you really want to add default crew add them also in this fonction after loading
// (when a ship is spawned by editor anyway this fonction below is never called)
///////////////////////////////////////////////////////////////////////////////////////////
void oneill::clbkLoadStateEx (FILEHANDLE scn, void *status)
{
char *line;
while (oapiReadScenario_nextline (scn, line))
{
// UMMU, Load all saved member from scenario.
// Return TRUE when a "UMMUCREW" line is encountered
// FALSE when it must pass this line to you or default parser
if(Crew.LoadAllMembersFromOrbiterScenario(line)==TRUE)
continue;
// ORBITER, unrecognised option - pass to Orbiter's generic parser
ParseScenarioLineEx (line, status);
}
// as airlock state depend of your ship (you may have a real animated airlock)
// it's your responsabilites to save and reload UMmu airlock state and set it accordingly
// to your airlock. IE: call here "SetAirlockDoorState" TRUE of FALSE depend
// of your animated airlock
}
// --------------------------------------------------------------
// Vessel initialisation
// --------------------------------------------------------------
DLLCLBK VESSEL *ovcInit (OBJHANDLE hvessel, int flightmodel)
{
return new oneill (hvessel, flightmodel);
}
// --------------------------------------------------------------
// Vessel cleanup
// --------------------------------------------------------------
DLLCLBK void ovcExit (VESSEL *vessel)
{
if (vessel) delete (oneill*)vessel;
}
THINGS LEFT TO DO:
- Add multiple UMMU docks
- Add the ability to add new crew while Orbiter is still running
- Tweak the textures for the new mesh (this I can do easily on my own)
- Figure out a value for "SetVisibilityLimit" so that the colony appears as a white dot from far away, instead of suddenly appearing as a mesh a few thousand km away. I have tried everything I can think of and nothing seems to work.
- Add beacons; if someone can give me the code for a stationary one and a rotating one, I can place the rest myself.
- Add RCS and main engines. I'm pretty sure I can do that myself, and someone might want to mess around with them. I think I remember someone mentioning it in the old thread.
That's all I can think of... I was wondering about adding UCGO as well, since there's a line of white squares on the right side of the dock texture that's believable as some kind of cargo attachment area, but one thing at a time, I guess.
If someone could help me with this code, I'd be extremely grateful - It's entirely beyond my skill level and makes no sense to me. None of the tutorials are thorough enough, and the API documents don't have any context for the layperson.
If anyone is willing to talk me through this or, wonder of wonders, put the code in themselves, I will happily return the favor with a textured mesh or a drawing or some other item that falls more within my skillset.
Attachments
Last edited: