Jump to content
The Dark Mod Forums

[2.10] X-Rays


Dragofer

Recommended Posts

Can this also been used with a mirror, so that you can show things in a mirror behind the player that is not visible when the player turns around (for example a ghost)?

Edit: I tried getting this to work by placing a mirror behind the X-ray screen. This does not seem to work properly, or I am doing something wrong.

A possible alternative way might be placing a camera pointed toward the players front side through an x-ray screen and then put a monitor on the other side. Just thinking out loud..

Edited by datiswous
  • Like 1
Link to comment
Share on other sites

14 hours ago, datiswous said:

Can this also been used with a mirror, so that you can show things in a mirror behind the player that is not visible when the player turns around (for example a ghost)?

Edit: I tried getting this to work by placing a mirror behind the X-ray screen. This does not seem to work properly, or I am doing something wrong.

A possible alternative way might be placing a camera pointed toward the players front side through an x-ray screen and then put a monitor on the other side. Just thinking out loud..

Xrays + mirrors don't seem to work well together yet, though experimentation may yield interesting results and maybe support could be added if it's considered an interesting combination by mappers.

From a performance perspective it seems unsensible to attempt this though, since the xray system adds a 2nd model and the mirror doubles everything, ending up at 4 models. But it depends on what you do with the system: if all you do is change some decorative models you probably wouldn't notice a difference, but you would notice it if you converted your entire city map into an undead necropolis through xray vision and threw in a mirror with realtime reflections.

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

Quote

Can this also been used with a mirror, so that you can show things in a mirror behind the player that is not visible when the player turns around (for example a ghost)?

Using Xray system imo seems overkill for something like that, i think there are simple tricks for that. 

If you have Doom 3, you can always go look how idSoftware team made the famous bathroom scare scene, where everything reflected in the mirror changes to a hellish look, including the player. I bet most of it is script, not hardcoded c++ but I'm not sure, unlike latter idtech 4 games, many stuff in Doom 3 is script based so perhaps that is as well.

Spoiler

But like I said, IMO something like that should be simple to do, you can always do vector math to check what is in front or back of the player but perhaps TDM scripting already has functions exactly for that.

For example, Doom3 idActor class has the following function bellow, obviously this is TDM, so things maybe different but if the TDM player, works in the same basic principles/code as the Doom 3 player then perhaps that function still exist, then is just a matter of, if TDM team exposed it to script, if it did, imo it is exactly what you want to use, to check what the player can and cannot see.

But if they didn't exposed it and you know how to scrip, I don't think it would be hard to create your own script function inspired on the c++ code bellow, with what TDM team already has exposed to script.

//////////

bool idActor::CanSee( idEntity *ent, bool useFov ) const {
    trace_t        tr;
    idVec3        eye;
    idVec3        toPos;

    if ( ent->IsHidden() ) {
        return false;
    }

    if ( ent->IsType( idActor::Type ) ) {
        toPos = ( ( idActor * )ent )->GetEyePosition();
    } else {
        toPos = ent->GetPhysics()->GetOrigin();
    }

    if ( useFov && !CheckFOV( toPos ) ) {
        return false;
    }

    eye = GetEyePosition();

    gameLocal.clip.TracePoint( tr, eye, toPos, MASK_OPAQUE, this );
    if ( tr.fraction >= 1.0f || ( gameLocal.GetTraceEntity( tr ) == ent ) ) {
        return true;
    }

    return false;
}

  • Like 1
Link to comment
Share on other sites

1 hour ago, Wellingtoncrab said:

but I can't find how to simply flag an object as hidden unless viewed through the xray. Is this info in the wiki somewhere?

The current method mentioned in the wiki in the spawnargs section is just to set "skin" "invisible" and "skin_xray" "visible".

We thought about using the "xray" spawnarg for this so that "0" = invisible in xray, "1" = invisible in normal vision and i.e. no value = visible in both, but the skin method just seemed more intuitive.

  • Like 1
Link to comment
Share on other sites

