25 May 2008

This commit is contained in:
g-cont 2008-05-25 00:00:00 +04:00 committed by Alibek Omarov
parent 9f130597d8
commit b3fb246eda
25 changed files with 576 additions and 280 deletions

View File

@ -63,5 +63,5 @@ if exist viewer\viewer.plg del /f /q viewer\viewer.plg
echo Build succeeded!
echo Please wait. Xash is now loading
cd D:\Xash3D\
xash.exe -log -game tmpQuArK -debug -dev 3 +map qctest
xash.exe -log -game tmpQuArK -debug -dev 3 +map start
:done

View File

@ -214,9 +214,6 @@ void CL_PredictMovement (void)
memset (&pm, 0, sizeof(pm));
pm.trace = CL_PMTrace;
pm.pointcontents = CL_PMpointcontents;
pm_airaccelerate = atof(cl.configstrings[CS_AIRACCEL]);
pm.ps = cl.frame.playerstate;
// SCR_DebugGraph (current - ack - 1, COLOR_0);
@ -230,7 +227,7 @@ void CL_PredictMovement (void)
cmd = &cl.cmds[frame];
pm.cmd = *cmd;
Pmove (&pm);
pe->PlayerMove( &pm, true );
// save for debug checking
VectorCopy (pm.ps.origin, cl.predicted_origins[frame]);

View File

@ -1,49 +0,0 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// collision.h - base collision detect
//=======================================================================
#ifndef COLLISION_H
#define COLLISION_H
// content masks
#define MASK_ALL (-1)
#define MASK_SOLID (CONTENTS_SOLID|CONTENTS_WINDOW)
#define MASK_PLAYERSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER)
#define MASK_DEADSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW)
#define MASK_MONSTERSOLID (CONTENTS_SOLID|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER)
#define MASK_WATER (CONTENTS_WATER|CONTENTS_LAVA|CONTENTS_SLIME)
#define MASK_OPAQUE (CONTENTS_SOLID|CONTENTS_SLIME|CONTENTS_LAVA)
#define MASK_SHOT (CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEADMONSTER)
#define MASK_CURRENT (CONTENTS_CURRENT_0|CONTENTS_CURRENT_90|CONTENTS_CURRENT_180|CONTENTS_CURRENT_270|CONTENTS_CURRENT_UP|CONTENTS_CURRENT_DOWN)
#define AREA_SOLID 1
#define AREA_TRIGGERS 2
// pmove->pm_flags
#define PMF_DUCKED 1
#define PMF_JUMP_HELD 2
#define PMF_ON_GROUND 4
#define PMF_TIME_WATERJUMP 8 // pm_time is waterjump
#define PMF_TIME_LAND 16 // pm_time is time before rejump
#define PMF_TIME_TELEPORT 32 // pm_time is non-moving time
#define PMF_NO_PREDICTION 64 // temporarily disables prediction (used for grappling hook)
/*
==============================================================
PLAYER MOVEMENT CODE
Common between server and client so prediction matches
==============================================================
*/
// button bits
#define BUTTON_ATTACK 1
#define BUTTON_USE 2
#define BUTTON_ATTACK2 4
#define BUTTONS_ATTACK (BUTTON_ATTACK | BUTTON_ATTACK2)
#define BUTTON_ANY 128 // any key whatsoever
extern float pm_airaccelerate;
void Pmove(pmove_t *pmove);
#endif//COLLISION_H

View File

@ -210,10 +210,6 @@ SOURCE=.\net_wins.c
# End Source File
# Begin Source File
SOURCE=.\pmove.c
# End Source File
# Begin Source File
SOURCE=.\uimenu\qmenu.c
# End Source File
# Begin Source File

View File

@ -20,7 +20,6 @@
#include "net_msg.h"
#include "screen.h"
#include "keycodes.h"
#include "pmove.h"
extern stdlib_api_t com;
extern physic_exp_t *pe;

View File

@ -115,6 +115,7 @@ void Host_InitPhysic( void )
// phys callback
pi.api_size = sizeof(physic_imp_t);
pi.Transform = SV_Transform;
pi.ClientMove = SV_PlayerMove;
pi.GetModelVerts = SV_GetModelVerts;
Sys_LoadLibrary( &physic_dll );

View File

@ -85,32 +85,6 @@ typedef enum
#define CM_BUTTONS (1<<6)
#define CM_IMPULSE (1<<7)
// player_state->stats[] indexes
enum player_stats
{
STAT_HEALTH_ICON = 0,
STAT_HEALTH,
STAT_AMMO_ICON,
STAT_AMMO,
STAT_ARMOR_ICON,
STAT_ARMOR,
STAT_SELECTED_ICON,
STAT_PICKUP_ICON,
STAT_PICKUP_STRING,
STAT_TIMER_ICON,
STAT_TIMER,
STAT_HELPICON,
STAT_SELECTED_ITEM,
STAT_LAYOUTS,
STAT_FRAGS,
STAT_FLASHES, // cleared each frame, 1 = health, 2 = armor
STAT_CHASE,
STAT_SPECTATOR,
STAT_SPEED = 22,
STAT_ZOOM,
MAX_STATS = 32,
};
// dmflags->value flags
#define DF_NO_HEALTH 0x00000001 // 1
#define DF_NO_ITEMS 0x00000002 // 2

View File

