Merge remote-tracking branch 'origin/dev_item_normal' into dev

This commit is contained in:
Benau 2018-11-15 12:43:09 +08:00
commit ec7216361d
8 changed files with 98 additions and 48 deletions

View File

@ -74,10 +74,13 @@ void ItemState::setDisappearCounter()
// -----------------------------------------------------------------------
/** Initialises an item.
* \param type Type for this item.
* \param xyz The position for this item.
* \param normal The normal for this item.
*/
void ItemState::initItem(ItemType type, const Vec3& xyz)
void ItemState::initItem(ItemType type, const Vec3& xyz, const Vec3& normal)
{
m_xyz = xyz;
m_normal = normal;
m_original_type = ITEM_NONE;
m_ticks_till_return = 0;
setDisappearCounter();
@ -156,7 +159,7 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
m_was_available_previously = true;
m_distance_2 = 1.2f;
initItem(type, xyz);
initItem(type, xyz, normal);
m_graphical_type = type;
m_original_rotation = shortestArcQuat(Vec3(0, 1, 0), normal);
m_listener = NULL;
@ -206,7 +209,7 @@ Item::Item(const Vec3& xyz, float distance, TriggerItemListener* trigger)
: ItemState(ITEM_TRIGGER)
{
m_distance_2 = distance*distance;
initItem(ITEM_TRIGGER, xyz);
initItem(ITEM_TRIGGER, xyz, /*normal not required*/Vec3(0,0,0));
m_graphical_type = ITEM_TRIGGER;
m_original_rotation = btQuaternion(0, 0, 0, 1);
m_node = NULL;
@ -218,10 +221,12 @@ Item::Item(const Vec3& xyz, float distance, TriggerItemListener* trigger)
/** Initialises the item. Note that m_distance_2 must be defined before calling
* this function, since it pre-computes some values based on this.
* \param type Type of the item.
* \param xyz Position of this item.
* \param normal Normal for this item.
*/
void Item::initItem(ItemType type, const Vec3 &xyz)
void Item::initItem(ItemType type, const Vec3 &xyz, const Vec3&normal)
{
ItemState::initItem(type, xyz);
ItemState::initItem(type, xyz, normal);
// Now determine in which quad this item is, and its distance
// from the center within this quad.
m_graph_node = Graph::UNKNOWN_SECTOR;

View File

@ -119,10 +119,17 @@ private:
* will always reappear after a while. */
int m_used_up_counter;
/** The original position - saves calls to m_node->getPosition()
* and then converting this value to a Vec3. */
/** The position of this ItemState. */
Vec3 m_xyz;
/** The original rotation of the item. While this is technically a visual
* only value (atm, it could be used for collision detection), it is
* required to make sure a client can display items with the right normal
* (in case that a client would get a different (or no) normal from a
* raycast).
*/
Vec3 m_normal;
/** The 'owner' of the item, i.e. the kart that dropped this item.
* Is NULL if the item is part of the track. */
const AbstractKart *m_previous_owner;
@ -154,7 +161,7 @@ protected:
public:
ItemState(ItemType type, const AbstractKart *owner=NULL, int id = -1);
void initItem(ItemType type, const Vec3& xyz);
void initItem(ItemType type, const Vec3& xyz, const Vec3& normal);
void update(int ticks);
void setDisappearCounter();
virtual void collected(const AbstractKart *kart);
@ -305,6 +312,12 @@ public:
// ------------------------------------------------------------------------
/** Returns the XYZ position of the item. */
const Vec3& getXYZ() const { return m_xyz; }
// ------------------------------------------------------------------------
/** Returns the normal of the ItemState. */
const Vec3 getNormal() const
{
return m_normal;
}
}; // class ItemState
// ============================================================================
@ -350,7 +363,7 @@ private:
* would not be collected. Used by the AI to avoid items. */
Vec3 *m_avoidance_points[2];
void initItem(ItemType type, const Vec3 &xyz);
void initItem(ItemType type, const Vec3 &xyz, const Vec3 &normal);
void setMesh(scene::IMesh* mesh, scene::IMesh* lowres_mesh);
void handleNewMesh(ItemType type);
@ -432,6 +445,12 @@ public:
return m_avoidance_points[1];
} // getAvoidancePoint
// ------------------------------------------------------------------------
/** Returns the normal of the item. */
const Vec3 getNormal() const
{
return quatRotate(m_original_rotation, Vec3(0,1,0));
}
// ------------------------------------------------------------------------
scene::ISceneNode *getSceneNode()
{

View File

@ -43,7 +43,8 @@ ItemEventInfo::ItemEventInfo(BareNetworkString *buffer, int *count)
if (m_type == IEI_NEW)
{
m_xyz = buffer->getVec3();
*count -= 12;
m_normal = buffer->getVec3();
*count -= 24;
}
else // IEI_COLLECT
{
@ -71,7 +72,10 @@ void ItemEventInfo::saveState(BareNetworkString *buffer)
// Only new item and collecting items need the index and kart id:
buffer->addUInt8(m_kart_id).addUInt16(m_index);
if (m_type == IEI_NEW)
{
buffer->add(m_xyz);
buffer->add(m_normal);
}
else if (m_type == IEI_COLLECT)
buffer->addUInt16(m_ticks_till_return);
}

View File

@ -52,6 +52,9 @@ private:
/** In case of new items the position of the new item. */
Vec3 m_xyz;
/** The normal of an item. */
Vec3 m_normal;
/** Ticks for the item to return, atm used by collecting banana
* with bomb to delay the return for banana. */
int16_t m_ticks_till_return;
@ -76,9 +79,9 @@ public:
* need to encode the new item type.
*/
ItemEventInfo(int ticks, ItemState::ItemType type, int index,
int kart_id, const Vec3 &xyz)
int kart_id, const Vec3 &xyz, const Vec3 &normal)
: m_ticks(ticks), m_index(index), m_kart_id(kart_id), m_xyz(xyz),
m_ticks_till_return(0)
m_normal(normal), m_ticks_till_return(0)
{
m_type = IEI_NEW;
} // ItemEventInfo(new item)
@ -125,6 +128,13 @@ public:
return m_xyz;
} // getXYZ
// --------------------------------------------------------------------
/** Returns the normal of a new item only. */
const Vec3& getNormal() const
{
assert(isNewItem());
return m_normal;
} // getNormal
// --------------------------------------------------------------------
/** Returns the ticks till return, used only by collection events. */
int getTicksTillReturn() const { return m_ticks_till_return; }
// --------------------------------------------------------------------