Beta2 features a new spawnarg: "suppressInSubview". Specific to lights, setting this to "1" makes the light visible only in normal vision while "2" makes it visible only in xray vision. Note that this affects other subviews like mirrors and camera screens, too.

The below screenshot was achieved by setting the spawnarg on the regular ceiling lamp to "1" and on the blue flame light to "2".

xray_2021-12-19_20_02_44.thumb.jpg.c233fa827daecb36b6dfd06bafe5ac18.jpg

  • Like 3
Link to comment
Share on other sites

This is a really awesome mechanic - I really like the default mixed material which blends the two realities together in a very eerie way. I was wondering looking at the material def if one of the parameters influenced the sort of mixing amount between the two vision modes - say if for example you wanted the xray vision to be a little more prevalent in the scene? 

-=  IRIS  =-    ♦    = SLL =

Link to comment
Share on other sites

@WellingtoncrabMixing models is probably my favourite mode, too. For adjusting their relative contributions I found it useful to add a line with "alpha" followed by a number to the xray material stage. Note that if you go for alpha values over 1 the rendering may become... weird and overly bright, depending on your colour precision setting.

  • Thanks 1
Link to comment
Share on other sites

Thanks@Dragofer! If I could trouble you for one more bit of guidance the wiki mentions using additional scripting to do things like manipulate the solid property objects. I see the default behavior for brushwork with xray skins is to make them non solid.

I want to make certain objects solid when not wearing the xray glasses and I am admittedly not sure where to start. I see there is a global parameter to track the state of whether or not the glasses are on - does that mean it can be referenced by the map script? 

-=  IRIS  =-    ♦    = SLL =

Link to comment
Share on other sites

4 hours ago, Wellingtoncrab said:

I want to make certain objects solid when not wearing the xray glasses and I am admittedly not sure where to start.

My approach was to add another function to the scriptobject, "update_xray_entities", which is called by the scriptobject's init function at map start and whenever the player puts on or takes off the xray glasses. See the customised scriptobject below (it also contains a proper cooldown to limit how rapidly the player can toggle the glasses to minimise visual glitches).

Spoiler
#ifndef __XRAY_GLASSES__
#define __XRAY_GLASSES__

float wearing_xray_glasses;		//this is global for the benefit of the spyglass_overridable scriptobject

object playertools_xray_glasses : player_tools
{
	void init();
	void inventoryUse(entity userEntity, entity frobbedEntity, float buttonState);
	void update_xray_entities();	//updates frobability and solidity of xray entities on the map

	float overlayHandle;
	float xrayGlassesCooldown;
};

void playertools_xray_glasses::init()
{
	sys.waitFrame();
	update_xray_entities();
}

void playertools_xray_glasses::inventoryUse(entity userEntity, entity frobbedEntity, float buttonState)
{
	if( sys.getTime() < xrayGlassesCooldown )
	{
		return;
	}

	if ( !wearing_xray_glasses )
	{
		wearing_xray_glasses = true;
		overlayHandle = $player1.createOverlay(getKey("gui"), ZOOM_GUI_LAYER);
		$player1.setSpyglassOverlayBackground();	// display the correct background based on aspect ratio
	}

	else
	{
		wearing_xray_glasses = false;
		$player1.destroyOverlay(overlayHandle);
	}

	update_xray_entities();
	sys.fadeIn('0 0 0', 1);
	xrayGlassesCooldown = sys.getTime() + 1.5;
}

void playertools_xray_glasses::update_xray_entities()
{
	// find entities whose solidity should toggle when xray glasses are toggled.
	entity e;
	do
	{
		e = sys.getNextEntity("solid_xray","",e);
		if( e )
		{
			if ( e.getFloatKey("solid_xray") == 0 )
			{
				if ( wearing_xray_glasses )	e.setSolid(0);
				else				e.setSolid(1);
			}
			
			else
			{
				if ( wearing_xray_glasses )	e.setSolid(1);
				else				e.setSolid(0);
			}
		}
	} while (e);

	// find entities whose frobability should toggle when xray glasses are toggled.
	do
	{
		e = sys.getNextEntity("frobable_xray","",e);
		if( e )
		{
			if ( e.getFloatKey("frobable_xray") == 0 )
			{
				if ( wearing_xray_glasses )	e.setFrobable(0);
				else				e.setFrobable(1);
			}
			
			else
			{
				if ( wearing_xray_glasses )	e.setFrobable(1);
				else				e.setFrobable(0);
			}
		}
	} while (e);
}