@ -1,145 +0,0 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// pmove.h - base player physic
//=======================================================================
#ifndef COLLISION_H
#define COLLISION_H
// encoded bmodel mask
#define SOLID_BMODEL 0xffffff
// content masks
#define MASK_ALL (-1)
#define MASK_SOLID (CONTENTS_SOLID|CONTENTS_WINDOW)
#define MASK_PLAYERSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER)
#define MASK_DEADSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW)
#define MASK_MONSTERSOLID (CONTENTS_SOLID|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER)
#define MASK_WATER (CONTENTS_WATER|CONTENTS_LAVA|CONTENTS_SLIME)
#define MASK_OPAQUE (CONTENTS_SOLID|CONTENTS_SLIME|CONTENTS_LAVA)
#define MASK_SHOT (CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEADMONSTER)
#define MASK_CURRENT (CONTENTS_CURRENT_0|CONTENTS_CURRENT_90|CONTENTS_CURRENT_180|CONTENTS_CURRENT_270|CONTENTS_CURRENT_UP|CONTENTS_CURRENT_DOWN)
// pmove_state_t is the information necessary for client side movement
#define PM_NORMAL 0 // can accelerate and turn
#define PM_SPECTATOR 1
#define PM_DEAD 2 // no acceleration or turning
#define PM_GIB 3 // different bounding box
#define PM_FREEZE 4
#define PM_INTERMISSION 5
#define PM_NOCLIP 6
// pmove->pm_flags
#define PMF_DUCKED 1
#define PMF_JUMP_HELD 2
#define PMF_ON_GROUND 4
#define PMF_TIME_WATERJUMP 8 // pm_time is waterjump
#define PMF_TIME_LAND 16 // pm_time is time before rejump
#define PMF_TIME_TELEPORT 32 // pm_time is non-moving time
#define PMF_NO_PREDICTION 64 // temporarily disables prediction (used for grappling hook)
#define PMF_ALL_TIMES (PMF_TIME_WATERJUMP|PMF_TIME_LAND|PMF_TIME_TELEPORT)
// viewmodel state
typedef struct
{
int index; // client modelindex
vec3_t angles; // can be some different with viewangles
vec3_t offset; // center offset
int sequence; // studio animation sequence
int frame; // studio frame
int body; // weapon body
int skin; // weapon skin
} vmodel_state_t;
// thirdperson model state
typedef struct
{
int index; // client modelindex
int sequence; // studio animation sequence
int frame; // studio frame
} pmodel_state_t;
// player_state_t communication
typedef struct
{
int bobcycle; // for view bobbing and footstep generation
float bobtime;
byte pm_type; // player movetype
byte pm_flags; // ducked, jump_held, etc
byte pm_time; // each unit = 8 ms
vec3_t origin;
vec3_t velocity;
vec3_t delta_angles; // add to command angles to get view direction
short gravity; // gravity value
short speed; // maxspeed
edict_t *groundentity; // current ground entity
int viewheight; // height over ground
int effects; // copied to entity_state_t->effects
int weapon; // copied to entity_state_t->weapon
vec3_t viewangles; // for fixed views
vec3_t viewoffset; // add to pmovestate->origin
vec3_t kick_angles; // add to view direction to get render angles
vec3_t oldviewangles; // for lerping viewmodel position
vec4_t blend; // rgba full screen effect
short stats[MAX_STATS];
float fov; // horizontal field of view
// player model and viewmodel
vmodel_state_t vmodel;
pmodel_state_t pmodel;
} player_state_t;
// user_cmd_t communication
typedef struct usercmd_s
{
byte msec;
byte buttons;
short angles[3];
byte impulse; // remove?
byte lightlevel; // light level the player is standing on
short forwardmove, sidemove, upmove;
} usercmd_t;
#define MAXTOUCH 32
typedef struct
{
player_state_t ps; // state (in / out)
// command (in)
usercmd_t cmd;
// results (out)
int numtouch;
edict_t *touchents[MAXTOUCH];
vec3_t mins, maxs; // bounding box size
int watertype;
int waterlevel;
float xyspeed; // avoid to compute it twice
// callbacks to test the world
trace_t (*trace)( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end );
int (*pointcontents)( vec3_t point );
} pmove_t;
/*
==============================================================
PLAYER MOVEMENT CODE
Common between server and client so prediction matches
==============================================================
*/
// button bits
#define BUTTON_ATTACK 1
#define BUTTON_USE 2
#define BUTTON_ATTACK2 4
#define BUTTONS_ATTACK (BUTTON_ATTACK | BUTTON_ATTACK2)
#define BUTTON_ANY 128 // any key whatsoever
extern float pm_airaccelerate;
void Pmove( pmove_t *pmove );
#endif//COLLISION_H

View File

@ -29,7 +29,6 @@ The code uses void pointers instead.
#ifndef PROGSVM_H
#define PROGSVM_H
#include "pmove.h"
#include "sv_edict.h" // server progs
#include "cl_edict.h" // client progs
#include "ui_edict.h" // uimenu progs

View File

@ -253,6 +253,7 @@ void SV_VM_End(void);
//
// sv_phys.c
//
void SV_PlayerMove( sv_edict_t *ed );
void SV_PrepWorldFrame (void);
void SV_Physics (edict_t *ent);
void SV_DropToFloor (edict_t *ent);

View File

@ -33,6 +33,7 @@ typedef struct worldsector_s
struct gclient_s
{
player_state_t ps; // communicated by server to clients
usercmd_t ucmd; // memeber current frame commands
int ping;
};

View File

