in-game radii view for triggers

Discussions about Coding and Scripting
User avatar
Feralidragon
Godlike
Posts: 5489
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: in-game radii view for triggers

Post by Feralidragon »

You can see the code for the way it's calculated in the source of my gore mod, which you can get from here:
http://www.mediafire.com/download/7iexi ... Eb_SRC.rar
namely you should look for the class NWCordSegm_UGSSE.

The class is very simple, and should give you an idea of how the calculations are made.

But to simplify things a bit more for you: you have to define the height your cylinder will have in the 2nd frame, since that's the maximum height your cylinder will possibly have and the base height at Drawscale=1.0, so let's call it BaseHeight.
From there, you also need to define the base radius of the cylinder: BaseRadius.

So the code would go as something like this (if no mistakes were made):

Code: Select all

var float BaseRadius, BaseHeight;

function SetScale(float Radius, float Height)
{
	DrawScale = Radius / BaseRadius;
	if (DrawScale > 0) {
		AnimFrame = Min(Height / BaseHeight * 0.5 / DrawScale, 0.5);
	}
}

defaultproperties
{
	Mesh=<cylinder mesh here>
	AnimSequence=<animation sequence here>
	BaseRadius=<base radius here>
	BaseHeight=<base height here>
}
As for how to do the cylinder mesh itself like this, it should be relatively simple either with Milkshape3D (which has a native exporter to vertex meshes), or Blender (which has an exporter recently developed by the community, I don't remember whom, but a search in OldUnreal or UnrealSP should yield results).
I have none of these installed at the moment, nor the time to rediscover these tools and set this up, but perhaps someone else could make this simple mesh for you the way I described it. :)

At Radius=0 the mesh wouldn't be visible at all, so if you want to at least see a thin point or a line, you can do something like:
DrawScale = Max(Radius, 0.25) / BaseRadius;
and remove the DrawScale > 0 condition, which is only there to prevent division by zero, with the 0.25 value being any value you see that works best for you, as the minimum radius to use.
Chris
Experienced
Posts: 134
Joined: Mon Nov 24, 2014 9:27 am

Re: in-game radii view for triggers

Post by Chris »

In that case, you wouldn't have to bother with a texture, you can just draw the mesh as a wireframe right away.
User avatar
Feralidragon
Godlike
Posts: 5489
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: in-game radii view for triggers

Post by Feralidragon »

That's correct, however unfortunately you cannot control the wireframe color afaik.
Could be a feature enhancement in v469: making it so that the Canvas DrawColor set the wireframe color.
User avatar
Gustavo6046
Godlike
Posts: 1462
Joined: Mon Jun 01, 2015 7:08 pm
Personal rank: Resident Wallaby
Location: Porto Alegre, Brazil
Contact:

Re: in-game radii view for triggers

Post by Gustavo6046 »

Feralidragon wrote: Wed Nov 27, 2019 9:58 pm making it so that the Canvas DrawColor set the wireframe color
I'd rather make a separate attribute, Canvas.WireframeColor, and set that to the current color by default (also right before every PostRender call), in order to be compatible with code that doesn't set DrawColor before drawing the wireframe.
"Everyone is an idea man. Everybody thinks they have a revolutionary new game concept that no one else has ever thought of. Having cool ideas will rarely get you anywhere in the games industry. You have to be able to implement your ideas or provide some useful skill. Never join a project whose idea man or leader has no obvious development skills. Never join a project that only has a web designer. You have your own ideas. Focus on them carefully and in small chunks and you will be able to develop cool projects."

Weapon of Destruction
OwYeaW
Experienced
Posts: 81
Joined: Fri Jan 09, 2015 4:24 pm

Re: in-game radii view for triggers

Post by OwYeaW »

thank you Feralidragon for the explanation and example

it took me a while to get the mesh properly imported in UT, i kind of spent my whole night on this lol
but eventually i got something now: https://streamable.com/xzq4a

didnt do uv wrapping yet, im using blender for the first time (the .u3d export tool seems to be broken btw)
the translucent textures are just placeholders, if anyone has some nice ideas for textures let me know
i probably want at least 3 different textures to distinguish Trigger, Kicker and TriggeredDeath from eachother

in the video i show a bug about the mesh going invisible when looking at it in certain angles (might have been because it was behind the mover doors?)
and the kind of expected "bug" when being inside the mesh, i wonder if there is some way to make it visible when being inside
making a hollow mesh? or is it possible to have 2 sided surfaces?

any recommendations are welcome


EDIT: yes 2sided works great: https://streamable.com/ldv25
just need to fix that bug about the mesh going invisible at certain view angles, i know theres a fix on this somewhere
User avatar
Feralidragon
Godlike
Posts: 5489
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: in-game radii view for triggers