View File

@ -257,42 +257,43 @@ unsigned int ItemManager::insertItem(Item *item)
* bubblegum).
* \param type Type of the item.
* \param kart The kart that drops the new item.
* \param xyz Can be used to overwrite the item location (used in networking).
* \param server_xyz Can be used to overwrite the item location.
* \param server_normal The normal as seen on the server.
*/
Item* ItemManager::dropNewItem(ItemState::ItemType type,
const AbstractKart *kart, const Vec3 *xyz)
const AbstractKart *kart,
const Vec3 *server_xyz,
const Vec3 *server_normal)
{
Vec3 hit_point;
Vec3 normal;
if(NetworkConfig::get()->isClient() && !server_xyz) return NULL;
Vec3 normal, pos;
const Material* material_hit;
Vec3 pos = xyz ? *xyz : kart->getXYZ();
Vec3 to = pos + kart->getTrans().getBasis() * Vec3(0, -10000, 0);
Track::getCurrentTrack()->getTriangleMesh().castRay(pos, to,
&hit_point,
&material_hit,
&normal);
// We will get no material if the kart is 'over nothing' when dropping
// the bubble gum. In most cases this means that the item does not need
// to be created (and we just return NULL). Only exception: if the server
// has sent a 'new item' event (which means its raycast found terrain),
// but the client does not have found a terrain (e.g. differences in
// position or more likely floating point differences). In this case, we
// must use the server position. In this and only this case xyz is not
// NULL (and then contains the server's position for the item).
if (!material_hit && !xyz) return NULL;
if (!material_hit)
if (!server_xyz)
{
// We are on a client which has received a new item event. Still
// create this item
normal.setValue(0, 1, 0); // Arbitrary, we don't have a normal
pos = *xyz;
// We are doing a new drop locally, i.e. not based on
// server data. So we need a raycast to find the correct
// location and normal of the item:
pos = server_xyz ? *server_xyz : kart->getXYZ();
Vec3 to = pos + kart->getTrans().getBasis() * Vec3(0, -10000, 0);
Vec3 hit_point;
Track::getCurrentTrack()->getTriangleMesh().castRay(pos, to,
&hit_point,
&material_hit,
&normal);
// We will get no material if the kart is 'over nothing' when dropping
// the bubble gum. In most cases this means that the item does not need
// to be created (and we just return NULL).
if (!material_hit) return NULL;
normal.normalize();
pos = hit_point + kart->getTrans().getBasis() * Vec3(0, -0.05f, 0);
}
else
{
normal.normalize();
pos = hit_point + kart->getTrans().getBasis() * Vec3(0, -0.05f, 0);
// We are on a client which has received a new item event from the
// server. So use the server's data for the new item:
normal = *server_normal;
pos = *server_xyz;
}
ItemState::ItemType mesh_type = type;

View File

@ -133,7 +133,9 @@ public:
virtual Item* placeItem (ItemState::ItemType type, const Vec3& xyz,
const Vec3 &normal);
virtual Item* dropNewItem (ItemState::ItemType type,
const AbstractKart* parent, const Vec3 *xyz=NULL);
const AbstractKart* parent,
const Vec3 *server_xyz = NULL,
const Vec3 *normal = NULL);
virtual Item* placeTrigger (const Vec3& xyz, float distance,
TriggerItemListener* listener);
void update (int ticks);