@ -160,19 +160,12 @@ void SV_SpawnServer (char *server, char *savename, sv_state_t serverstate )
// save name for levels that don't set message
strcpy (sv.configstrings[CS_NAME], server);
if (Cvar_VariableValue ("deathmatch"))
{
sprintf(sv.configstrings[CS_AIRACCEL], "%g", sv_airaccelerate->value);
pm_airaccelerate = sv_airaccelerate->value;
}
else
{
strcpy(sv.configstrings[CS_AIRACCEL], "0");
pm_airaccelerate = 0;
}
if( Cvar_VariableValue ("deathmatch") )
com.sprintf( sv.configstrings[CS_AIRACCEL], "%g", sv_airaccelerate->value );
else com.strcpy( sv.configstrings[CS_AIRACCEL], "0" );
SZ_Init(&sv.multicast, sv.multicast_buf, sizeof(sv.multicast_buf));
strcpy (sv.name, server);
com.strcpy( sv.name, server );
SV_VM_Begin();

View File

@ -49,7 +49,7 @@ void SV_PutClientInServer (edict_t *ent)
memset (&ent->priv.sv->client->ps, 0, sizeof(client->ps));
// info_player_start
VectorCopy(ent->progs.sv->origin, client->ps.origin);
VectorCopy( ent->progs.sv->origin, client->ps.origin );
client->ps.fov = 90;
client->ps.fov = bound(1, client->ps.fov, 160);
@ -81,8 +81,10 @@ void SV_PutClientInServer (edict_t *ent)
ent->progs.sv->angles[ROLL] = 0;
}
VectorCopy(ent->progs.sv->angles, client->ps.viewangles);
VectorCopy( ent->progs.sv->angles, client->ps.viewangles );
SV_LinkEdict(ent);
ent->priv.sv->physbody = pe->CreatePlayer( ent->priv.sv, SV_GetModelPtr( ent ), ent->progs.sv->m_pmatrix );
}
/*
@ -512,6 +514,7 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd)
else client->ps.pm_flags &= ~PMF_TIME_TELEPORT;
pm.ps = client->ps;
memcpy( &client->ucmd, ucmd, sizeof(usercmd_t));//IMPORTANT!!!
VectorCopy(ent->progs.sv->origin, pm.ps.origin );
VectorCopy(ent->progs.sv->velocity, pm.ps.velocity );
@ -522,7 +525,7 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd)
pm.pointcontents = PM_pointcontents;
// perform a pmove
Pmove (&pm);
pe->PlayerMove( &pm, false );
// save results of pmove
client->ps = pm.ps;
@ -669,7 +672,7 @@ void Cmd_Say_f (edict_t *ent, bool team, bool arg0)
// don't let text be too long for malicious reasons
if (strlen(text) > 150) text[150] = 0;
strcat(text, "\n");
com.strcat(text, "\n");
if (dedicated->value)
PF_cprintf(NULL, PRINT_CHAT, "%s", text);
@ -789,4 +792,50 @@ void SV_Transform( sv_edict_t *ed, matrix4x3 transform )
// refresh force and torque
pe->GetForce( ed->physbody, edict->progs.sv->velocity, edict->progs.sv->avelocity, edict->progs.sv->force, edict->progs.sv->torque );
pe->GetMassCentre( ed->physbody, edict->progs.sv->m_pcentre );
}
/*
==============
CV_ClientMove
grab user cmd from player_state_t
send it to transform callback
==============
*/
void SV_PlayerMove( sv_edict_t *ed )
{
pmove_t pm;
gclient_t *client;
edict_t *player;
client = ed->client;
player = PRVM_PROG_TO_EDICT( ed->serialnumber );
memset( &pm, 0, sizeof(pm) );
if( player->progs.sv->movetype == MOVETYPE_NOCLIP )
client->ps.pm_type = PM_SPECTATOR;
else client->ps.pm_type = PM_NORMAL;
client->ps.gravity = sv_gravity->value;
if( player->progs.sv->teleport_time )
client->ps.pm_flags |= PMF_TIME_TELEPORT;
else client->ps.pm_flags &= ~PMF_TIME_TELEPORT;
pm.ps = client->ps;
pm.cmd = client->ucmd;
pm.body = ed->physbody; // member body ptr
VectorCopy( player->progs.sv->origin, pm.ps.origin );
VectorCopy( player->progs.sv->velocity, pm.ps.velocity );
pe->ServerMove( &pm );
// save results of pmove
client->ps = pm.ps;
VectorCopy(pm.ps.origin, player->progs.sv->origin);
VectorCopy(pm.ps.velocity, player->progs.sv->velocity);
VectorCopy(pm.mins, player->progs.sv->mins);
VectorCopy(pm.maxs, player->progs.sv->maxs);
VectorCopy(pm.ps.viewangles, client->ps.viewangles);
}

View File

@ -52,8 +52,8 @@ void Sys_Error( const char *error, ... )
// prepare host to close
sprintf( host.finalmsg, "Server fatal crashed: %s\n", errorstring );
host.state = HOST_ERROR; // lock shutdown state
Host_FreeRender();
host.state = HOST_ERROR; // lock shutdown state
Host_FreeRender(); // close render to show message error
com.error("%s", errorstring );
}

View File

