Board index FlightGear Development Nasal

3D models with Nasal  Topic is solved

Nasal is the scripting language of FlightGear.

3D models with Nasal

Postby RenanMsV » Sun Mar 26, 2017 11:56 pm

Can I create an Addon that load a 3D model, animate it and control with Nasal? Regardless of which aircraft I am using
www.flightgearbrasil.com.br
www.fgbrazukas.wixsite.com/fgbrazukas
RenanMsV
 
Posts: 134
Joined: Thu Oct 27, 2016 3:02 am
Callsign: BR-RVD

Re: 3D models with Nasal

Postby Necolatis » Mon Mar 27, 2017 12:37 am

Yes you can.

It will be tied to the world though and not the aircraft, but by updating it every frame, you can make it appear to be attached to the aircraft.

I will post the code to do this later today or tomorrow, don't have time right now. Unless somebody else beats me to it.
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2233
Joined: Mon Oct 29, 2012 1:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2020.3.19
OS: Windows 10

Re: 3D models with Nasal  

Postby Necolatis » Mon Mar 27, 2017 5:03 am

First you make the model. It should just be normal xml as if you were gonna load it though aircraft model system.

Code: Select all
 var n = props.globals.getNode("models", 1);
  var i = 0;
  for (i = 0; 1==1; i += 1) {
    if (n.getChild("model", i, 0) == nil) {
      break;
    }
  }
  var objModel = n.getChild("model", i, 1);

  objModel.getNode("elevation",1).setDoubleValue(0);
  objModel.getNode("latitude",1).setDoubleValue(0);
  objModel.getNode("longitude",1).setDoubleValue(0);
  objModel.getNode("elevation-ft-prop",1).setValue(objModel.getPath()~"/elevation");
  objModel.getNode("latitude-deg-prop",1).setValue(objModel.getPath()~"/latitude");
  objModel.getNode("longitude-deg-prop",1).setValue(objModel.getPath()~"/longitude");
  objModel.getNode("heading",1).setDoubleValue(0);
  objModel.getNode("pitch",1).setDoubleValue(0);
  objModel.getNode("roll",1).setDoubleValue(0);
  objModel.getNode("heading-deg-prop",1).setValue(objModel.getPath()~"/heading");
  objModel.getNode("pitch-deg-prop",1).setValue(objModel.getPath()~"/pitch");
  objModel.getNode("roll-deg-prop",1).setValue(objModel.getPath()~"/roll");

  objModel.getNode("path",1).setValue("myModel.xml"); # this is the model to be loaded.

  var loadNode = objModel.getNode("load", 1);
  loadNode.setBoolValue(1);
  loadNode.remove();


Now its loaded and shown (at the center of earth) so all you have to do to manipulate it, is to manipulate the properties under objModel.getPath() .. (the ones without the -prop ending). If you need to animate specific within it, you can do that the regular fashion with animation tags inside the xml and link that to properties you control via nasal.

Now if you want to make it appear to be attached to aircraft coordinates instead of lat,lon, alt, you are gonna need a helper method that translate between them. James is in progress of making one in C for nasal called aircraftToCart(), but until that gets committed into Flightgear you can use this, its not super precise though (at certain aircraft attitudes):