Post by Feralidragon »

The mesh goes invisible when the center of the actor (the actor Location) is not in view at certain angles (when it's behind you for example).

It's not exactly a bug, it was an intended engine optimization so that meshes behind you wouldn't get rendered, which for the normal game it works since meshes were not meant to ever be that big, but once you go for something like that, that kind of problem occurs.

Unreal 227 "fixes" this by giving you an option, in the form of a new actor boolean property, to force the mesh to render regardless of where it's located relative to you and your view.
In UT99 however, unfortunately you do not have this option.

However, I also have developed a "fix" for that one, for UT99, since in NW3 I wanted to have "forcefields", and if you were inside one, at certain angles it would disappear, which was a big problem for me.
So what I ended up coming up with was fairly simple: since the mesh disappears when its actor location is behind you, all you have to do is ensure the actor (with the mesh) is always on front of you, at all times (every tick).

From there, to keep the mesh visibly where it's supposed to be, you set the PrePivot in such way that the mesh is rendered in the location you actually want it to be rendered at.
PrePivot establishes where the mesh is rendered, as an offset from the actor's location, or to put it in more technical terms: the real rendering location of any mesh is Location + PrePivot, which is a quite neat feature of the engine, which I used and abused for other things other than this kind of fix.

So, you have to do something like this (simplified version):

Code: Select all

var vector RealLocation;
var float RenderDistance;

function update(vector ViewLocation, rotator ViewRotation)
{
	SetLocation(ViewLocation + vector(ViewRotation) * RenderDistance); //set the actor on front of the player, at a distance set by RenderDistance
	PrePivot = RealLocation - Location;
}

defaultproperties
{
	RenderDistance=128.000000
}
This works fairly well most of the time, however due to the order of updates in a tick (when each actor is updated), which is decided by the order each actor was spawned (at least pre-v469, not sure if it will remain like this with the incoming fixes and optimizations), if the ViewLocation corresponds to another actor other than the PlayerPawn itself (such as a guided Redeemer missile for example), since those actors are generally updated later by being spawned afterwards, the ViewLocation and ViewRotation you use in those cases is highly likely to be outdated by the time the tick finishes, creating a flickering or disappearing effect again if the actor is set to be too close in front of you or if the actor is rotated quickly enough.

For normal cases, such as yours, setting a RenderDistance to just far away enough, should suffice for the time being.
But if you want to check what I did to solve that problem, as well including some other features (such as only do this processing when you're "inside" the actor, to keep the optimization working when you're not), you can check the NaliFullMeshFX class from NW3, namely from the NWCoreVIII package (all my sources are here: viewtopic.php?t=5638 ).
OwYeaW
Experienced
Posts: 81
Joined: Fri Jan 09, 2015 4:24 pm

Re: in-game radii view for triggers

Post by OwYeaW »

how are these calculations done to check if an Actor is behind you or not? maybe i can hack into that?

EDIT:

good stuff FeraliDragon, i got it working, its also working properly online when moving: https://streamable.com/hisxl

this is the Actor class:

Code: Select all

//=============================================================================
// BT_TriggerCollision
//=============================================================================
class BT_TriggerCollision expands Actor;

#exec MESH IMPORT MESH=BT_TriggerCylinder ANIVFILE=Models\BT_TriggerCylinder_a.3d DATAFILE=Models\BT_TriggerCylinder_d.3d X=0 Y=0 Z=0 LODSTYLE=10 LODFRAME=0 
#exec MESH ORIGIN MESH=BT_TriggerCylinder X=0 Y=0 Z=0 YAW=0 PITCH=0 ROLL=0

#exec MESH SEQUENCE MESH=BT_TriggerCylinder SEQ=All		STARTFRAME=0 NUMFRAMES=2
#exec MESH SEQUENCE MESH=BT_TriggerCylinder SEQ=Still	STARTFRAME=0 NUMFRAMES=1 RATE=1.0

#exec MESHMAP NEW			MESHMAP=BT_TriggerCylinder	MESH=BT_TriggerCylinder
#exec MESHMAP SCALE			MESHMAP=BT_TriggerCylinder	X=1 Y=1 Z=2000

var	Triggers localTrigger;
var PlayerPawn LocalPlayer;
var float RadiusView;
var float RenderDistance;
var vector CentralLoc;

function PostBeginPlay()
{
	if(Triggers(Owner) != None)
	{
		localTrigger = Triggers(Owner);
		RadiusView = localTrigger.CollisionRadius*1.5;
		DrawScale = FMax(localTrigger.CollisionRadius/64, 0.1);
		AnimFrame = FMax(localTrigger.CollisionHeight, 1)/128000/DrawScale;

		//	A skin for each different type of Trigger
		if(Trigger(localTrigger) != None)
			Skin = Texture'FireEffect10';
		else if(Kicker(localTrigger) != None)
			Skin = Texture'FireEffect26';

		Super.PostBeginPlay();
	}
	else
		Destroy();
}

function Tick(float Delta)
{
	local float viewDist;
	local vector camLoc;
	local rotator camRot;
	local Actor camActor;

	//	Make sure that we follow the movements of the Trigger in case its moving
	if(localTrigger.Location != CentralLoc)
		CentralLoc = localTrigger.Location;

	//	Calculate new location and prepivot and make the mesh always visible
	LocalPlayer.PlayerCalcView(camActor, camLoc, camRot);

	viewDist = VSize(camLoc - CentralLoc);
	if(viewDist <= RadiusView)
	{
		SetLocation(camLoc + vector(camRot) * RenderDistance); //set the actor on front of the player, at a distance set by RenderDistance
		PrePivot = CentralLoc - Location;
	}
	else if(Location != CentralLoc)
	{
		SetLocation(CentralLoc);
		PrePivot = vect(0,0,0);
	}
}

defaultproperties
{
	RenderDistance=128
	AnimSequence=All
	Mesh=LodMesh'BT_TriggerCylinder'
	Style=STY_Translucent
	DrawType=DT_Mesh
	bUnlit=true
}
i have been struggling with Blender for hours again tonight, eventually i found out that the program im using to convert .obj (2 frames) to .u3d called U3D is messing up the UV Wrapping
the UV Wrapping seems to be fine if i basically dont touch it inside Blender, as soon as i use scaling, moving, rotating, even mirror on any face; the UV Wrapping eventually gets messed up when converting it in U3D
maybe im missing something in Blender? like; any changes i do after i did "Unwrap" on any face will get it eventually messed up, so maybe im missing some "save UV Map" step?
although when i look at the exported .obj in any obj viewer; the UV Wrapping seems perfect

i will show the UV Map below, the top and bottom turn out fine after the conversion, the 32 side faces dont
Image

also the addon for Blender to export to .u3d directly breaks my cylinder mesh and gives it some weird shape
OwYeaW
Experienced
Posts: 81
Joined: Fri Jan 09, 2015 4:24 pm

Re: in-game radii view for triggers

Post by OwYeaW »

i just tested the functionality in several maps now and got huge fps drops when theres multiple cylinders spawned
the fps drops seem to happen because of the cylinder being in an animation
the fps drops are gone when i let the cylinders be spawned without an AnimSequence or AnimSequence=Still

is there a way to kind of "freeze" the Actor in its animation? the actor should still be movable
User avatar
Chamberly
Godlike
Posts: 1963
Joined: Sat Sep 17, 2011 4:32 pm
Personal rank: Dame. Vandora
Location: TN, USA
Contact:

Re: in-game radii view for triggers

Post by Chamberly »

Well with some codes to detect something to freeze and then another code to detect something to animate would be an idea.

I'm thinking if a player touch Trigger32, then the box would freeze until after certain amount of time or until a TriggerHit11 was shot by a gun. That sounds close enough?
Image
Image
Image Edit: Why does my sig not work anymore?
OwYeaW
Experienced
Posts: 81
Joined: Fri Jan 09, 2015 4:24 pm

Re: in-game radii view for triggers

Post by OwYeaW »

Chamberly wrote: Mon Dec 02, 2019 1:04 pm Well with some codes to detect something to freeze and then another code to detect something to animate would be an idea.

I'm thinking if a player touch Trigger32, then the box would freeze until after certain amount of time or until a TriggerHit11 was shot by a gun. That sounds close enough?
im sorry but both sentences dont make sense to me at all

"some codes to detect something to freeze"?
i can detect anything i want, but that doesnt change anything
User avatar
Feralidragon
Godlike
Posts: 5489
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: in-game radii view for triggers

Post by Feralidragon »

Calculation: I don't know how the engine calculates this exactly, since it's not exposed in Unrealscript, but the most simple way to do it is with a dot product between the normal of the vector from the player view location to the actor location, with the vector representing the view rotation of the player, something like:
DotProduct = Normal(A.Location - ViewLocation) dot vector(ViewRotation);
with the simplest check being if the DotProduct is less than zero, although the engine's condition is likely to be less than -0.5 or lower, since at -1.0 the location would be behind your view, at 0.0 it would be on either of the sides of your view (think 90º in any direction from your view), and 1.0 would mean it would be directly in the center of your view.

The dot product is the cosine of the angle between 2 vectors, so this means you can use this to easily check if a location is within your FOV, and it's likely that the engine makes the mesh disappear within a small angle at the back of your view using this tyoe of calculation, but only the native gurus can reliably answer to this.


UV/export: do not forget what I mentioned earlier, concerning a vertex mesh bounding box.
Your mesh has to be within a bounding box of 256x256x256 (if I remember correctly), meaning that none of the vertices can be farther than 128 units from the mesh origin in either axis.
If you go beyond this bounding box, the mesh will be all messed up upon export, since the vertex coordinates outside of this bounding box will overflow.


Lag/animation: I use and abuse the AnimFrame property in my gore mod, and I am able to spawn several hundreds without any issue other than rendering lag, only when they are in view.
So that couldn't be it, at least not directly, there's likely something else at play together with the AnimFrame manipulation there.

One thing to keep in mind is that AnimSequence and AnimFrame only set a state in the mesh, simply related to where each vertex is located, and when you just set these directly without calling any animation functions, you're not really running an animation, you're just setting an animation state, a key frame if you will, so there's no reason that I can remember at least for something like that to cause any sort of lag.

A test you can do to either prove or disprove this, is to keep the code itself commented out, but setting the default values of AnimSequence and AnimFrame to a value that could be calculated by the code, so you can check if it's code or if it's the state of the mesh that is making the engine go bananas.

Having that said, you only need to set them once, so if there was any sort of lag, it would be momentarily during the first moment when you spawn them, but then again, I don't think there's any reason for that lag.

Furthermore, you don't (and maybe even shouldn't) use the triggers themselves directly to set this up, and maybe that could be the source of the lag somehow.
What you should do is to actually have a TriggerCylinder class for example, extending from Actor, and then spawn one for each trigger in the client only (multiplayer-wise), and maybe let them just update themselves.