@ -1,17 +1,17 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// cm_callback.c - game callbacks
// cm_callback.c - generic callbacks
//=======================================================================
#include "physic.h"
#include "cm_local.h"
void Callback_ApplyForce( const NewtonBody* body )
{
float mass;
vec3_t size, force, torque;
vec3_t m_size, force, torque;
NewtonBodyGetMassMatrix (body, &mass, &size[0], &size[1], &size[2]);
NewtonBodyGetMassMatrix (body, &mass, &m_size[0], &m_size[1], &m_size[2]);
VectorSet( torque, 0.0f, 0.0f, 0.0f );
VectorSet( force, 0.0f, -9.8f * mass, 0.0f );
@ -20,6 +20,12 @@ void Callback_ApplyForce( const NewtonBody* body )
NewtonBodyAddTorque (body, torque);
}
void Callback_PmoveApplyForce( const NewtonBody* body )
{
// grab state and jump to CM_ServerMove
pi.ClientMove((sv_edict_t *)NewtonBodyGetUserData( body ));
}
void Callback_ApplyTransform( const NewtonBody* body, const float* matrix )
{
sv_edict_t *edict = (sv_edict_t *)NewtonBodyGetUserData( body );

View File

@ -192,6 +192,20 @@ extern physic_t ph;
extern cvar_t *cm_noareas;
// test variables
extern int characterID;
extern uint m_jumpTimer;
extern bool m_isStopped;
extern bool m_isAirBorne;
extern float m_maxStepHigh;
extern float m_yawAngle;
extern float m_maxTranslation;
extern vec3_t m_size;
extern vec3_t m_stepContact;
extern vec3_t m_forceVector;
extern matrix4x4 m_matrix;
extern float *m_upVector;
//
// cm_test.c
//

View File

@ -1,26 +1,22 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
//=======================================================================
// Copyright XashXT Group 2007 ©
// cm_pmove.c - player movement code
//=======================================================================
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
#include "cm_local.h"
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "engine.h"
#include "pmove.h"
#include "mathlib.h"
int characterID;
uint m_jumpTimer;
bool m_isStopped;
bool m_isAirBorne;
float m_maxStepHigh;
float m_yawAngle;
float m_maxTranslation;
vec3_t m_size;
vec3_t m_stepContact;
vec3_t m_forceVector;
float *m_upVector;
matrix4x4 m_matrix;
#define PM_SPEED 160.f
#define STEPSIZE 18
@ -74,6 +70,16 @@ float pm_friction = 6.0f;
float pm_waterfriction = 1.0f;
float pm_flightfriction = 3.0f;
/*
==============================================================
PLAYER MOVEMENT CODE
Common between server and client so prediction matches
==============================================================
*/
/*
walking up a step should kill some velocity
*/
@ -108,7 +114,7 @@ void PM_AddTouchEnt( edict_t *entity )
{
int i;
if( pm->numtouch == MAXTOUCH )
if( pm->numtouch == PM_MAXTOUCH )
return;
// see if it is already added
@ -1474,7 +1480,7 @@ Pmove
Can be called by either the server or the client
================
*/
void Pmove( pmove_t *pmove )
void Quake_PMove( pmove_t *pmove )
{
pm = pmove;
@ -1584,4 +1590,232 @@ void Pmove( pmove_t *pmove )
pmove->cmd.upmove = 20;
}
//PM_CheckStuck();
}
void CM_CmdUpdateForce( usercmd_t *cmd )
{
m_forceVector[0] = cmd->forwardmove;// / 200;
m_forceVector[2] = cmd->sidemove;// / 200;
if( cmd->upmove != 0.0f)
{
m_jumpTimer = 4;
}
}
void CM_ServerMove( pmove_t *pmove )
{
float mass, Ixx, Iyy, Izz, dist, floor, accelY;
float newScale, deltaHeight, steerAngle, timestep, timestepInv;
vec3_t force, add_force, torque, omega, heading, velocity, step;
matrix4x4 matrix, collisionPaddingMatrix;
vec3_t head1, head2, vec_view, pin;
NewtonCollision *col;
NewtonBody *body;
pm = pmove;
body = pm->body;
PM_UpdateViewAngles( &pm->ps, &pm->cmd );
CM_CmdUpdateForce( &pm->cmd );
// get the current world timestep
timestep = NewtonGetTimeStep( gWorld );
timestepInv = 1.0f / timestep;
col = NewtonBodyGetCollision( body );
// get the character mass
NewtonBodyGetMassMatrix( body, &mass, &Ixx, &Iyy, &Izz);
VectorSet( force, 0.0f, mass * -9.8f, 0.0f);
NewtonBodyGetVelocity( body, &velocity[0] ); // get the velocity vector
NewtonBodyGetMatrix( body, &matrix[0][0] );
// if the floor is with in reach then the character must be snap to the ground
// the max allow distance for snapping i 0.25 of a meter
if( m_isAirBorne && !m_jumpTimer )
{
floor = CM_FindFloor( matrix[3], m_size[2] + 0.25f );
deltaHeight = (matrix[3][2] - m_size[2]) - floor;
if((deltaHeight < (0.25f - 0.001f)) && (deltaHeight > 0.01f))
{
// snap to floor only if the floor is lower than the character feet
accelY = - (deltaHeight * timestepInv + velocity[2]) * timestepInv;
force[2] = mass * accelY;
}
}
else if( m_jumpTimer == 4 ) //JUMP_TIMER
{
vec3_t veloc;
VectorSet( veloc, 0.0f, 0.4f, 0.0f );
NewtonAddBodyImpulse( body, &veloc[0], &matrix[3][0] );
}
m_jumpTimer = m_jumpTimer ? m_jumpTimer - 1 : 0;
// rotate the force direction to align with the camera
VectorIRotate( m_forceVector, m_matrix, heading );
newScale = 1.0f / sqrt( DotProduct(heading, heading) + 1.0e-6f );
VectorScale( heading, newScale, heading );
VectorScale( heading, mass * 30.0f, head1 );
VectorScale( heading, 2.0f * DotProduct( velocity, heading ), head2 );
VectorSubtract( head1, head2, add_force );
VectorAdd( force, add_force, force );
NewtonBodySetForce( body, &force[0] );
// estimate the final horizontal translation for to next force and velocity
VectorScale( force, timestep / mass, force );
VectorAdd( force, velocity, step );
VectorScale( step, timestep, step );
VectorSet( step, DotProduct(step, m_matrix[0]), DotProduct(step, m_matrix[2]), DotProduct(step, m_matrix[1]));
MatrixLoadIdentity( collisionPaddingMatrix );
step[2] = 0.0f;
dist = DotProduct( step, step );
if( dist > m_maxTranslation * m_maxTranslation )
{
matrix4x4 transp;
// when the velocity is high enough that can miss collision we will enlarge the collision
// long the vector velocity
dist = sqrt( dist );
VectorScale( step, 1.0f / dist, step );
// make a rotation matrix that will align the velocity vector with the front vector
collisionPaddingMatrix[0][0] = step[0];
collisionPaddingMatrix[0][2] = -step[2];
collisionPaddingMatrix[2][0] = step[2];
collisionPaddingMatrix[2][2] = step[0];
// get the transpose of the matrix
MatrixTranspose( transp, collisionPaddingMatrix );
VectorScale( transp[0], dist/m_maxTranslation, transp[0] );
// calculate and oblique scale matrix by using a similar transformation matrix of the for, R'* S * R
MatrixConcat( collisionPaddingMatrix, collisionPaddingMatrix, transp );
}
// set the collision modifierMatrix;
NewtonConvexHullModifierSetMatrix( col, &collisionPaddingMatrix[0][0] );
// calculate the torque vector
VectorMultiply( m_matrix[0], pm->ps.viewangles, vec_view );
steerAngle = bound( -1.0f, vec_view[2], -1.0f );
steerAngle = asin( steerAngle );
NewtonBodyGetOmega( body, &omega[0] );
VectorSet( torque, 0.0f, 0.5f * Iyy * (steerAngle * timestepInv - omega[2]) * timestepInv, 0.0f );
NewtonBodySetTorque( body, &torque[0] );
// assume the character is on the air. this variable will be set to false if the contact detect
//the character is landed
m_isAirBorne = true;
VectorSet( m_stepContact, 0.0f, -m_size[2], 0.0f );
VectorSet( pin, 0.0f, 1.0f, 0.0f);
NewtonUpVectorSetPin( m_upVector, &pin[0] );
}
void CM_ClientMove( pmove_t *pmove )
{
}
// find floor for character placement
float CM_FindFloor( vec3_t p0, float maxDist )
{
// shot a vertical ray from a high altitude and collected the intersection parameter.
vec3_t p1;
VectorCopy( p0, p1 );
p1[2] -= INCH2METER( maxDist ); // FIXME
NewtonWorldRayCast( gWorld, &p0[0], &p1[0], NULL, NULL );
// the intersection is the interpolated value
return p0[2] - maxDist * INCH2METER( 1.2f ); //FIXME
}
physbody_t *Phys_CreatePlayer( sv_edict_t *ed, cmodel_t *mod, matrix4x3 transform )
{
NewtonCollision *col, *hull;
NewtonBody *body;
matrix4x4 trans;
vec3_t radius, mins, maxs, upDirection;
if( !cm_physics_model->integer )
return NULL;
// setup matrixes
MatrixLoadIdentity( trans );
if( mod )
{
// player m_size
VectorCopy( mod->mins, mins );
VectorCopy( mod->maxs, maxs );
VectorSubtract( maxs, mins, m_size );
VectorScale( m_size, 0.5f, radius );
}
ConvertDimensionToPhysic( m_size );
ConvertDimensionToPhysic( radius );
VectorSet( m_stepContact, 0.0f, -m_size[2], 0.0f );
m_maxTranslation = m_size[0] * 0.25f;
m_maxStepHigh = -m_size[2] * 0.5f;
// setup translation matrix
VectorCopy( transform[0], trans[0] );
VectorCopy( transform[1], trans[1] );
VectorCopy( transform[2], trans[2] );
VectorCopy( transform[3], trans[3] );
trans[3][2] = CM_FindFloor( trans[3], 100 ) + radius[2]; // merge floor position
// place a sphere at the center
col = NewtonCreateSphere( gWorld, radius[0], radius[2], radius[1], NULL );
// wrap the character collision under a transform, modifier for tunneling trught walls avoidance
hull = NewtonCreateConvexHullModifier( gWorld, col );
NewtonReleaseCollision( gWorld, col );
body = NewtonCreateBody( gWorld, hull ); // create the rigid body
NewtonBodySetAutoFreeze( body, 0 ); // disable auto freeze management for the player
NewtonWorldUnfreezeBody( gWorld, body ); // keep the player always active
// reset angular and linear damping
NewtonBodySetLinearDamping( body, 0.0f );
NewtonBodySetAngularDamping( body, vec3_origin );
NewtonBodySetMaterialGroupID( body, characterID );// set material Id for this object
// setup generic callback to engine.dll
NewtonBodySetUserData( body, ed );
NewtonBodySetTransformCallback( body, Callback_ApplyTransform );
NewtonBodySetForceAndTorqueCallback( body, Callback_PmoveApplyForce );
NewtonBodySetMassMatrix( body, 10.0f, m_size[0], m_size[1], m_size[2] ); // 10 kg
NewtonBodySetMatrix(body, &trans[0][0] );// origin
// release the collision geometry when not need it
NewtonReleaseCollision( gWorld, hull );
// add and up vector constraint to help in keeping the body upright
VectorSet( upDirection, 0.0f, 1.0f, 0.0f );
m_upVector = (float *)NewtonConstraintCreateUpVector( gWorld, &upDirection[0], body );
return (physbody_t *)body;
}
/*
===============================================================================
PMOVE ENTRY POINT
===============================================================================
*/
void CM_PlayerMove( pmove_t *pmove, bool clientmove )
{
if( !cm_physics_model->integer )
Quake_PMove( pmove );
}

View File

@ -57,5 +57,10 @@ int CM_LeafArea( int leafnum );
bool CM_AreasConnected( int area1, int area2 );
int CM_WriteAreaBits( byte *buffer, int area );
void CM_ModelBounds( cmodel_t *model, vec3_t mins, vec3_t maxs );
float CM_FindFloor( vec3_t p0, float maxDist );
void CM_PlayerMove( pmove_t *pmove, bool clientmove );
void CM_ServerMove( pmove_t *pmove );
void CM_ClientMove( pmove_t *pmove );
#endif//CM_UTILS_H

View File

@ -15,17 +15,19 @@ NewtonWorld *gWorld;
cvar_t *cm_use_triangles;
cvar_t *cm_solver_model;
cvar_t *cm_friction_model;
cvar_t *cm_physics_model;
bool InitPhysics( void )
{
physpool = Mem_AllocPool("Physics Pool");
cmappool = Mem_AllocPool("CM Zone");
gWorld = NewtonCreate (Palloc, Pfree); // alloc world
gWorld = NewtonCreate( Palloc, Pfree ); // alloc world
cm_noareas = Cvar_Get( "cm_noareas", "0", 0 );
cm_use_triangles = Cvar_Get("cm_convert_polygons", "1", CVAR_INIT|CVAR_SYSTEMINFO );//, "convert bsp polygons to triangles, slowly but more safety way" );
cm_solver_model = Cvar_Get("cm_solver", "0", CVAR_ARCHIVE );//, "change solver model: 0 - precision, 1 - adaptive, 2 - fast. (changes need restart server to take effect)" );
cm_friction_model = Cvar_Get("cm_friction", "0", CVAR_ARCHIVE );//, "change solver model: 0 - precision, 1 - adaptive. (changes need restart server to take effect)" );
cm_physics_model = Cvar_Get("cm_physic", "1", CVAR_ARCHIVE );//, "change physic model: 0 - Classic Quake Physic, 1 - Physics Engine" );
return true;
}
@ -91,6 +93,12 @@ physic_exp_t DLLEXPORT *CreateAPI ( stdlib_api_t *input, physic_imp_t *engfuncs
Phys.Frame = PhysFrame;
Phys.CreateBody = Phys_CreateBody;
Phys.CreatePlayer = Phys_CreatePlayer;
Phys.PlayerMove = CM_PlayerMove;
Phys.ServerMove = CM_ServerMove;
Phys.ClientMove = CM_ClientMove;
Phys.GetForce = Phys_GetForce;
Phys.SetForce = Phys_SetForce;
Phys.GetMassCentre = Phys_GetMassCentre;

View File

@ -56,8 +56,8 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 user32.lib msvcrt.lib newton.lib opengl32.lib /nologo /dll /pdb:none /machine:I386 /nodefaultlib:"libc.lib" /libpath:"../public/libs/"
# Begin Custom Build
TargetDir=\XASH3D\src_main\temp\physic\!release
InputPath=\XASH3D\src_main\temp\physic\!release\physic.dll
TargetDir=\Xash3D\src_main\temp\physic\!release
InputPath=\Xash3D\src_main\temp\physic\!release\physic.dll
SOURCE="$(InputPath)"
"D:\Xash3D\bin\physic.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
@ -93,8 +93,8 @@ LINK32=link.exe
# ADD LINK32 user32.lib msvcrtd.lib newton.lib opengl32.lib /nologo /dll /debug /machine:I386 /nodefaultlib:"libc.lib" /pdbtype:sept /libpath:"../public/libs/"
# SUBTRACT LINK32 /nodefaultlib
# Begin Custom Build
TargetDir=\XASH3D\src_main\temp\physic\!debug
InputPath=\XASH3D\src_main\temp\physic\!debug\physic.dll
TargetDir=\Xash3D\src_main\temp\physic\!debug
InputPath=\Xash3D\src_main\temp\physic\!debug\physic.dll
SOURCE="$(InputPath)"
"D:\Xash3D\bin\physic.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
@ -125,6 +125,10 @@ SOURCE=.\cm_model.c
# End Source File
# Begin Source File
SOURCE=.\cm_pmove.c
# End Source File
# Begin Source File
SOURCE=.\cm_portals.c
# End Source File
# Begin Source File

View File

@ -30,6 +30,7 @@ extern NewtonWorld *gWorld;
extern cvar_t *cm_use_triangles;
extern cvar_t *cm_solver_model;
extern cvar_t *cm_friction_model;
extern cvar_t *cm_physics_model; // 0 - classic Quake Physic, 1 - Newton Physic
long _ftol2( double dblSource );
void Phys_LoadBSP( uint *buffer );
@ -41,6 +42,7 @@ void Phys_Frame( float time );
// cm_rigidbody.c
//
physbody_t *Phys_CreateBody( sv_edict_t *ed, cmodel_t *mod, matrix4x3 transform, int solid );
physbody_t *Phys_CreatePlayer( sv_edict_t *ed, cmodel_t *mod, matrix4x3 transform );
bool Phys_GetForce( physbody_t *body, vec3_t velocity, vec3_t avelocity, vec3_t force, vec3_t torque );
void Phys_SetForce( physbody_t *body, vec3_t velocity, vec3_t avelocity, vec3_t force, vec3_t torque );
bool Phys_GetMassCentre( physbody_t *body, matrix3x3 mass );
@ -51,6 +53,7 @@ void Phys_RemoveBody( physbody_t *body );
// cm_callback.c
//
void Callback_ApplyForce( const NewtonBody* body );
void Callback_PmoveApplyForce( const NewtonBody* body );
void Callback_ApplyTransform( const NewtonBody* body, const float* matrix );
#define Host_Error com.error

View File

@ -29,6 +29,74 @@
#define RDF_IRGOGGLES 2
#define RDF_PAIN 4
// encoded bmodel mask
#define SOLID_BMODEL 0xffffff
// content masks
#define MASK_ALL (-1)
#define MASK_SOLID (CONTENTS_SOLID|CONTENTS_WINDOW)
#define MASK_PLAYERSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER)
#define MASK_DEADSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW)
#define MASK_MONSTERSOLID (CONTENTS_SOLID|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER)
#define MASK_WATER (CONTENTS_WATER|CONTENTS_LAVA|CONTENTS_SLIME)
#define MASK_OPAQUE (CONTENTS_SOLID|CONTENTS_SLIME|CONTENTS_LAVA)
#define MASK_SHOT (CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEADMONSTER)
#define MASK_CURRENT (CONTENTS_CURRENT_0|CONTENTS_CURRENT_90|CONTENTS_CURRENT_180|CONTENTS_CURRENT_270|CONTENTS_CURRENT_UP|CONTENTS_CURRENT_DOWN)
// pmove_state_t is the information necessary for client side movement
#define PM_NORMAL 0 // can accelerate and turn
#define PM_SPECTATOR 1
#define PM_DEAD 2 // no acceleration or turning
#define PM_GIB 3 // different bounding box
#define PM_FREEZE 4
#define PM_INTERMISSION 5
#define PM_NOCLIP 6
// pmove->pm_flags
#define PMF_DUCKED 1
#define PMF_JUMP_HELD 2
#define PMF_ON_GROUND 4
#define PMF_TIME_WATERJUMP 8 // pm_time is waterjump
#define PMF_TIME_LAND 16 // pm_time is time before rejump
#define PMF_TIME_TELEPORT 32 // pm_time is non-moving time
#define PMF_NO_PREDICTION 64 // temporarily disables prediction (used for grappling hook)
#define PMF_ALL_TIMES (PMF_TIME_WATERJUMP|PMF_TIME_LAND|PMF_TIME_TELEPORT)
// button bits
#define BUTTON_ATTACK 1
#define BUTTON_USE 2
#define BUTTON_ATTACK2 4
#define BUTTONS_ATTACK (BUTTON_ATTACK | BUTTON_ATTACK2)
#define BUTTON_ANY 128 // any key whatsoever
#define PM_MAXTOUCH 32
// player_state->stats[] indexes
enum player_stats
{
STAT_HEALTH_ICON = 0,
STAT_HEALTH,
STAT_AMMO_ICON,
STAT_AMMO,
STAT_ARMOR_ICON,
STAT_ARMOR,
STAT_SELECTED_ICON,
STAT_PICKUP_ICON,
STAT_PICKUP_STRING,
STAT_TIMER_ICON,
STAT_TIMER,
STAT_HELPICON,
STAT_SELECTED_ITEM,
STAT_LAYOUTS,
STAT_FRAGS,
STAT_FLASHES, // cleared each frame, 1 = health, 2 = armor
STAT_CHASE,
STAT_SPECTATOR,
STAT_SPEED = 22,
STAT_ZOOM,
MAX_STATS = 32,
};
typedef enum
{
R_BEAM,
@ -145,6 +213,92 @@ typedef struct
} refdef_t;
// viewmodel state
typedef struct vmodel_state_s
{
int index; // client modelindex
vec3_t angles; // can be some different with viewangles
vec3_t offset; // center offset
int sequence; // studio animation sequence
int frame; // studio frame
int body; // weapon body
int skin; // weapon skin
} vmodel_state_t;
// thirdperson model state
typedef struct pmodel_state_s
{
int index; // client modelindex
int sequence; // studio animation sequence
int frame; // studio frame
} pmodel_state_t;
// player_state_t communication
typedef struct player_state_s
{
int bobcycle; // for view bobbing and footstep generation
float bobtime;
byte pm_type; // player movetype
byte pm_flags; // ducked, jump_held, etc
byte pm_time; // each unit = 8 ms
vec3_t origin;
vec3_t velocity;
vec3_t delta_angles; // add to command angles to get view direction
short gravity; // gravity value
short speed; // maxspeed
edict_t *groundentity; // current ground entity
int viewheight; // height over ground
int effects; // copied to entity_state_t->effects
int weapon; // copied to entity_state_t->weapon
vec3_t viewangles; // for fixed views
vec3_t viewoffset; // add to pmovestate->origin
vec3_t kick_angles; // add to view direction to get render angles
vec3_t oldviewangles; // for lerping viewmodel position
vec4_t blend; // rgba full screen effect
short stats[MAX_STATS];
float fov; // horizontal field of view
// player model and viewmodel
vmodel_state_t vmodel;
pmodel_state_t pmodel;
} player_state_t;
// user_cmd_t communication
typedef struct usercmd_s
{
byte msec;
byte buttons;
short angles[3];
byte impulse; // remove?
byte lightlevel; // light level the player is standing on
short forwardmove, sidemove, upmove;
} usercmd_t;
typedef struct pmove_s
{
player_state_t ps; // state (in / out)
// command (in)
usercmd_t cmd;
physbody_t *body; // pointer to physobject
// results (out)
int numtouch;
edict_t *touchents[PM_MAXTOUCH]; // max touch
vec3_t mins, maxs; // bounding box size
int watertype;
int waterlevel;
float xyspeed; // avoid to compute it twice
// callbacks to test the world
trace_t (*trace)( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end );
int (*pointcontents)( vec3_t point );
} pmove_t;
/*
==============================================================================
@ -283,9 +437,17 @@ typedef struct physic_exp_s
int (*LeafArea)( int leafnum );
bool (*AreasConnected)( int area1, int area2 );
int (*WriteAreaBits)( byte *buffer, int area );
// player movement code
void (*PlayerMove)( pmove_t *pmove, bool clientmove );
void (*ServerMove)( pmove_t *pmove );
void (*ClientMove)( pmove_t *pmove );
// simple objects
physbody_t *(*CreateBody)( sv_edict_t *ed, cmodel_t *mod, matrix4x3 transform, int solid );
physbody_t *(*CreatePlayer)( sv_edict_t *ed, cmodel_t *mod, matrix4x3 transform );
bool (*GetForce)(physbody_t *body, vec3_t vel, vec3_t avel, vec3_t force, vec3_t torque );
void (*SetForce)(physbody_t *body, vec3_t vel, vec3_t avel, vec3_t force, vec3_t torque );
bool (*GetMassCentre)( physbody_t *body, matrix3x3 mass );
@ -298,6 +460,7 @@ typedef struct physic_imp_s
// interface validator
size_t api_size; // must matched with sizeof(physic_imp_t)
void (*ClientMove)( sv_edict_t *ed );
void (*Transform)( sv_edict_t *ed, matrix4x3 transform );
float *(*GetModelVerts)( sv_edict_t *ent, int *numvertices );
} physic_imp_t;

View File

@ -307,6 +307,26 @@ _inline void VectorVectors(vec3_t forward, vec3_t right, vec3_t up)
CrossProduct(right, forward, up);
}
_inline void MatrixTranspose( matrix4x4 out, const matrix4x4 in1 )
{
out[0][0] = in1[0][0];
out[0][1] = in1[1][0];
out[0][2] = in1[2][0];
out[0][3] = in1[3][0];
out[1][0] = in1[0][1];
out[1][1] = in1[1][1];
out[1][2] = in1[2][1];
out[1][3] = in1[3][1];
out[2][0] = in1[0][2];
out[2][1] = in1[1][2];
out[2][2] = in1[2][2];
out[2][3] = in1[3][2];
out[3][0] = in1[0][3];
out[3][1] = in1[1][3];
out[3][2] = in1[2][3];
out[3][3] = in1[3][3];
}
_inline void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
{
float angle;
@ -837,6 +857,26 @@ _inline void R_ConcatTransforms( matrix3x4 in1, matrix3x4 in2, matrix3x4 out )
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
}
_inline void MatrixConcat( matrix4x4 out, const matrix4x4 in1, const matrix4x4 in2 )
{
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0] + in1[0][3] * in2[3][0];
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1] + in1[0][3] * in2[3][1];
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2] + in1[0][3] * in2[3][2];
out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3] * in2[3][3];
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0] + in1[1][3] * in2[3][0];
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1] + in1[1][3] * in2[3][1];
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2] + in1[1][3] * in2[3][2];
out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3] * in2[3][3];
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0] + in1[2][3] * in2[3][0];
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1] + in1[2][3] * in2[3][1];
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2] + in1[2][3] * in2[3][2];
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3] * in2[3][3];
out[3][0] = in1[3][0] * in2[0][0] + in1[3][1] * in2[1][0] + in1[3][2] * in2[2][0] + in1[3][3] * in2[3][0];
out[3][1] = in1[3][0] * in2[0][1] + in1[3][1] * in2[1][1] + in1[3][2] * in2[2][1] + in1[3][3] * in2[3][1];
out[3][2] = in1[3][0] * in2[0][2] + in1[3][1] * in2[1][2] + in1[3][2] * in2[2][2] + in1[3][3] * in2[3][2];
out[3][3] = in1[3][0] * in2[0][3] + in1[3][1] * in2[1][3] + in1[3][2] * in2[2][3] + in1[3][3] * in2[3][3];
}
_inline void TransformRGB( vec3_t in, vec3_t out )
{
out[0] = in[0]/255.0f;

View File

@ -21,6 +21,9 @@ fopen
1. Способность виртуальной машины игнорировать проги
Физика игрока:
1. Чтобы капсула не падала необходимо создать UpVectorConstraint
Список файлов на сервере: