Jump to content

SexLab Framework Development


Recommended Posts

Hello

 

Have not been playing Skyrim for a while and recently updatet to the newst sl version. One question. Is it still not save to use the automatic tfc option ? Do i have to stop tfc by myself at/before the finale stage does the framework do this for me ?

 

Thx for your great work btw. Allways astonishing what happens here in just a few weeks/month.

 

 

Link to comment

Hello

 

Have not been playing Skyrim for a while and recently updatet to the newst sl version. One question. Is it still not save to use the automatic tfc option ? Do i have to stop tfc by myself at/before the finale stage does the framework do this for me ?

 

Thx for your great work btw. Allways astonishing what happens here in just a few weeks/month.

 

tfc is safe now. 

Link to comment

Anyone having issue trying to get the profieciency of there sexual experince to raise. I have managed to get vaginal to increase, but I can't get any of the other stats to raise. Also, Vaginal seemed to go from Unskilled stright to Grand Master, no steps in between, after about an hour of combined sex time. I've done about three hours now, the last hour with only an oral animation active. This is preventing me from starting the Sexlab Guild v0.9 mod as I'm stuck with Unskilled oral, preventing me from passing the test.

Link to comment

Finally finished Dark Souls 2 (assuming I don't get sucked into playing a new game+). So going to start working on getting the current API documentation caught up and then start planning out new features for 1.60.

Link to comment

Finally managed to get an SKSE plugin to compile and have started experimenting with replacing a couple of the slower SexLab functions with native functions done in C++, the few I've managed to replicate so far have all benchmarked to be significantly faster than their Papyrus equivalent, which is neat and will definitely result in some significant performance improvements for SexLab 1.60+

 

One part I've having trouble with so far however is calculating the actors position at the start of each stage seems to provide wildly different results in C++ than it does in Papyrus, which results in animations being wildly out of alignment. Being able to trim as much time off as I can in this phase of SexLab's code would result in better synced animations, making it an ideal target to replace with SKSE native functions as much as I can.

 

Everything I've tried has failed to correct the issue though, and I'm pretty much out of ideas, I think it's related to the fact that C++ uses doubles for sin/cos/tan calculations, while papyrus uses floats. Even just straight outputting the results of C++ math.h Sin() and Papyrus Math.Sin() result in completely different numbers. I don't really know though, I'm completely out of my element here, I don't know C++ and am more or less just stumbling my way through it here by looking at examples and applying my existing Python & PHP programming knowledge.

 

The relevant parts of that problem below:

 

Papyrus:

	function SyncLocation(bool Force = false)
		Offsets = Animation.GetPositionOffsets(AdjustKey, Position, Stage)
		float[] CenterLoc = Thread.CenterLocation
		Loc[0] = CenterLoc[0] + ( Math.sin(CenterLoc[5]) * Offsets[0] ) + ( Math.cos(CenterLoc[5]) * Offsets[1] )
		Loc[1] = CenterLoc[1] + ( Math.cos(CenterLoc[5]) * Offsets[0] ) + ( Math.sin(CenterLoc[5]) * Offsets[1] )
		Loc[2] = CenterLoc[2] + Offsets[2]
		Loc[3] = CenterLoc[3]
		Loc[4] = CenterLoc[4]
		Loc[5] = CenterLoc[5] + Offsets[3]

C++ SKSE Plugin:

	void OffsetCoords(StaticFunctionTag* base, VMArray<float> Coords, VMArray<float> CenterLoc, float forward, float sideward, float upward, float rotate){
		// Array holders
		float value;
		float *set = &value;
		// Cos / Sin of center Rot Z
		CenterLoc.Get(set, 5);
		float sinZ = sin(value);
		float cosZ = cos(value);
		// X
		CenterLoc.Get(set, 0);
		value += (sinZ * forward) + (cosZ * sideward);
		Coords.Set(set, 0);
		// Y
		CenterLoc.Get(set, 1);
		value += (cosZ * forward) + (sinZ * sideward);
		Coords.Set(set, 1);
		// Z
		CenterLoc.Get(set, 2);
		value += upward;
		Coords.Set(set, 2);
		// Rot Z
		CenterLoc.Get(set, 5);
		value += rotate;
		Coords.Set(set, 5);
		// Rot X,Y (copy center)
		CenterLoc.Get(set, 3);
		Coords.Set(set, 3);
		CenterLoc.Get(set, 4);
		Coords.Set(set, 4);
	}

Their arguments are wildly different due to the different application methods, but the math of calculating their final offset locations should be the same; yet they result in significantly different X & Y coordinates.

Link to comment

Why is there <float> ? Is it just for the commenting or SKSE requires that? Im not much of a programmer but never seen anything like that in C++.

 

It's a template: It's C++ convention.

 

 I'm quite familiar with C++, Ashal. Do you have the full source available to take a look at?

Link to comment

Why is there <float> ? Is it just for the commenting or SKSE requires that? Im not much of a programmer but never seen anything like that in C++.

 

VMArray<float> defines the argument as a papyrus float array, VMArray is the Skyrim class for Papyrus arrays, and <float> tells it what type it is.

Link to comment

 

Why is there <float> ? Is it just for the commenting or SKSE requires that? Im not much of a programmer but never seen anything like that in C++.

 

It's a template: It's C++ convention.

 

 I'm quite familiar with C++, Ashal. Do you have the full source available to take a look at?

 

 

 

It's not much to look at beyond the snippet I posted, as it's mostly just me playing around with shit right now, but here it is:

 

plugin_example.zip

 

It's not there in the source now, but I had at one point had this C++ function, which was in turn registered as a Papyrus native function to test in game:

	float TestCos(StaticFunctionTag* base, float value){
		return cos(value);
	}

and comparing the results in Skyrim with 

	Debug.TraceAndBox( "Papyrus: " + Math.Cos(PlayerRef.GetAngleZ()) )
	Debug.TraceAndBox( "SKSE: " + TestCos(PlayerRef.GetAngleZ()) )

would result in different outputs, I can't remember the exact numbers, but something in the range of one resulting in -0.4 and the other in -0.1, which seems minor but when used in the offset calculations it would place the actor 4+ feet to the left/right of where they should be.

 

And for further reference, the final-ish implementation of the SKSE function looks something like this inside the sslActorAlias script:

	function OffsetCoords(float[] Coords, float[] CenterLoc, float forward, float sideward, float upward, float rotate) global native

	function SyncLocation(bool Force = false)
		Offsets = Animation.GetPositionOffsets(AdjustKey, Position, Stage)
		OffsetCoords(Loc, Thread.CenterLocation, Offsets[0], Offsets[1], Offsets[2], Offsets[3])
Link to comment

 

It's not much to look at beyond the snippet I posted, as it's mostly just me playing around with shit right now, but here it is:

attachicon.gifplugin_example.zip

It's not there in the source now, but I had at one point had this C++ function, which was in turn registered as a Papyrus native function to test in game:

	float TestCos(StaticFunctionTag* base, float value){
		return cos(value);
	}

and comparing the results in Skyrim with 

	Debug.TraceAndBox( "Papyrus: " + Math.Cos(PlayerRef.GetAngleZ()) )
	Debug.TraceAndBox( "SKSE: " + TestCos(PlayerRef.GetAngleZ()) )

would result in different outputs, I can't remember the exact numbers, but something in the range of one resulting in -0.4 and the other in -0.1, which seems minor but when used in the offset calculations it would place the actor 4+ feet to the left/right of where they should be.

 

And for further reference, the final-ish implementation of the SKSE function looks something like this inside the sslActorAlias script:

	function OffsetCoords(float[] Coords, float[] CenterLoc, float forward, float sideward, float upward, float rotate) global native

	function SyncLocation(bool Force = false)
		Offsets = Animation.GetPositionOffsets(AdjustKey, Position, Stage)
		OffsetCoords(Loc, Thread.CenterLocation, Offsets[0], Offsets[1], Offsets[2], Offsets[3])

I don't see anything immediately wrong: I'm going to set up an environment to compile SKSE plugins (Something I've been meaning to do anyways), then play with it / figure it out.

 

You shouldn't be seeing any decrease in accuracy casting from a float to a double (Though the reverse would lose some precision. Not enough to account for a massive difference (0.1 - 0.4), though). 

Link to comment

 

 

It's not much to look at beyond the snippet I posted, as it's mostly just me playing around with shit right now, but here it is:

attachicon.gifplugin_example.zip

It's not there in the source now, but I had at one point had this C++ function, which was in turn registered as a Papyrus native function to test in game:

	float TestCos(StaticFunctionTag* base, float value){
		return cos(value);
	}

and comparing the results in Skyrim with 

	Debug.TraceAndBox( "Papyrus: " + Math.Cos(PlayerRef.GetAngleZ()) )
	Debug.TraceAndBox( "SKSE: " + TestCos(PlayerRef.GetAngleZ()) )

would result in different outputs, I can't remember the exact numbers, but something in the range of one resulting in -0.4 and the other in -0.1, which seems minor but when used in the offset calculations it would place the actor 4+ feet to the left/right of where they should be.

 

And for further reference, the final-ish implementation of the SKSE function looks something like this inside the sslActorAlias script:

	function OffsetCoords(float[] Coords, float[] CenterLoc, float forward, float sideward, float upward, float rotate) global native

	function SyncLocation(bool Force = false)
		Offsets = Animation.GetPositionOffsets(AdjustKey, Position, Stage)
		OffsetCoords(Loc, Thread.CenterLocation, Offsets[0], Offsets[1], Offsets[2], Offsets[3])

I don't see anything immediately wrong: I'm going to set up an environment to compile SKSE plugins (Something I've been meaning to do anyways), then play with it / figure it out.

 

You shouldn't be seeing any decrease in accuracy casting from a float to a double (Though the reverse would lose some precision. Not enough to account for a massive difference (0.1 - 0.4), though). 

 

 

My mostly uneducated suspicion would be that Papyrus is calculating it based on some sort of in-game measurement and not just as a raw floating point / double like c++ is doing. I hoped to find some example in the SKSE source code using Z rotations in a cos/sin/tan, but wasn't able to find one anywhere.

 

In the long run though, moving this function to C++ is in the minority of optimizations, it was just one of the first things I thought to test that I didn't think would be to difficult to get running with my limited C++ knowledge. There are ultimately other, more important places, I could cut Papyrus out of the loop that doesn't involve bashing my head on trigonometry issues.

Link to comment

 

My mostly uneducated suspicion would be that Papyrus is calculating it based on some sort of in-game measurement and not just as a raw floating point / double like c++ is doing. I hoped to find some example in the SKSE source code using Z rotations in a cos/sin/tan, but wasn't able to find one anywhere.

 

In the long run though, moving this function to C++ is in the minority of optimizations, it was just one of the first things I thought to test that I didn't think would be to difficult to get running with my limited C++ knowledge. There are ultimately other, more important places, I could cut Papyrus out of the loop that doesn't involve bashing my head on trigonometry issues.

 

 

Unlikely, I suspect that internally floats will be cast to doubles to calculate and cast to floats again for Papyrus. That would explain the calculation errors.

Link to comment

 

 

My mostly uneducated suspicion would be that Papyrus is calculating it based on some sort of in-game measurement and not just as a raw floating point / double like c++ is doing. I hoped to find some example in the SKSE source code using Z rotations in a cos/sin/tan, but wasn't able to find one anywhere.

 

In the long run though, moving this function to C++ is in the minority of optimizations, it was just one of the first things I thought to test that I didn't think would be to difficult to get running with my limited C++ knowledge. There are ultimately other, more important places, I could cut Papyrus out of the loop that doesn't involve bashing my head on trigonometry issues.

 

 

Unlikely, I suspect that internally floats will be cast to doubles to calculate and cast to floats again for Papyrus. That would explain the calculation errors.

 

 

No, it wouldn't. Values off by that much can't be explained by precision errors.

 

I figured out the problem (Very simple mistake): 

Papyrus's math.cos works on degrees, C++'s (And pretty much every math library from every other language) works on Radians.

 

Thus...

	float TestCos(StaticFunctionTag* base, float val) {
		return cos((val * M_PI / 180));
	}

provides the output that you want:

 

 

 

[05/19/2014 - 06:39:03PM] [Zad]: i: 180.000000
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    -1.000000
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: -1.000000
[05/19/2014 - 06:39:03PM] [Zad]: i: 10.000000
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.984808
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.984808
[05/19/2014 - 06:39:03PM] [Zad]: i: 9.850000
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.985259
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.985259
[05/19/2014 - 06:39:03PM] [Zad]: i: 9.700001
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.985703
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.985703
[05/19/2014 - 06:39:03PM] [Zad]: i: 9.550001
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.986141
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.986141
[05/19/2014 - 06:39:03PM] [Zad]: i: 9.400002
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.986572
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.986572
[05/19/2014 - 06:39:03PM] [Zad]: i: 9.250002
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.986996
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.986996
[05/19/2014 - 06:39:03PM] [Zad]: i: 9.100002
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.987414
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.987414
[05/19/2014 - 06:39:03PM] [Zad]: i: 8.950003
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.987824
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.987824
[05/19/2014 - 06:39:03PM] [Zad]: i: 8.800003
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.988228
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.988228
[05/19/2014 - 06:39:03PM] [Zad]: i: 8.650003
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.988626
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.988626
[05/19/2014 - 06:39:03PM] [Zad]: i: 8.500004
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.989016
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.989016
[05/19/2014 - 06:39:03PM] [Zad]: i: 8.350004
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.989399
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.989399
[05/19/2014 - 06:39:03PM] [Zad]: i: 8.200005
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.989776
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.989776
[05/19/2014 - 06:39:03PM] [Zad]: i: 8.050005
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.990146
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.990146
[05/19/2014 - 06:39:03PM] [Zad]: i: 7.900005
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.990509
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.990509
[05/19/2014 - 06:39:03PM] [Zad]: i: 7.750005
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.990866
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.990866
[05/19/2014 - 06:39:03PM] [Zad]: i: 7.600005
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.991216
[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.991216
[05/19/2014 - 06:39:03PM] [Zad]: i: 7.450005
[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.991558

Link to comment

 

 

My mostly uneducated suspicion would be that Papyrus is calculating it based on some sort of in-game measurement and not just as a raw floating point / double like c++ is doing. I hoped to find some example in the SKSE source code using Z rotations in a cos/sin/tan, but wasn't able to find one anywhere.

 

In the long run though, moving this function to C++ is in the minority of optimizations, it was just one of the first things I thought to test that I didn't think would be to difficult to get running with my limited C++ knowledge. There are ultimately other, more important places, I could cut Papyrus out of the loop that doesn't involve bashing my head on trigonometry issues.

 

Unlikely, I suspect that internally floats will be cast to doubles to calculate and cast to floats again for Papyrus. That would explain the calculation errors.

 

 

No, it wouldn't. Values off by that much can't be explained by precision errors.

 

I figured out the problem (Very simple mistake): 

Papyrus's math.cos works on degrees, C++'s (And pretty much every math library from every other language) works on Radians.

 

Thus...

	float TestCos(StaticFunctionTag* base, float val) {
		return cos((val * M_PI / 180));
	}
provides the output that you want:

 

 

 

[05/19/2014 - 06:39:03PM] [Zad]: i: 180.000000

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    -1.000000

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: -1.000000

[05/19/2014 - 06:39:03PM] [Zad]: i: 10.000000

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.984808

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.984808

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.850000

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.985259

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.985259

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.700001

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.985703

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.985703

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.550001

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.986141

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.986141

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.400002

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.986572

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.986572

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.250002

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.986996

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.986996

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.100002

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.987414

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.987414

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.950003

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.987824

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.987824

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.800003

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.988228

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.988228

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.650003

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.988626

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.988626

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.500004

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.989016

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.989016

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.350004

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.989399

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.989399

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.200005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.989776

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.989776

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.050005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.990146

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.990146

[05/19/2014 - 06:39:03PM] [Zad]: i: 7.900005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.990509

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.990509

[05/19/2014 - 06:39:03PM] [Zad]: i: 7.750005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.990866

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.990866

[05/19/2014 - 06:39:03PM] [Zad]: i: 7.600005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.991216

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.991216

[05/19/2014 - 06:39:03PM] [Zad]: i: 7.450005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.991558

 

 

Fantastic, it probably would've taken me ages to catch onto that, if ever. Thanks!

Link to comment

 

 

 

My mostly uneducated suspicion would be that Papyrus is calculating it based on some sort of in-game measurement and not just as a raw floating point / double like c++ is doing. I hoped to find some example in the SKSE source code using Z rotations in a cos/sin/tan, but wasn't able to find one anywhere.

 

In the long run though, moving this function to C++ is in the minority of optimizations, it was just one of the first things I thought to test that I didn't think would be to difficult to get running with my limited C++ knowledge. There are ultimately other, more important places, I could cut Papyrus out of the loop that doesn't involve bashing my head on trigonometry issues.

 

Unlikely, I suspect that internally floats will be cast to doubles to calculate and cast to floats again for Papyrus. That would explain the calculation errors.

 

 

No, it wouldn't. Values off by that much can't be explained by precision errors.

 

I figured out the problem (Very simple mistake): 

Papyrus's math.cos works on degrees, C++'s (And pretty much every math library from every other language) works on Radians.

 

Thus...

	float TestCos(StaticFunctionTag* base, float val) {
		return cos((val * M_PI / 180));
	}
provides the output that you want:

 

 

 

[05/19/2014 - 06:39:03PM] [Zad]: i: 180.000000

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    -1.000000

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: -1.000000

[05/19/2014 - 06:39:03PM] [Zad]: i: 10.000000

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.984808

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.984808

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.850000

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.985259

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.985259

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.700001

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.985703

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.985703

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.550001

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.986141

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.986141

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.400002

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.986572

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.986572

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.250002

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.986996

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.986996

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.100002

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.987414

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.987414

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.950003

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.987824

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.987824

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.800003

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.988228

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.988228

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.650003

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.988626

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.988626

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.500004

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.989016

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.989016

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.350004

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.989399

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.989399

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.200005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.989776

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.989776

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.050005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.990146

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.990146

[05/19/2014 - 06:39:03PM] [Zad]: i: 7.900005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.990509

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.990509

[05/19/2014 - 06:39:03PM] [Zad]: i: 7.750005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.990866

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.990866

[05/19/2014 - 06:39:03PM] [Zad]: i: 7.600005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.991216

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.991216

[05/19/2014 - 06:39:03PM] [Zad]: i: 7.450005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.991558

 

 

Fantastic, it probably would've taken me ages to catch onto that, if ever. Thanks!

 

 

No problem: It gave me a good excuse to figure out the SKSE plugins api. Time to write my own! :D

Link to comment

 

 

 

 

My mostly uneducated suspicion would be that Papyrus is calculating it based on some sort of in-game measurement and not just as a raw floating point / double like c++ is doing. I hoped to find some example in the SKSE source code using Z rotations in a cos/sin/tan, but wasn't able to find one anywhere.

 

In the long run though, moving this function to C++ is in the minority of optimizations, it was just one of the first things I thought to test that I didn't think would be to difficult to get running with my limited C++ knowledge. There are ultimately other, more important places, I could cut Papyrus out of the loop that doesn't involve bashing my head on trigonometry issues.

 

Unlikely, I suspect that internally floats will be cast to doubles to calculate and cast to floats again for Papyrus. That would explain the calculation errors.

 

 

No, it wouldn't. Values off by that much can't be explained by precision errors.

 

I figured out the problem (Very simple mistake): 

Papyrus's math.cos works on degrees, C++'s (And pretty much every math library from every other language) works on Radians.

 

Thus...

	float TestCos(StaticFunctionTag* base, float val) {
		return cos((val * M_PI / 180));
	}
provides the output that you want:

 

 

 

[05/19/2014 - 06:39:03PM] [Zad]: i: 180.000000

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    -1.000000

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: -1.000000

[05/19/2014 - 06:39:03PM] [Zad]: i: 10.000000

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.984808

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.984808

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.850000

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.985259

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.985259

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.700001

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.985703

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.985703

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.550001

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.986141

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.986141

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.400002

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.986572

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.986572

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.250002

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.986996

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.986996

[05/19/2014 - 06:39:03PM] [Zad]: i: 9.100002

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.987414

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.987414

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.950003

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.987824

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.987824

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.800003

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.988228

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.988228

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.650003

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.988626

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.988626

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.500004

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.989016

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.989016

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.350004

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.989399

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.989399

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.200005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.989776

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.989776

[05/19/2014 - 06:39:03PM] [Zad]: i: 8.050005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.990146

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.990146

[05/19/2014 - 06:39:03PM] [Zad]: i: 7.900005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.990509

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.990509

[05/19/2014 - 06:39:03PM] [Zad]: i: 7.750005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.990866

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.990866

[05/19/2014 - 06:39:03PM] [Zad]: i: 7.600005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.991216

[05/19/2014 - 06:39:03PM] [Zad]: Papyrus: 0.991216

[05/19/2014 - 06:39:03PM] [Zad]: i: 7.450005

[05/19/2014 - 06:39:03PM] [Zad]: SKSE:    0.991558

 

 

Fantastic, it probably would've taken me ages to catch onto that, if ever. Thanks!

 

 

No problem: It gave me a good excuse to figure out the SKSE plugins api. Time to write my own! :D

 

(unsurprisingly) the benefits of SKSE plugin over Papyrus seem pretty major as far as I can tell so far. I'm looking forward to what sort of performance improvements I can squeeze out of SexLab with it.

 

In case you're curious, and because I can't sleep and feel the need to over explain something; running some examples through my benchmark script (sslBenchmark.psc), with an average time to complete 10 x 5,000 iterations of SexLab's current Papyrus implementaion of IsStrippable() in sslActorLibrary.psc (a primary source of slowdown in starting up SexLab scenes) versus the SKSE based implementation, HasKeywordSub(), which was included in the source code I attached a few posts back; resulted in pretty significant performance gains.

 

Test 1 - Papyrus IsStrippable(form) - NO FormList caching of results - 21.41s average

Test 2 - Papyrus IsStrippable(form) - WITH FormList caching of results - 0.81s average

Test 3 - SKSE Plugin HasKeywordSub(form, string) - no caching of any kind - 0.24s average

 

Ultimately, if well cached, the difference between current IsStrippable() vs HasKeywordSub() is in practical terms, unnoticeable, but the fact that it outshines it by a significant margin in cases where none of the actors armor is cached as strippable/unstrippable, could very well make a difference of 2-3 seconds in scene startup time.

 

Which, admittedly, likely only me as as somebody who cares more about how the framework performs from a hobbyist perspective than as a normal user would likely not really notice the difference.

Link to comment

 

(unsurprisingly) the benefits of SKSE plugin over Papyrus seem pretty major as far as I can tell so far. I'm looking forward to what sort of performance improvements I can squeeze out of SexLab with it.

 

In case you're curious, and because I can't sleep and feel the need to over explain something; running some examples through my benchmark script (sslBenchmark.psc), with an average time to complete 10 x 5,000 iterations of SexLab's current Papyrus implementaion of IsStrippable() in sslActorLibrary.psc (a primary source of slowdown in starting up SexLab scenes) versus the SKSE based implementation, HasKeywordSub(), which was included in the source code I attached a few posts back; resulted in pretty significant performance gains.

 

Test 1 - Papyrus IsStrippable(form) - NO FormList caching of results - 21.41s average

Test 2 - Papyrus IsStrippable(form) - WITH FormList caching of results - 0.81s average

Test 3 - SKSE Plugin HasKeywordSub(form, string) - no caching of any kind - 0.24s average

 

Ultimately, if well cached, the difference between current IsStrippable() vs HasKeywordSub() is in practical terms, unnoticeable, but the fact that it outshines it by a significant margin in cases where none of the actors armor is cached as strippable/unstrippable, could very well make a difference of 2-3 seconds in scene startup time.

 

Which, admittedly, likely only me as as somebody who cares more about how the framework performs from a hobbyist perspective than as a normal user would likely not really notice the difference.

Nice. That's quite the improvement!

 

I've been debating offloading a couple of the heavier functions from DDi to SKSE plugins. Now that I've got the initial "Setting up the SKSE environment" barrier out of the way, think I'll go ahead and do so (Not that it was particularly slow to begin with, though there are certainly a few places that could benefit from a native C++ implementation). Not to mention a few things that would be downright impossible to do via papyrus...

Link to comment

Thank you for making and supporting the Sexlab plug in but i want to state i dislike being forced to download a alpha version of skse to use the most recent version of sex lab. I believe you did this for efficiency improvements(noble goal) but since i'm not following this thread i can't be sure.

 

Talking about efficiency, you'd be shocked how efficient a HashMap can be. I don't know if Skse or skyrim's scripting language support them but the theory of how they work, is you have a key, and a value. you enter the key, and with 1 check, the program returns a value; but why these hashMaps are so power is the concept that it only has to make this one check unlike an array list which you have to check every element.

Lets say we want to count how many times each letter pops up in a book, then you make each letter a key, to the number of times a letter shows up. Then all you have to do is update the number by increasing it by 1. Just to give you a bench mark, i had a homework assignment where was told to print out how many repeat characters are in the first chapter of moby dick. because of loading from a file and storing the values in a collection(HashMap) it took me 110MS roughly; the next part required that after that first character count, all other counts had to have a massive efficiency improvement. I was about to get repeat calls to the method to take 3MS because basically all i had to do was scan all the values in the hash map and see if the returned value was more than 1.

Link to comment

Thank you for making and supporting the Sexlab plug in but i want to state i dislike being forced to download a alpha version of skse to use the most recent version of sex lab. I believe you did this for efficiency improvements(noble goal) but since i'm not following this thread i can be sure.

 

Talking about efficiency, you'd be shocked how efficient a HashMap can be. I don't know if Skse or skyrim's scripting language support them but the theory of how they work, is you have a key, and a value. you enter the key, and with 1 check, the program returns a value; but why these hashMaps are so power is the concept that it only has to make this one check unlike an array list which you have to check every element.

 

Lets say we want to count how many times each letter pops up in a book, then you make each letter a key, to the number of times a letter shows up. Then all you have to do is update the number by increasing it by 1. Just to give you a bench mark, i had a homework assignment where was told to print out how many repeat characters are in the first chapter of moby dick. because of loading from a file and storing the values in a collection(HashMap) it took me 110MS roughly; the next part required that after that first character count, all other counts had to have a massive efficiency improvement. I was about to get repeat calls to the method to take 3MS because basically all i had to do was scan all the values in the hash map and see if the returned value was more than 1.

Real data-structures in papyrus? That's hilarious :P. We don't even have 2d arrays in these parts, much less dicts / hashtables. That said, there's no reason one couldn't be implemented in C++, and made available through SKSE. For that matter, PapyrusUtil already does something similar-ish.

Link to comment

Thank you for making and supporting the Sexlab plug in but i want to state i dislike being forced to download a alpha version of skse to use the most recent version of sex lab. I believe you did this for efficiency improvements(noble goal) but since i'm not following this thread i can be sure.

 

Talking about efficiency, you'd be shocked how efficient a HashMap can be. I don't know if Skse or skyrim's scripting language support them but the theory of how they work, is you have a key, and a value. you enter the key, and with 1 check, the program returns a value; but why these hashMaps are so power is the concept that it only has to make this one check unlike an array list which you have to check every element.

 

Lets say we want to count how many times each letter pops up in a book, then you make each letter a key, to the number of times a letter shows up. Then all you have to do is update the number by increasing it by 1. Just to give you a bench mark, i had a homework assignment where was told to print out how many repeat characters are in the first chapter of moby dick. because of loading from a file and storing the values in a collection(HashMap) it took me 110MS roughly; the next part required that after that first character count, all other counts had to have a massive efficiency improvement. I was about to get repeat calls to the method to take 3MS because basically all i had to do was scan all the values in the hash map and see if the returned value was more than 1.

 

HashMaps aren't natively supported by Papyrus. We can only work with Bool, Int, Float and String as native datatypes. Even if someone would make something like that as an SKSE plugin it would be slower than the above data types because you have to convert them back so the Papyrus Compiler can work with it. Besides the mentioned PapyrusUtil, JContainers also supports data structures.

 

Only the Creation Kit Extender could change that, but it is still under development and who knows when it will be ready for an alpha release. As long as we don't have it, we won't see any performance boost from those storage plugins.

Link to comment

 

Thank you for making and supporting the Sexlab plug in but i want to state i dislike being forced to download a alpha version of skse to use the most recent version of sex lab. I believe you did this for efficiency improvements(noble goal) but since i'm not following this thread i can be sure.

 

Talking about efficiency, you'd be shocked how efficient a HashMap can be. I don't know if Skse or skyrim's scripting language support them but the theory of how they work, is you have a key, and a value. you enter the key, and with 1 check, the program returns a value; but why these hashMaps are so power is the concept that it only has to make this one check unlike an array list which you have to check every element.

 

Lets say we want to count how many times each letter pops up in a book, then you make each letter a key, to the number of times a letter shows up. Then all you have to do is update the number by increasing it by 1. Just to give you a bench mark, i had a homework assignment where was told to print out how many repeat characters are in the first chapter of moby dick. because of loading from a file and storing the values in a collection(HashMap) it took me 110MS roughly; the next part required that after that first character count, all other counts had to have a massive efficiency improvement. I was about to get repeat calls to the method to take 3MS because basically all i had to do was scan all the values in the hash map and see if the returned value was more than 1.

 

HashMaps aren't natively supported by Papyrus. We can only work with Bool, Int, Float and String as native datatypes. Even if someone would make something like that as an SKSE plugin it would be slower than the above data types because you have to convert them back so the Papyrus Compiler can work with it. Besides the mentioned PapyrusUtil, JContainers also supports data structures.

 

Only the Creation Kit Extender could change that, but it is still under development and who knows when it will be ready for an alpha release. As long as we don't have it, we won't see any performance boost from those storage plugins.

 

The advantage of a hashMap would be data retrieval; which i believe that you could retrieve and convert the variables in less time then just retrieving the data in the native script. it would be to your advantage make a hashmap in C++ if that were true.

However i should really stop talking since i have no experience with Papyrus and just speaking about theoretical concepts not facts or bench marks will not help intelligent conversation.

 

EDIT

Well back to reinstalling my mods after Steam started throwing error 80 which made me think my game was corrupted.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. For more information, see our Privacy Policy & Terms of Use