#endif //__XRAY_GLASSES__

 

4 hours ago, Wellingtoncrab said:

I see there is a global parameter to track the state of whether or not the glasses are on - does that mean it can be referenced by the map script?

Yes, making that variable accessible to other scripts was the reason behind making it global. Personally I've used this for a custom version of the spyglass scriptobject that can't be used while the player has xray glasses on (see the beginning of the inventoryUse function in the below scriptobject).

Note that the custom spyglass scriptobject has to be #included later than the xray glasses in tdm_custom_scripts.script so that the variable already exists by the time the spyglass scriptobject tries to read it.

Spoiler
#ifndef __SPYGLASS_OVERRIDABLE__
#define __SPYGLASS_OVERRIDABLE__

//difference to normal spyglass: can't be used if already wearing xray_glasses (wearing_xray_glasses = true)

object playertools_spyglass_overridable : player_tools {
	void init();
	void inventoryUse(entity userEntity, entity frobbedEntity, float buttonState);
	void zoomOut();

	float zoomedIn;
	float zoomMutex;
	float overlayHandle;
};

void playertools_spyglass_overridable::init()
{
	zoomedIn = false;
	zoomMutex = false;
}

void playertools_spyglass_overridable::zoomOut()
{
	zoomedIn = false;
	$player1.endZoom(ZOOM_OUT_DURATION);

	zoomMutex = true; // disable commands during the zoom out transition

	sys.wait(ZOOM_OUT_DURATION/1000);
	$player1.destroyOverlay(overlayHandle);
	overlayHandle = 0;

	zoomMutex = false;

	$player1.setImmobilization(SPYGLASS, 0);
}

void playertools_spyglass_overridable::inventoryUse(entity userEntity, entity frobbedEntity, float buttonState)
{
	if (wearing_xray_glasses)
	{
		return;
	}

	// This is to avoid zoomIn events during zoomOut transitions, which look bad
	if (zoomMutex) {
		return;
	}

	if (!zoomedIn)
	{
		// Start zooming in
		zoomedIn = true;
		$player1.startZoom(ZOOM_IN_DURATION, ZOOM_STARTFOV, ZOOM_ENDFOV);

		// Create the GUI
		overlayHandle = $player1.createOverlay(getKey("gui"), ZOOM_GUI_LAYER);

		// Disable some player actions while zoomed in
		$player1.setImmobilization(SPYGLASS, SPYGLASS_IMMOBILIZATION);

		$player1.setGuiFloat(overlayHandle, STATE_ZOOM_IN_REQUEST, 0);
		$player1.setGuiFloat(overlayHandle, STATE_ZOOM_OUT_REQUEST, 0);

		// grayman #3807 - display the correct background based on aspect ratio
		$player1.setSpyglassOverlayBackground();

		eachFrame {
			// Check if the zoom has been ended >> break the loop
			if (!zoomedIn) {
				break;
			}

			float closeRequest = $player1.getGuiFloat(overlayHandle, STATE_CLOSE_REQUEST);
			if (closeRequest)
			{
				// Perform the zoomOut transition and break the loop
				zoomOut();
				break;
			}

			float zoomInRequest = $player1.getGuiFloat(overlayHandle, STATE_ZOOM_IN_REQUEST);
			float zoomOutRequest = $player1.getGuiFloat(overlayHandle, STATE_ZOOM_OUT_REQUEST);

			float curFov = $player1.getFov();
			float newFov = curFov;

			if (zoomInRequest)
			{
				newFov -= ZOOM_STEP;

				// Reset the GUI variable
				$player1.setGuiFloat(overlayHandle, STATE_ZOOM_IN_REQUEST, 0);
			}
			else if (zoomOutRequest)
			{
				// Zoom further out, if applicable
				newFov += ZOOM_STEP;

				// Reset the GUI variable
				$player1.setGuiFloat(overlayHandle, STATE_ZOOM_OUT_REQUEST, 0);
			}

			if (zoomInRequest || zoomOutRequest)
			{
				// Clamp the zoom value
				if (newFov < ZOOM_ENDFOV)
				{
					newFov = ZOOM_ENDFOV;
				}
				else if (newFov > ZOOM_STARTFOV) 
				{
					newFov = ZOOM_STARTFOV;
				}

				// Start the zoom transition from the current value to the the new one
				$player1.startZoom(ZOOM_STEP_DURATION, curFov, newFov);
			}
		}
	}
	else
	{
		// We're already zoomed in, so zoom out now.
		zoomOut();
	}
}

