Page 6 of 46

Posted: Mon Apr 06, 2009 6:59 pm
by Ramirez
This should have been easy. I'm setting up what should be a simple distance check but I'm having trouble. I've got a checkDistance function in the ship script and a FOUND_PLAYER state in the ship's AI, but it's refusing to change AI state.

Here's the script:

Code: Select all

this.checkDistance = function()
{if(player.ship.position.distanceTo(this.ship) < 5000)
   {this.ship.target = player.ship;
   this.ship.reactToAIMessage("FOUND_PLAYER")}
   }
While in the AI I have the function:

Code: Select all

"FOUND_PLAYER" =
{
		ENTER = (performAttack);
		ATTACKED = (setTargetToPrimaryAggressor, "setStateTo: ATTACK_SHIP");
		"ENERGY_LOW" = ("setStateTo: FLEE");
		"INCOMING_MISSILE" = (fightOrFleeMissile, "setStateTo: FLEE");
		"TARGET_DESTROYED" = ("setStateTo: WAIT_FOR_PLAYER");
		"TARGET_LOST" = ("setStateTo: WAIT_FOR_PLAYER");
		UPDATE = ();
};
When I get within range the ship sets the player as the target, and from the log I can see:

Code: Select all

[ai.takeAction]: Feudal Knight (Tibedied) 209 to take action sendScriptMessage: checkDistance
  [ai.message.receive]: AI feudal-challenger2AI.plist for Feudal Knight (Tibedied) 209 in state 'WAIT_FOR_PLAYER' receives message 'FOUND_PLAYER'
But despite that the ship remains in the WAIT_FOR_PLAYER state. I can't see what I'm doing wrong - thoughts anyone?

Posted: Mon Apr 06, 2009 7:05 pm
by Thargoid
reactToAIMessage is to set a condition within a state (e.g. "ENERGY_LOW" or "INCOMING_MISSILE" in your AI above).

The command you want is this.ship.AIState = "FOUND_PLAYER" as you want to switch to a new state, not select a condition within the one you're currently in (WAIT_FOR_PLAYER in this case).

Or alternatively you could add something like "PLAYER_FOUND" = ("setStateTo: FOUND_PLAYER"); in your WAIT_FOR_PLAYER state, and then use this.ship.reactToAIMessage("PLAYER_FOUND");

If you want to see how the script and AI talk to one another, have a look in Captured Thargons for an example or six.

Posted: Tue May 05, 2009 12:12 pm
by Ramirez
Hey all. Just clocking in to let you know that despite appearances this project isn't dead - I've just been sidetracked by various RL shenanigans, plus I've been hard at work achieving world domination in Empire: Total War.

So where are we? I've relocated the Royal Courts down onto the planet surface using Thargoid's Planetfall addon, and I've added the Royal Hunting Lodges where the challenges take place. The challenge system is pretty much done, though I'm still tweaking the AI to make opponents a bit more aggressive. The bookmaking calculations I'm using result in fairly low odds, but I figure that even doubling your money in a single challenge is a better result than you'd get through normal trading.

I was going to move onto tournaments but I think I'll go back and clean up everything I've done so far. I also want to take a look at the photo mssions idea as that should be relatively easy to set up and integrate into the exisitng mission script. In the meantime I'll try to post a further WIP package for people to have a look at.

Posted: Sun May 17, 2009 12:29 pm
by Ramirez
OK, here's another WIP package that covers missions, promotions and challenges. There's plenty of tweaking and optimising still to do but the basics are there.

Feudal States WIP v0.2

Help!!

Posted: Mon Aug 10, 2009 7:05 pm
by Ramirez
Hi again - another long absence, this time a combination of surprisingly good weather, some much-needed home improvements and the release of ARMA2!

Not much progress on the OXP, unfortunately. I've hit a stumbling block with the decal shaders - I know Ahruman did a detailed post on it but I still don't understand how to get them to work. Are there any example OXPs out there which just do decals on their own without things like normal maps and engine glows? I've looked at some of the recent models but it's really hard to sort one shader effect from another.

Also I was getting a bit jaded with the OXP after seeing some of the great model work in the screenshots thread. I've pretty much reached my limit in terms of modelling/texturing and could do with some help in making the 3 or 4 basic feudal ship models really look the part. If anyone's up for the challenge please reply to the post or feel free to send me a PM.

Finally thanks to all of you who've helped out so far - there's some really nice bits of script in here that would be a shame to waste!

Oh, here's a quick glimpse of the readme - inspired by Aegidian's Oolite splash screen:

Image