View File

@ -148,23 +148,29 @@ void NetworkItemManager::switchItems()
* \param type Type of the item.
* \param kart In case of a dropped item used to avoid that a kart
* is affected by its own items.
* \param server_xyz In case of rewind the server's position of this item.
* \param server_normal In case of rewind the server's normal of this item.
*/
Item* NetworkItemManager::dropNewItem(ItemState::ItemType type,
const AbstractKart *kart, const Vec3 *xyz)
const AbstractKart *kart,
const Vec3 *server_xyz,
const Vec3 *server_normal)
{
Item *item = ItemManager::dropNewItem(type, kart, xyz);
Item *item = ItemManager::dropNewItem(type, kart, server_xyz, server_normal);
if(!item) return NULL;
// Nothing else to do for client
if (NetworkConfig::get()->isClient()) return item;
assert(!server_xyz);
// Server: store the data for this event:
m_item_events.lock();
m_item_events.getData().emplace_back(World::getWorld()->getTicksSinceStart(),
type, item->getItemId(),
kart->getWorldKartId(),
xyz ? *xyz : kart->getXYZ() );
item->getXYZ(),
item->getNormal());
m_item_events.unlock();
return item;
} // dropNewItem
@ -409,7 +415,7 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
AbstractKart *kart = world->getKart(iei.getKartId());
ItemState *is = new ItemState(iei.getNewItemType(), kart,
iei.getIndex() );
is->initItem(iei.getNewItemType(), iei.getXYZ());
is->initItem(iei.getNewItemType(), iei.getXYZ(), iei.getNormal());
if (m_switch_ticks >= 0)
{
ItemState::ItemType new_type = m_switch_to[is->getType()];
@ -491,8 +497,9 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
// A new item was dropped according to the server that is not
// yet part of the current state --> create new item
Vec3 xyz = is->getXYZ();
Vec3 normal = is->getNormal();
Item *item_new = dropNewItem(is->getType(), is->getPreviousOwner(),
&xyz);
&xyz, &normal );
if (i != item_new->getItemId())
{
// The newly created item on the client has been given a

View File

@ -80,8 +80,10 @@ public:
int ticks) OVERRIDE;
virtual void collectedItem(ItemState *item, AbstractKart *kart) OVERRIDE;
virtual void switchItems() OVERRIDE;
virtual Item* dropNewItem(ItemState::ItemType type, const AbstractKart *kart,
const Vec3 *xyz=NULL) OVERRIDE;
virtual Item* dropNewItem(ItemState::ItemType type,
const AbstractKart *kart,
const Vec3 *server_xyz = NULL,
const Vec3 *server_normal = NULL) OVERRIDE;
virtual BareNetworkString* saveState(std::vector<std::string>* ru)
OVERRIDE;
virtual void restoreState(BareNetworkString *buffer, int count) OVERRIDE;