#endif //__SPYGLASS_OVERRIDABLE__
4 hours ago, Wellingtoncrab said:

I see the default behavior for brushwork with xray skins is to make them non solid.

The xray system itself should not have any effect on the solidity of entities, only the regular "skin". That said, I can't exclude 100% from my memory that setting a nonsolid "skin_xray" on i.e. a brush entity may affect its solidity in unforeseen ways.

  • Like 1
Link to comment
Share on other sites

Thank you for the expanded scripts - those additional spawnargs work great! Didn't even think about the spyglass!

3 hours ago, Dragofer said:

The xray system itself should not have any effect on the solidity of entities, only the regular "skin". That said, I can't exclude 100% from my memory that setting a nonsolid "skin_xray" on i.e. a brush entity may affect its solidity in unforeseen ways.

Yeah, reading your point above I realized the issue on the brush work I was putting both "skin" "visible" and "skin_xray" "invisible" on them and it was that inclusion of "skin" "visible" which was making them nonsolid when the glasses weren't on - obviously a bit redundant to specify you should be able to see the brush with the glasses off, so just removed that spawn arg and now it works exactly like I would expect - thanks again!

  • Like 1

-=  IRIS  =-    ♦    = SLL =

Link to comment
Share on other sites

  • 2 months later...

So is it possible to make walls and ceiling of a room look transparent through an x-ray screen? It seems to be possible at least through skins. If a bigger room is put around it, through the x-ray screen it would look like it has the bigger room size, looking through transparent walls.

Link to comment
Share on other sites

4 hours ago, datiswous said:

So is it possible to make walls and ceiling of a room look transparent through an x-ray screen? It seems to be possible at least through skins. If a bigger room is put around it, through the x-ray screen it would look like it has the bigger room size, looking through transparent walls.

I suppose so

Link to comment
Share on other sites

22 hours ago, datiswous said:

So is it possible to make walls and ceiling of a room look transparent through an x-ray screen? It seems to be possible at least through skins. If a bigger room is put around it, through the x-ray screen it would look like it has the bigger room size, looking through transparent walls.

Yes, but the walls and ceiling couldn't be worldspawn.

I'd do it via skin spawnargs too.

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...
On 12/20/2021 at 4:37 PM, Dragofer said:

Xrays + mirrors don't seem to work well together yet

What exactly doesn't work well (apart from potentially bad performance)?

It seems to work, but there is an issue with light, but maybe this is with mirrors in general?

Spoiler

xray_demo_2022-04-12_19_49_35.thumb.jpg.665ce8070702adb52d929613303403e3.jpg

 

Btw. on certain angles the x-ray screen turns black:

Spoiler

xray_demo_2022-04-12_20_14_34.thumb.jpg.817ba2717c5476402e86812d052815d0.jpg

Edited by datiswous
Link to comment
Share on other sites

  • 2 months later...

What about xrays + camera screens? I've got a security camera with a display screen, as described here: https://wiki.thedarkmod.com/index.php?title=Security_Camera_(2.10%2B)#Sending_the_camera.27s_view_to_a_Display_Screen. The camera is pointing at an entity that's been configured with skin_xray. If I watch the Display Screen with the xray glasses on, I don't see the xray version of the entity. Is that by design? Is there a way to make this happen?