Posted: Tue Aug 11, 2009 9:15 am
by DaddyHoggy
Welcome back R! ArmaA2 - well, well, that explains a lot... :wink: (we use VBS2 here at work - based on the original ArmA engine)

I can't model for toffee so count me out, but I'd like to say I like the front cover of your readme! Very, erm, Feudal!

Posted: Tue Aug 11, 2009 9:40 am
by Griff
@ Ramirez, i can chop all the glows & stuff out the shader i've been using recently leaving just the decal and the base diffuse texture map, do you want a version with or without normalmapping?

edit: i had the normalmapped shader handy so i cobbled this together in my coffee break. This will take your 'diffuse' texturemap (the usual skin texture map), a normal map and a decal image and mix them together. this example expects the decal image to be made up of 4 smaller decal images arranged in a horizontal row, the uDecalSelect number then picks a decal from the image and the 'diffuseColor()' function in the shader mixes it into the diffuse texture. the fragment shader checks for Simple shader mode and ignores the decal code if it is switched on

vertex shader:

Code: Select all

#define OO_TANGENT_ATTR 1  // <---- Define OO_TANGENT_ATTR to 1 so that Oolite gives correct tangent data to shader. 
#ifdef OO_TANGENT_ATTR 
attribute vec3      tangent; 
#else 
const vec3         tangent = vec3(1.0, 0.0, 0.0); 
#endif

varying vec2         vTexCoord;
varying vec3         vEyeVector;   // These are all in tangent space
varying vec3         vLight0Vector;
varying vec3         vLight1Vector;


void main()
{
   // Build tangent basis
   vec3 n = normalize(gl_NormalMatrix * gl_Normal);
   vec3 t = normalize(gl_NormalMatrix *tangent);
   vec3 b = cross(n, t);
   mat3 TBN = mat3(t, b, n);
   
   vec3 eyeVector = -vec3(gl_ModelViewMatrix * gl_Vertex);
   vEyeVector = eyeVector * TBN;
   
#ifdef OO_LIGHT_0_FIX
   vec3 light0Vector = gl_LightSource[0].position.xyz + eyeVector;
   vLight0Vector = light0Vector * TBN;
#endif
   vec3 light1Vector = gl_LightSource[1].position.xyz + eyeVector;
   vLight1Vector = light1Vector * TBN;
   vTexCoord = gl_MultiTexCoord0.st;
   gl_Position = ftransform();

// gl_TexCoord used for the decal function in the fragment
   gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; 
}
Fragment Shader

Code: Select all

uniform sampler2D    uColorMap;
uniform sampler2D    uNormalMap;
uniform sampler2D    uDecalMap;


varying vec2         vTexCoord;
varying vec3         vEyeVector;   // These are all in tangent space
varying vec3         vLight0Vector;
varying vec3         vLight1Vector;

// Constants
const float KspecExponent = 12.0;
const float kDecalSize = 6.1;  // Sets the Decal Size - smaller number is bigger
const float kDecalS = 0.61;     // Decal S (U) Co-oord - Tweak to fit your model
const float kDecalT = 0.15;    // Decal T (V) Co-oord - Tweak to fit your model
const float kDecalCount = 4.0; //Match the number of Decals in your texture

// Uniforms from Oolite
   uniform float  uDecalSelect; 

   /*  uDecalSelect is used to decide which decal to select, it works like this - our decal image is split into a  'kDecalCount' number of columns
. In this example kDecalCount = 4.0   so our 128x512 decal image 
will be split into 4 columns of 128x128 pixels.
By giving uDecalSelect a value between 0.0 and 0.24 this will select decal 1 from the image, 0.25-0.49 will select decal 2, 0.50-0.74 is decal 3 and  0.74-1.0 we be decal 4 */

void Light(in vec3 lightVector, in vec3 normal, in vec4 lightColor, in vec3 eyeVector, 
           in float KspecExponent, inout vec4 totalDiffuse, inout vec4 totalSpecular)
{
   lightVector = normalize(lightVector);
   vec3 reflection = normalize(-reflect(lightVector, normal));
   
   totalDiffuse += gl_FrontMaterial.diffuse * lightColor * max(dot(normal, lightVector), 0.0);
   totalSpecular += lightColor * pow(max(dot(reflection, eyeVector), 0.0), KspecExponent);
}


#define LIGHT(idx, vector) Light(vector, normal, gl_LightSource[idx].diffuse, eyeVector, KspecExponent, diffuse, specular)