Also, when using the canvas, you can draw the same actor (DrawActor) multiple times with different attributes (different animations, textures, mesh, etc), and it generally works.
If the actor is being actively animated (think TweenAnim, PlayAnim, those sorts of calls), some weird behavior will be noticed in the multiple renders, but as long as the actor is more "static" and not doing or changing by itself, it should render without a problem, so you have multiple approaches here you can test and choose.
OwYeaW
Experienced
Posts: 81
Joined: Fri Jan 09, 2015 4:24 pm

Re: in-game radii view for triggers

Post by OwYeaW »

so i found out the meshses being so tall is the cause of massive fps drops

currently not sure how to work around this but im trying :s
User avatar
Feralidragon
Godlike
Posts: 5489
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: in-game radii view for triggers

Post by Feralidragon »

Probably the first step to is test multiple heights and check when and how much it starts to impact the fps (although I don't know why it would impact the fps either, maybe because of them being rendered as translucent?).

The second step would be asking yourself if you really need them that tall, and if you cannot just cap them (at some point I don't think it would be useful for your particular purpose).

If you really want the full height, with no cap, instead of spawning just 1 cylinder per trigger, you can spawn multiple but with different heights, and just stack them together, and precisely so, so all sides connect nicely and seamlessly.
You can even go further and have 4 cylinder models: a normal one, one without the lower circle, another without the upper circle and one without both (so you don't get flat circles in the middle of stack).

Although, in this last solution, if the impact on the fps has to do with how the cylinders are being rendered (translucent) instead of their size, you really cannot get around that, stacking won't help.
OwYeaW
Experienced
Posts: 81
Joined: Fri Jan 09, 2015 4:24 pm

Re: in-game radii view for triggers

Post by OwYeaW »

well, i can definitely confirm that when spawning the meshes with a higher (2nd frame, fully extended) height can do big impact on fps
even if eventually the meshes are drawn visually the same

currently trying to find a reasonable Z scale considering functionality versus fps
basically finding reasonable fps and enough size to cover most of the possible collision Height/Width ratios

if i cant find a reasonable scale i would probably have to try spawn multiple meshes, which is getting really retarded when looking how "hard" it is to just spawn some simple meshes

also i changed the cylinder mesh from 32 sides to 16 sides, cutting more than half of the polygons
but as i already pointed out, seems like the amount of polygons have totally nothing to do with the massive fps drops im getting
User avatar
Feralidragon
Godlike
Posts: 5489
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: in-game radii view for triggers

Post by Feralidragon »

But did you try to check how the fps behaves if you render the cylinders in an opaque fashion (Style = STY_Normal)?
Just to rule out if the fps drop isn't the area that translucent surfaces cover around the map.

The number of polys impact rendering performance, but changing from 16 to 32 sides yields barely any difference, since the cylinder will just go from 64 triangles to 96 (+32 triangles), which is almost nothing, especially if you use LOD properly to morph polys away at distance.
Unless you have a ton of them in view, something in the order of hundreds, at that point the 32 polys reduction is a 33% reduction on rendering workload, and may make a difference.
Post Reply