core/smn_vector.cpp
author David Anderson <dvander@alliedmods.net>
Sun Oct 21 17:58:35 2007 +0000 (2007-10-21)
changeset 1620 fd5c786ca8e5
parent 1553 164d888e1d9f
child 1871 a152bfe8634b
permissions -rw-r--r--
atcprintf() is now fully re-entrant, meaning translations can be used from inside translations
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "sm_globals.h"
    33 #include <vector.h>
    34 #include <mathlib/math_base.h>
    35 
    36 #define SET_VECTOR(addr, vec) \
    37 	addr[0] = sp_ftoc(vec.x); \
    38 	addr[1] = sp_ftoc(vec.y); \
    39 	addr[2] = sp_ftoc(vec.z); 
    40 
    41 static cell_t GetVectorLength(IPluginContext *pContext, const cell_t *params)
    42 {
    43 	cell_t *addr;
    44 
    45 	pContext->LocalToPhysAddr(params[1], &addr);
    46 
    47 	Vector source(sp_ctof(addr[0]), sp_ctof(addr[1]), sp_ctof(addr[2]));
    48 	
    49 	if (!params[2])
    50 	{
    51 		return sp_ftoc(source.Length());
    52 	} else {
    53 		return sp_ftoc(source.LengthSqr());
    54 	}
    55 }
    56 
    57 static cell_t GetVectorDistance(IPluginContext *pContext, const cell_t *params)
    58 {
    59 	cell_t *addr1, *addr2;
    60 
    61 	pContext->LocalToPhysAddr(params[1], &addr1);
    62 	pContext->LocalToPhysAddr(params[2], &addr2);
    63 
    64 	Vector source(sp_ctof(addr1[0]), sp_ctof(addr1[1]), sp_ctof(addr1[2]));
    65 	Vector dest(sp_ctof(addr2[0]), sp_ctof(addr2[1]), sp_ctof(addr2[2]));
    66 
    67 	if (!params[3])
    68 	{
    69 		return sp_ftoc(source.DistTo(dest));
    70 	} else {
    71 		return sp_ftoc(source.DistToSqr(dest));
    72 	}
    73 }
    74 
    75 static cell_t GetVectorDotProduct(IPluginContext *pContext, const cell_t *params)
    76 {
    77 	cell_t *addr1, *addr2;
    78 
    79 	pContext->LocalToPhysAddr(params[1], &addr1);
    80 	pContext->LocalToPhysAddr(params[2], &addr2);
    81 
    82 	Vector source(sp_ctof(addr1[0]), sp_ctof(addr1[1]), sp_ctof(addr1[2]));
    83 	Vector dest(sp_ctof(addr2[0]), sp_ctof(addr2[1]), sp_ctof(addr2[2]));
    84 
    85 	return sp_ftoc(source.Dot(dest));
    86 }
    87 
    88 static cell_t GetVectorCrossProduct(IPluginContext *pContext, const cell_t *params)
    89 {
    90 	cell_t *addr1, *addr2, *set;
    91 
    92 	pContext->LocalToPhysAddr(params[1], &addr1);
    93 	pContext->LocalToPhysAddr(params[2], &addr2);
    94 	pContext->LocalToPhysAddr(params[3], &set);
    95 
    96 	Vector vec1(sp_ctof(addr1[0]), sp_ctof(addr1[1]), sp_ctof(addr1[2]));
    97 	Vector vec2(sp_ctof(addr2[0]), sp_ctof(addr2[1]), sp_ctof(addr2[2]));
    98 
    99 	Vector vec3 = vec1.Cross(vec2);
   100 
   101 	SET_VECTOR(set, vec3);
   102 
   103 	return 1;
   104 }
   105 
   106 static cell_t GetAngleVectors(IPluginContext *pContext, const cell_t *params)
   107 {
   108 	cell_t *ang_addr;
   109 
   110 	pContext->LocalToPhysAddr(params[1], &ang_addr);
   111 
   112 	QAngle angle(sp_ctof(ang_addr[0]), sp_ctof(ang_addr[1]), sp_ctof(ang_addr[2]));
   113 	Vector fwd, right, up;
   114 
   115 	AngleVectors(angle, &fwd, &right, &up);
   116 
   117 	cell_t *addr_fwd, *addr_right, *addr_up;
   118 	pContext->LocalToPhysAddr(params[2], &addr_fwd);
   119 	pContext->LocalToPhysAddr(params[3], &addr_right);
   120 	pContext->LocalToPhysAddr(params[4], &addr_up);
   121 
   122 	SET_VECTOR(addr_fwd, fwd);
   123 	SET_VECTOR(addr_right, right);
   124 	SET_VECTOR(addr_up, up);
   125 
   126 	return 1;
   127 }
   128 
   129 static cell_t GetVectorAngles(IPluginContext *pContext, const cell_t *params)
   130 {
   131 	cell_t *vec_addr;
   132 
   133 	pContext->LocalToPhysAddr(params[1], &vec_addr);
   134 
   135 	Vector vec(sp_ctof(vec_addr[0]), sp_ctof(vec_addr[1]), sp_ctof(vec_addr[2]));
   136 	QAngle angle;
   137 
   138 	VectorAngles(vec, angle);
   139 
   140 	cell_t *ang_addr;
   141 	pContext->LocalToPhysAddr(params[2], &ang_addr);
   142 
   143 	SET_VECTOR(ang_addr, angle);
   144 
   145 	return 1;
   146 }
   147 
   148 static cell_t GetVectorVectors(IPluginContext *pContext, const cell_t *params)
   149 {
   150 	cell_t *vec_addr;
   151 
   152 	pContext->LocalToPhysAddr(params[1], &vec_addr);
   153 
   154 	Vector vec(sp_ctof(vec_addr[0]), sp_ctof(vec_addr[1]), sp_ctof(vec_addr[2]));
   155 	Vector right, up;
   156 
   157 	VectorVectors(vec, right, up);
   158 
   159 	cell_t *addr_right, *addr_up;
   160 	pContext->LocalToPhysAddr(params[2], &addr_right);
   161 	pContext->LocalToPhysAddr(params[3], &addr_up);
   162 
   163 	SET_VECTOR(addr_right, right);
   164 	SET_VECTOR(addr_up, up);
   165 
   166 	return 1;
   167 }
   168 
   169 static cell_t NormalizeVector(IPluginContext *pContext, const cell_t *params)
   170 {
   171 	cell_t *addr;
   172 
   173 	pContext->LocalToPhysAddr(params[1], &addr);
   174 
   175 	Vector source(sp_ctof(addr[0]), sp_ctof(addr[1]), sp_ctof(addr[2]));
   176 	float length = VectorNormalize(source);
   177 
   178 	pContext->LocalToPhysAddr(params[2], &addr);
   179 	SET_VECTOR(addr, source);
   180 
   181 	return sp_ftoc(length);
   182 }
   183 
   184 //:TODO: OMG remove this when we get the OB SDK!!1
   185 // as well as bitbuf.cpp (i write it here just to remind it)
   186 #if defined ORANGEBOX_BUILD && !defined __linux__
   187 float ham(float _X)
   188 {
   189 	return sqrt(_X); 
   190 }
   191 float (*pfSqrt)(float x)  = ham;
   192 #endif
   193 
   194 REGISTER_NATIVES(vectorNatives)
   195 {
   196 	{"GetAngleVectors",			GetAngleVectors},
   197 	{"GetVectorAngles",			GetVectorAngles},
   198 	{"GetVectorCrossProduct",	GetVectorCrossProduct},
   199 	{"GetVectorDistance",		GetVectorDistance},
   200 	{"GetVectorDotProduct",		GetVectorDotProduct},
   201 	{"GetVectorLength",			GetVectorLength},
   202 	{"GetVectorVectors",		GetVectorVectors},
   203 	{"NormalizeVector",			NormalizeVector},
   204 	{NULL,					NULL}
   205 };