#ifndef OO_REDUCED_COMPLEXITY 
// function to read in the colour map then scale and position the decal map onto it. 
vec4 diffuseColor() 
{ 
   vec2 baseTexCoord = gl_TexCoord[0].st; 
    
// Calculate decal texture co-ordinates. 
   vec2 decalTexCoord = baseTexCoord; 
   decalTexCoord -= vec2(kDecalS, kDecalT - (0.5 / kDecalSize)); 
   decalTexCoord *= vec2(kDecalSize / kDecalCount, kDecalSize); 
    
// Select the desired decal from the set. 
   float offset = floor(uDecalSelect * kDecalCount) / kDecalCount; 
   decalTexCoord.s += offset; 
    
// Get texture values. 
   vec4 baseTex = texture2D(uColorMap, baseTexCoord); 
   vec4 decalTex = texture2D(uDecalMap, decalTexCoord); 
        decalTex *= step(offset, decalTexCoord.s) * 
                    step(0.0, decalTexCoord.t) * 
                    step(-1.0 / kDecalCount - offset, -decalTexCoord.s) * 
                    step(-1.0, -decalTexCoord.t); 
    
// Composite decal over base. 
   return baseTex + decalTex; 
}      
#endif  

void main()
{
   vec3 eyeVector = normalize(vEyeVector);
   vec2 texCoord = vTexCoord;
   
   vec3 normal = normalize( texture2D(uNormalMap, texCoord).xyz - 0.5);
   normal = normalize(normal);

   vec4 colorMap = texture2D(uColorMap, texCoord);
   vec4 diffuse = vec4(0.0), specular = vec4(0);

   float specIntensity = 1.0;
 
#ifdef OO_LIGHT_0_FIX
   LIGHT(0, normalize(vLight0Vector));
#endif
   LIGHT(1, normalize(vLight1Vector));
   diffuse += gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
   
// Calculate the lighting for full shader mode
   #ifndef OO_REDUCED_COMPLEXITY 
   vec4 color = diffuse * diffuseColor() + specular * specIntensity;
   #endif
   
// Calculate the lighting for simple shader mode
   #ifdef OO_REDUCED_COMPLEXITY    
   vec4 color = diffuse * colorMap + specular * specIntensity;
   #endif

   gl_FragColor = color;
}
shipdata.plist shaders definition

Code: Select all

	shaders = 
		{ 
            "your_diffuse_texture_map.png" = 
			{ 
                vertex_shader = "the_vertex_shader.vertex"; 
                fragment_shader = "the_fragment_shader.fragment"; 
                textures = 
						(
							"your_diffuse_texture_map.png", 
							"your_normalmap_texture.png",
							{name = "your_decal_texture"; repeat_s = "yes";}
						);
				uniforms =
						{
						uColorMap = { type = texture; value = 0; };
						uNormalMap = { type = texture; value = 1; };
						uDecalMap = { type = texture; value = 2; };	
						uDecalSelect = { type = "float"; value = 0.3; };			
						}; 	
			}; 
		};
In the shipdata.plist example above, you can see uDecalSelect is being given the value 0.3, so it's the 2nd decal that is going to get used. to have Oolite choose random decals everytime it spawns a ship use

Code: Select all

 uDecalSelect = "entityPersonality"; 


These are the lines in the fragment shader that control the size and placement of your decal
const float kDecalSize = 6.1; // Sets the Decal Size - smaller number is bigger
const float kDecalS = 0.61; // Decal S (U) Co-oord - Tweak to fit your model
const float kDecalT = 0.15; // Decal T (V) Co-oord - Tweak to fit your model

This line needs to match how many decals your are placing in a horizontal row in your decal, have a look at ahrumans post where he explains the shader for an example of a decal image

const float kDecalCount = 4.0; //Match the number of Decals in your texture

other important lines you might need to tweak:
const float KspecExponent = 12.0; - the glossyness of the surface (highlight size basically - higher numbers make the surface more plastic/wet looking

float specIntensity = 1.0; - the shinyness of the surface, higher numbers make brighter highlights, you can also use numbers lower than 1.0 (eg float

specIntensity = 0.5; or float specIntensity = 0.005;

Make sure you change all the referenced png's and shader filenames in the shipdata.plist example above to match what your textures and shader files are called.

Posted: Tue Aug 11, 2009 11:36 am
by DaddyHoggy
Griff wrote:
i had the normalmapped shader handy so i cobbled this together in my coffee break.
Show off! :wink: :)

Posted: Tue Aug 11, 2009 3:20 pm
by Griff
:D It was just a quick cut and paste job!
I've found a no-normal map shader and cut all the glowy stuff out to leave only the decal stuff. This shader just needs a colour diffuse map for the ship and a strip of decal images in a horizontal row - (the shader example below is looking for 4 decals exactly the same as ahruman demonstrates in his post when he wrote the shader example)

Decal Shader, no normalmap version

vertex shader

Code: Select all

varying vec3         v_normal;      // Surface normal
varying vec3         v_pos;      // Vertex/fragment position in eye space

void main()
{
   v_normal = normalize(gl_NormalMatrix * gl_Normal);
   v_pos = vec3(gl_ModelViewMatrix * gl_Vertex);
   
   gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
Fragment Shader:

Code: Select all

// Texture Information from Oolite.
   uniform sampler2D      tex0; // Difuse and Illumination map
   uniform sampler2D      tex1; // Decal Texture 
  
   
// Uniforms from Oolite
  
   uniform float  uDecalSelect; // used to decide which decal to select
 
 // Information from vertex shader.
   varying vec3         v_normal;   // Surface normal
   varying vec3         v_pos;      // Vertex/fragment position in eye space

   // Constants
   const float specExponent = 5.0;
   const float kDecalSize = 8.0;  // Sets the Decal Size - smaller number is bigger
   const float kDecalS = 0.50;
   const float kDecalT = 0.15;
   const float kDecalCount = 4.0; //Match the number of Decals in your texture

// the diffuseColor function takes your diffuse map and your decal map, selects, 
// scales & positions the decal image then adds it into the diffuse texturemap

vec4 diffuseColor() 
{ 
   vec2 baseTexCoord = gl_TexCoord[0].st; 
    
// Calculate decal texture co-ordinates. 
   vec2 decalTexCoord = baseTexCoord; 
   decalTexCoord -= vec2(kDecalS, kDecalT - (0.5 / kDecalSize)); 
   decalTexCoord *= vec2(kDecalSize / kDecalCount, kDecalSize); 
    
// Select the desired decal from the set. 
   float offset = floor(uDecalSelect * kDecalCount) / kDecalCount; 
   decalTexCoord.s += offset; 
    
// Get texture values. 
   vec4 baseTex = texture2D(tex0, baseTexCoord); 
   vec4 decalTex = texture2D(tex1, decalTexCoord); 
        decalTex *= step(offset, decalTexCoord.s) * 
                    step(0.0, decalTexCoord.t) * 
                    step(-1.0 / kDecalCount - offset, -decalTexCoord.s) * 
                    step(-1.0, -decalTexCoord.t); 
    
// Composite decal over base. 
   return baseTex + decalTex; 
}      
   
// Calculate the contribution of a single light. Ought to be a function, but OS X's GLSlang implementation isn't sufficiently clever.
   #define LIGHT(idx) \
        { \
           vec3 lightVector   = normalize(gl_LightSource[idx].position.xyz); \
           vec3 reflection   = normalize(-reflect(lightVector, v_normal)); \
           diffuse += gl_FrontMaterial.diffuse * gl_LightSource[idx].diffuse * max(dot(v_normal, lightVector), 0.0); \
           specular += gl_LightSource[idx].diffuse * pow(max(dot(reflection, eyeVector), 0.0), specExponent); \
        }
   
   void main(void)
   {
   vec4 diffuse = vec4(0.0), specular = vec4(0.0);
   vec3 eyeVector = normalize(-v_pos);
 
// Load texture data
   vec2 texCoord = gl_TexCoord[0].st;
   vec4 colorMap = texture2D(tex0, texCoord);
   
// calculate specular effects
   float specIntensity = 1.0;
   
/*   Light 0 is the "showroom" light, used in the demo screen and shipyard.
     Light 1 is the sun.
*/
   #ifdef OO_LIGHT_0_FIX
   LIGHT(0);
   #endif
 
   LIGHT(1);
   diffuse += gl_FrontMaterial.ambient * gl_LightModel.ambient;
   
// Calculate the lighting for full shader mode
   #ifndef OO_REDUCED_COMPLEXITY 
   vec4 color = diffuse * diffuseColor() + specular * specIntensity;
   #endif

// Calculate the lighting for simple shader mode
   #ifdef OO_REDUCED_COMPLEXITY    
   vec4 color = diffuse * colorMap + specular * specIntensity;
   #endif
 
#ifndef OO_REDUCED_COMPLEXITY  

// Output final color
   gl_FragColor = vec4(color.rgb, 1.0);
   }
Shipdata.plist shaders entry

Code: Select all

	shaders = 
		{ 
            "your_diffuse_texturemap.png" = 
			{ 
                vertex_shader = "your_vertex_shader.vertex"; 
                fragment_shader = "your_fragment_shader.fragment"; 
		textures = (
					"your_diffuse_texturemap.png", 
					{name = "your_decal_texturemap.png"; repeat_s = "yes";}
					);
				uniforms =
						{
						
						uDecalSelect = { type = "float"; value = 0.3; };			
						}; 	
			}; 
		};
I'll copy the stuff from the post above about what settings you might need to tweak
In the shipdata.plist example above, you can see uDecalSelect is being given the value 0.3, so it's the 2nd decal that is going to get used. to have Oolite choose random decals everytime it spawns a ship use
Code:
uDecalSelect = "entityPersonality";


These are the lines in the fragment shader that control the size and placement of your decal
const float kDecalSize = 6.1; // Sets the Decal Size - smaller number is bigger
const float kDecalS = 0.61; // Decal S (U) Co-oord - Tweak to fit your model
const float kDecalT = 0.15; // Decal T (V) Co-oord - Tweak to fit your model

This line needs to match how many decals your are placing in a horizontal row in your decal, have a look at ahrumans post where he explains the shader for an example of a decal image

const float kDecalCount = 4.0; //Match the number of Decals in your texture

other important lines you might need to tweak:
const float KspecExponent = 12.0; - the glossyness of the surface (highlight size basically - higher numbers make the surface more plastic/wet looking

float specIntensity = 1.0; - the shinyness of the surface, higher numbers make brighter highlights, you can also use numbers lower than 1.0 (eg float

specIntensity = 0.5; or float specIntensity = 0.005;

Make sure you change all the referenced png's and shader filenames in the shipdata.plist example above to match what your textures and shader files are called.

Posted: Tue Aug 11, 2009 6:30 pm
by Tivva
PICS please Griff
All that gobble-de-gook gibberish is lost on us mere mortals without pics.
:lol:

Posted: Tue Aug 11, 2009 7:21 pm
by Ramirez
That's excellent, Griff! Just tried it and I've managed to get a coat of arms successfully pasted onto the bottom of a ship.

I've obviously got lots of tweaking to do but this should get me on the right track.

Posted: Tue Aug 11, 2009 9:13 pm
by Rustybolts
I hope you complete this oxp it looks good, looking forward to running it. One question! Is it all based in galaxy one or is that just on the demo download?

Posted: Wed Aug 12, 2009 11:36 am
by Ramirez
It's just one galaxy at the moment so as to keep things manageable. The long term plan is to extend it to the other galaxies with feudal systems, so I'm trying not to hard-code things too much.

Posted: Thu Aug 13, 2009 2:31 pm
by Ramirez
I may be running before I can walk here, but what about applying the same decal more than once, with different orientations?

I thought I'd try and see if I could apply just the same decal with different position and sizing, and was surprised to see that it worked. I created two sets of constants, one for each decal:

Code: Select all

 // Constants 
   const float specExponent = 5.0; // constants for both decals
   const float kDecal1Count = 4.0; 
   const float kDecal1Size = 8.0;  // data for decal 1
   const float kDecal1S = 0.50; 
   const float kDecal1T = 0.15; 

   const float kDecal2Size = 12.0;  // data for decal 2
   const float kDecal2S = 0.50; 
   const float kDecal2T = 0.85; 
Then I followed that renaming through until I ended up with the composite line

Code: Select all

return baseTex + decal1Tex + decal2Tex;
All that seemed to work, so I then used Ahruman's example to try rotating one of the decals. I added another constant

Code: Select all

const float kOrientation1 = 0.7853981634; // pi / 4 
then added in the bits and pieces for the rotation

Code: Select all

float s = sin(kOrientation1); 
    float c = cos(kOrientation1); 
    decal1TexCoord *= mat2(c, s, -s, c); 
This also seemd to work; the first decal was rotated while the other one stayed in position. The problem was in applying the second rotation; I thought I'd be able to create two sets of float s and float c, one for each decal (e.g. with float 1s = sin(kOrientation1)), however I tried this and I got a syntax error (couldn't find any code to compile). Not surprising as I'm just copying and pasting code without knowing exactly how it works!

Is what I'm trying to do actually possible, given the correct functions and syntax? Also are there any texture memory issues or anything I should be worrying about with this approach?

(ooh, I've just noticed my Elite forum status - only took 3 and a half years!)

Posted: Thu Aug 13, 2009 3:24 pm
by Griff
could you post your entire shader code please Ramirez? i'll copy it into Rendermonkey and hopefully it should explain what the syntax error is.
If we can get multiple copies of decals working it would be rather cool!