Code: Select all
var getGPS = func(x, y, z) {
   #
   # get Coord from body structural position. x,y,z must be in meters.
        #
   # Derived from Vivian Meazza's code in AIModel/submodel.cxx by Alexis Bory.
   # Bugfixes by Nikolai V. Chr.

   var ac = geo.aircraft_position();

   if(x == 0 and y==0 and z==0) {
      return geo.Coord.new(ac);
   }

   var ac_roll = getprop("orientation/roll-deg");
   var ac_pitch = getprop("orientation/pitch-deg");
   var ac_hdg   = getprop("orientation/heading-deg");

   var in    = [0,0,0];
   var trans = [[0,0,0],[0,0,0],[0,0,0]];
   var out   = [0,0,0];

   in[0] =  -x * M2FT;
   in[1] =   y * M2FT;
   in[2] =   z * M2FT;
   # Pre-process trig functions:
   var cosRx = math.cos(-ac_roll * D2R);
   var sinRx = math.sin(-ac_roll * D2R);
   var cosRy = math.cos(-ac_pitch * D2R);
   var sinRy = math.sin(-ac_pitch * D2R);
   var cosRz = math.cos(ac_hdg * D2R);
   var sinRz = math.sin(ac_hdg * D2R);
   # Set up the transform matrix:
   trans[0][0] =  cosRy * cosRz;
   trans[0][1] =  -1 * cosRx * sinRz + sinRx * sinRy * cosRz ;
   trans[0][2] =  sinRx * sinRz + cosRx * sinRy * cosRz;
   trans[1][0] =  cosRy * sinRz;
   trans[1][1] =  cosRx * cosRz + sinRx * sinRy * sinRz;
   trans[1][2] =  -1 * sinRx * cosRx + cosRx * sinRy * sinRz;
   trans[2][0] =  -1 * sinRy;
   trans[2][1] =  sinRx * cosRy;
   trans[2][2] =  cosRx * cosRy;
   # Multiply the input and transform matrices:
   out[0] = in[0] * trans[0][0] + in[1] * trans[0][1] + in[2] * trans[0][2];
   out[1] = in[0] * trans[1][0] + in[1] * trans[1][1] + in[2] * trans[1][2];
   out[2] = in[0] * trans[2][0] + in[1] * trans[2][1] + in[2] * trans[2][2];
   # Convert ft to degrees of latitude:
   out[0] = out[0] / (366468.96 - 3717.12 * math.cos(ac.lat() * D2R));
   # Convert ft to degrees of longitude:
   out[1] = out[1] / (365228.16 * math.cos(ac.lat() * D2R));
   # Set position:
   var mlat = ac.lat() + out[0];
   var mlon = ac.lon() + out[1];
   var malt = (ac.alt() * M2FT) + out[2];
   
   var c = geo.Coord.new();
   c.set_latlon(mlat, mlon, malt * FT2M);

   return c;
}


Just call that with the coordinates from the aircraft coordinate system, and it will return a geo.Coord as result. Then you can just ask that for result.alt() [is in meters], result.lat(), result.lon() and put that into your model every frame.
Last edited by Necolatis on Wed Mar 29, 2017 8:48 pm, edited 1 time in total.
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2233
Joined: Mon Oct 29, 2012 1:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2020.3.19
OS: Windows 10

Re: 3D models with Nasal

Postby RenanMsV » Tue Mar 28, 2017 1:12 pm

It's like the UFO system works ?
www.flightgearbrasil.com.br
www.fgbrazukas.wixsite.com/fgbrazukas
RenanMsV
 
Posts: 134
Joined: Thu Oct 27, 2016 3:02 am
Callsign: BR-RVD

Re: 3D models with Nasal

Postby Necolatis » Tue Mar 28, 2017 5:08 pm

No idea.
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2233
Joined: Mon Oct 29, 2012 1:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2020.3.19
OS: Windows 10

Re: 3D models with Nasal

Postby RenanMsV » Wed Mar 29, 2017 8:20 pm

Having a problem with M2FT or D2R.

"nil used in numeric context"
www.flightgearbrasil.com.br
www.fgbrazukas.wixsite.com/fgbrazukas
RenanMsV
 
Posts: 134
Joined: Thu Oct 27, 2016 3:02 am
Callsign: BR-RVD

Re: 3D models with Nasal

Postby Necolatis » Wed Mar 29, 2017 8:39 pm

M2FT and D2R is never nil.

Which line was the error on?

Edit: I just found an error in the first snippet of code, is corrected now.
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2233
Joined: Mon Oct 29, 2012 1:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2020.3.19
OS: Windows 10

Re: 3D models with Nasal

Postby RenanMsV » Wed Mar 29, 2017 8:53 pm

Code: Select all
var n = props.globals.getNode("models", 1);
var i = 0;
for (i = 0; 1==1; i += 1) {
  if (n.getChild("model", i, 0) == nil) {
    break;
  }
}
var objModel = n.getChild("model", i, 1);

objModel.getNode("elevation",1).setDoubleValue(0);
objModel.getNode("latitude",1).setDoubleValue(0);
objModel.getNode("longitude",1).setDoubleValue(0);
objModel.getNode("elevation-ft-prop",1).setValue(objModel.getPath()~"/elevation");
objModel.getNode("latitude-deg-prop",1).setValue(objModel.getPath()~"/latitude");
objModel.getNode("longitude-deg-prop",1).setValue(objModel.getPath()~"/longitude");
objModel.getNode("heading",1).setDoubleValue(0);
objModel.getNode("pitch",1).setDoubleValue(0);
objModel.getNode("roll",1).setDoubleValue(0);
objModel.getNode("heading-deg-prop",1).setValue(objModel.getPath()~"/heading");
objModel.getNode("pitch-deg-prop",1).setValue(objModel.getPath()~"/pitch");
objModel.getNode("roll-deg-prop",1).setValue(objModel.getPath()~"/roll");

  objModel.getNode("path",1).setValue((getprop("/sim/fg-root") ~ "/Nasal/br_fgpassengers/models/operations.xml")); # this is the model to be loaded.

  var loadNode = objModel.getNode("load", 1);
  loadNode.setBoolValue(1);
  loadNode.remove();

  var repeattimer = func () {
     settimer(
      func {
       refreshCoord();
       print("Done");
       },0.1
       );
  }

  var refreshCoord = func(){
     var coord = props.globals.getNode("position");
   var result = getGPS(coord.getNode("latitude-deg").getValue(),coord.getNode("longitude-deg").getValue(), coord.getNode("ground-elev-m").getValue());
   print(coord.getNode("latitude-deg").getValue());
   objModel.getNode("elevation",1).setDoubleValue(result.alt());
   objModel.getNode("latitude",1).setDoubleValue(result.lat());
   objModel.getNode("longitude",1).setDoubleValue(result.lon());
   repeattimer();
 }

 var getGPS = func(x, y, z) {
   #
   # get Coord from body structural position. x,y,z must be in meters.
        #
   # Derived from Vivian Meazza's code in AIModel/submodel.cxx by Alexis Bory.
   # Bugfixes by Nikolai V. Chr.

   var ac = geo.aircraft_position();

   if(x == 0 and y==0 and z==0) {
    return geo.Coord.new(ac);
  }

  var ac_roll = getprop("orientation/roll-deg");
  var ac_pitch = getprop("orientation/pitch-deg");
  var ac_hdg   = getprop("orientation/heading-deg");

  var in    = [0,0,0];
  var trans = [[0,0,0],[0,0,0],[0,0,0]];
  var out   = [0,0,0];

  in[0] =  -x * M2FT;
  in[1] =   y * M2FT;
  in[2] =   z * M2FT;
   # Pre-process trig functions:
   var cosRx = math.cos(-ac_roll * D2R);
   var sinRx = math.sin(-ac_roll * D2R);
   var cosRy = math.cos(-ac_pitch * D2R);
   var sinRy = math.sin(-ac_pitch * D2R);
   var cosRz = math.cos(ac_hdg * D2R);
   var sinRz = math.sin(ac_hdg * D2R);
   # Set up the transform matrix:
   trans[0][0] =  cosRy * cosRz;
   trans[0][1] =  -1 * cosRx * sinRz + sinRx * sinRy * cosRz ;
   trans[0][2] =  sinRx * sinRz + cosRx * sinRy * cosRz;
   trans[1][0] =  cosRy * sinRz;
   trans[1][1] =  cosRx * cosRz + sinRx * sinRy * sinRz;
   trans[1][2] =  -1 * sinRx * cosRx + cosRx * sinRy * sinRz;
   trans[2][0] =  -1 * sinRy;
   trans[2][1] =  sinRx * cosRy;
   trans[2][2] =  cosRx * cosRy;
   # Multiply the input and transform matrices:
   out[0] = in[0] * trans[0][0] + in[1] * trans[0][1] + in[2] * trans[0][2];
   out[1] = in[0] * trans[1][0] + in[1] * trans[1][1] + in[2] * trans[1][2];
   out[2] = in[0] * trans[2][0] + in[1] * trans[2][1] + in[2] * trans[2][2];
   # Convert ft to degrees of latitude:
   out[0] = out[0] / (366468.96 - 3717.12 * math.cos(ac.lat() * D2R));
   # Convert ft to degrees of longitude:
   out[1] = out[1] / (365228.16 * math.cos(ac.lat() * D2R));
   # Set position:
   var mlat = ac.lat() + out[0];
   var mlon = ac.lon() + out[1];
   var malt = (ac.alt() * M2FT) + out[2];
   
   var c = geo.Coord.new();
   c.set_latlon(mlat, mlon, malt * FT2M);

   return c;
 }
 refreshCoord();


Nil in numeric context
Line 71
Called from 40
Called from 107

Line 71 : in[2] = z * M2FT;

I'm probably calling the function with wrong parameters
www.flightgearbrasil.com.br
www.fgbrazukas.wixsite.com/fgbrazukas
RenanMsV
 
Posts: 134
Joined: Thu Oct 27, 2016 3:02 am
Callsign: BR-RVD

Re: 3D models with Nasal

Postby Necolatis » Wed Mar 29, 2017 9:20 pm

Its z that is nil then. Its probably position/ground-elev-m that is nil due to terrasync not having loaded the terrain yet, or maybe its called before terrain is loaded.

However you are using getGPS wrong, it works opposite than what you are doing. The x,y,z you put into it is in the same coordinate system as the AC3D model is in. Then what you get out of it, is GPS coordinates, so lat, lon and alt, which you did correct.
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2233
Joined: Mon Oct 29, 2012 1:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2020.3.19
OS: Windows 10

Re: 3D models with Nasal

Postby RenanMsV » Wed Mar 29, 2017 9:34 pm

Oh, ok thanks, I get it now, it's used to position the object in relation to the aircraft.
The object was created attached to the world, but it created one more.
Having two objects.
Models
Models [1]
All with the same data.
www.flightgearbrasil.com.br
www.fgbrazukas.wixsite.com/fgbrazukas
RenanMsV
 
Posts: 134
Joined: Thu Oct 27, 2016 3:02 am
Callsign: BR-RVD

Re: 3D models with Nasal

Postby Necolatis » Wed Mar 29, 2017 9:39 pm

I suspect your code has then been ran 2 times, how did you call it to start with?
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2233
Joined: Mon Oct 29, 2012 1:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2020.3.19
OS: Windows 10

Re: 3D models with Nasal

Postby RenanMsV » Wed Mar 29, 2017 9:45 pm

Thank you! It is now working properly. Now I just have to do the "easiest" part, animate everything. Thank you!
www.flightgearbrasil.com.br
www.fgbrazukas.wixsite.com/fgbrazukas
RenanMsV
 
Posts: 134
Joined: Thu Oct 27, 2016 3:02 am
Callsign: BR-RVD

Re: 3D models with Nasal

Postby Necolatis » Wed Mar 29, 2017 9:49 pm

Your welcome.
"Airplane travel is nature's way of making you look like your passport photo."
— Al Gore
User avatar
Necolatis
 
Posts: 2233
Joined: Mon Oct 29, 2012 1:40 am
Location: EKOD
Callsign: Leto
IRC name: Neco
Version: 2020.3.19
OS: Windows 10


Return to Nasal

Who is online

Users browsing this forum: No registered users and 2 guests