Link to comment
Share on other sites

The image on the camera screen is exactly that, an image rendering the view of the camera. All information on what entities were visible on that image is gone. The only way that I can think of would be to render the camera view both in xray and default and then pick the on depending on whether or not the player has the xray glasses on.

This doesn't make much sense to me, though. I mean, if you look at a screen through a xray machine would you really expect that the xray move through the screen and the cables to the camera, from which they are emitted and then reflected again through the camera all the way back to the screen. Or what scenario do you have in mind?

FM's: Builder Roads, Old Habits, Old Habits Rebuild

Mapping and Scripting: Apples and Peaches

Sculptris Models and Tutorials: Obsttortes Models

My wiki articles: Obstipedia

Texture Blending in DR: DR ASE Blend Exporter

Link to comment
Share on other sites

I figured it was by design. It certainly don't make sense from real-world xray point-of-view. 

OTOH, who's to say how cameras and xrays behave in the Dark Mod world? Maybe the camera isn't sending electronic data to a screen (as in our world), but actually opening a "view portal" to the camera location. So you're looking at the actual photons coming from the source. In which case, the xray glasses might behave as I hoped. (I'm not saying that physics/magic should behave that way in the DM world, I'm just saying that it might. If it doesn't, that's cool).

Here's an example of the scenario I have in mind: There's a room that has objects can be xray-viewed. The room is heavily-guarded and has security cameras that broadcast to a Security Room. The player can either a) sneak into the room, avoid guards and cameras, put on the glasses and look at the xray item, or b) find the Security Room, put on the glasses and look at the screen when the camera is pointing at the item. Two ways for the player to solve the problem, which is always nice.

If the DM world doesn't work that way, no worries.

Link to comment
Share on other sites

That would definetely make more sense. While the TDM world does indeed not has to work like real life in all its aspects, teh similarities will make the player assume that this is the case. So many players may simple not get the idea that the could use the glasses in that way.

In addition we already have a mission that features these glasses, and they were tied into the story. Reusing these gadget over and over again will probably become boring by the time, not to mention one may not want to run around with those on over and over again.

It may be worthwhile to think about different usecases of this feature. Combining it with cameras might open up new possibilities. Note that, although it is called x-ray it doesn't have to be used in that manner. Basically you get to see something else when applied, which isn't the definition of x-ray per se.

  • Like 1

FM's: Builder Roads, Old Habits, Old Habits Rebuild

Mapping and Scripting: Apples and Peaches

Sculptris Models and Tutorials: Obsttortes Models

My wiki articles: Obstipedia

Texture Blending in DR: DR ASE Blend Exporter

Link to comment
Share on other sites

  • 1 year later...
6 hours ago, datiswous said:

Are the entities that are hidden while seen through the x-ray screen still being rendered by the engine?

In my understanding the entities are still being rendered for the normal view, since the x-ray subview is an additional rendering instance. You can show both views at the same time with transparency if you want a ghostly effect.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recent Status Updates

    • datiswous

      Beta test(er) tip:
      Test your mission at least once with all lights on. This can be done using notarget in console. Maybe just quickly fly around with noclip.
      Also test all lights which are off by default (enable all lights via script?). Mission testers will miss a lot of light bugs, because they take out lights with water arrows etc. and don't turn on lights so they don't spot light leaks etc. I've seen this now in some recent new missions after they're released.
      · 0 replies
    • Bergante

      welcome back Sotha 🫠
      👻
      · 6 replies
    • JackFarmer

      This site is getting more popular by the day - ca. 870 bots online this morning CET!
      · 2 replies
    • Xolvix

      Personal reminder for me to actually get back to TDM and all the missions I missed.
      · 1 reply
    • JackFarmer

      What is actually grammatically correct when it happens in the future? “Paul Atreides is an idiot” or ‘Paul Atreides was an idiot’? or ‘Paul Atreides will be an idiot’? The latter would at least fit in with the whole psychic and providence stuff!
      · 2 replies
×
×
  • Create New...