Files
pvvmud/common/lib/gos/msggos.C
2025-03-05 08:37:43 +01:00

375 lines
10 KiB
C

/*
* PVVMUD a 3D MUD
* Copyright (C) 1998-1999 Programvareverkstedet (pvv@pvv.org)
*
* 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.
*
* 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 "pvvmud.H"
#include <stdlib.h>
#include <iostream.h>
#include "msggos.H"
#include "texture.H"
///////////////////////////////////////////////////////////////////////////////
// MsgGOSError
CMsgGOSError::CMsgGOSError():CMessage(MSG_GOSERROR, sizeof(BYTE)){
setName("MsgGOSError");
writeByte(1,0); // Error
}
CMsgGOSError::CMsgGOSError(BYTE error):CMessage(MSG_GOSERROR, sizeof(BYTE)){
setName("MsgGOSError");
writeByte(1,error);
}
BYTE CMsgGOSError::getError(){
return readByte(1);
}
///////////////////////////////////////////////////////////////////////////////
// MsgGOSRequest
CMsgGOSRequest::CMsgGOSRequest():CMessage(MSG_GOSREQUEST, sizeof(BYTE) + sizeof(WORD)){
setName("MsgGOSRequest");
}
CMsgGOSRequest::CMsgGOSRequest(BYTE requestType,WORD objectId):CMessage(MSG_GOSREQUEST, sizeof(BYTE) + sizeof(WORD)){
setName("MsgGOSRequest");
writeByte(1,requestType);
writeWord(2,objectId);
}
BYTE CMsgGOSRequest::getRequestType(){
return readByte(1);
}
WORD CMsgGOSRequest::getObjectId(){
return readWord(2);
}
///////////////////////////////////////////////////////////////////////////////
// MsgGeometry
CMsgGeometry::CMsgGeometry():CMsgVarLength(MSG_GEOMETRY){
setName("MsgGeometry");
}
#define HEADSIZE (sizeof(DWORD)+sizeof(WORD)*4)
#define VERTEXSIZE (3*sizeof(DWORD))
#define NORMALSIZE (3*sizeof(DWORD))
#define TEXCOORDSIZE (2*sizeof(DWORD))
#define POLYGONHEADSIZE (sizeof(DWORD)+4*sizeof(WORD))
CMsgGeometry::CMsgGeometry(CGeometry & geometry):CMsgVarLength(MSG_GEOMETRY){
setName("MsgGeometry");
WORD numV,numN,numTC,numP;
int type,materialId,numVI,numNI,numTCI;
DWORD size = sizeof(DWORD)+sizeof(WORD); // GeometryId + NumSubObjects
WORD numSubObjects = 0;
// Calculate size
CGeometry * geo = &geometry;
while (geo != NULL){
numSubObjects++;
size += HEADSIZE;
numV = geo->getNumVertices();
numN = geo->getNumNormals();
numTC = geo->getNumTexCoords();
numP = geo->getNumPolygons();
size += numV*VERTEXSIZE+numN*NORMALSIZE+numTC*TEXCOORDSIZE;
while (numP-- > 0){
size += POLYGONHEADSIZE;
CPolygon * poly = geo->getPolygon(numP);
poly->get(&type,&materialId,&numVI,&numNI,&numTCI);
size += (numVI + numNI + numTCI)*sizeof(WORD);
}
geo = geo->getNext();
}
// Then the size is known
setBodyLength(size);
cdebug << "Geometry: size " << size << "\n";
// Write geometry
writeDWord(getLength(),geometry.getId());
writeWord(MSGCURRPOS,numSubObjects);
geo = &geometry;
while (geo != NULL){
numV = geo->getNumVertices();
numN = geo->getNumNormals();
numTC = geo->getNumTexCoords();
numP = geo->getNumPolygons();
// Write geometry head
writeWord(MSGCURRPOS,numV);
writeWord(MSGCURRPOS,numN);
writeWord(MSGCURRPOS,numTC);
writeWord(MSGCURRPOS,numP);
writeDWord(MSGCURRPOS,geo->getSubId());
// Write geometry body
// Vertices
while (numV-- > 0){
CVertex * vertex = geo->getVertex(numV);
writeDouble(MSGCURRPOS,vertex->getZ());
writeDouble(MSGCURRPOS,vertex->getY());
writeDouble(MSGCURRPOS,vertex->getX());
}
// Normals
while (numN-- > 0){
CNormal * normal = geo->getNormal(numN);
writeDouble(MSGCURRPOS,normal->getZ());
writeDouble(MSGCURRPOS,normal->getY());
writeDouble(MSGCURRPOS,normal->getX());
}
// TexCoords
while (numTC-- > 0){
CTexCoord * texCoord = geo->getTexCoord(numTC);
writeDouble(MSGCURRPOS,texCoord->getV());
writeDouble(MSGCURRPOS,texCoord->getU());
}
// Polygons
while (numP-- > 0){
CPolygon * poly = geo->getPolygon(numP);
// Write polygon head
poly->get(&type,&materialId,&numVI,&numNI,&numTCI);
writeDWord(MSGCURRPOS,materialId);
writeWord(MSGCURRPOS,type);
writeWord(MSGCURRPOS,numVI);
writeWord(MSGCURRPOS,numNI);
writeWord(MSGCURRPOS,numTCI);
// Write polygon body
// Vertex index list
while (numVI-- > 0){
writeWord(MSGCURRPOS,poly->getVertexIndex(numVI));
}
// Normal index list
while (numNI-- > 0){
writeWord(MSGCURRPOS,poly->getNormalIndex(numNI));
}
// TexCoord index list
while (numTCI-- > 0){
writeWord(MSGCURRPOS,poly->getTexCoordIndex(numTCI));
}
}
geo = geo->getNext();
}
}
DWORD CMsgGeometry::getGeometryId(){
return readDWord(getLength());
}
CGeometry* CMsgGeometry::getGeometry(){
// cdebug << "CMsgGeometry::getGeometry: Not impl.!\n";
CGeometry *geo = NULL;
// Set the current read pointer in correct position
DWORD geometryId = getGeometryId();
// Get number of subobjects and read them
WORD numSubObjects = readWord(MSGCURRPOS);
while (numSubObjects-- > 0){
// Read geometry head and create geometry
WORD numV = readWord(MSGCURRPOS);
WORD numN = readWord(MSGCURRPOS);
WORD numTC = readWord(MSGCURRPOS);
WORD numP = readWord(MSGCURRPOS);
CGeometry * newgeo = newGeometry(geometryId,numV,numN,numTC,numP);
newgeo->setNext(geo);
geo = newgeo;
geo->setSubId(readDWord(MSGCURRPOS));
// Read geometry body
// Vertices
while (numV-- > 0){
geo->setVertex(numV,readDouble(MSGCURRPOS),readDouble(MSGCURRPOS),readDouble(MSGCURRPOS));
}
// Normals
while (numN-- > 0){
geo->setNormal(numN,readDouble(MSGCURRPOS),readDouble(MSGCURRPOS),readDouble(MSGCURRPOS));
}
// TexCoords
while (numTC-- > 0){
geo->setTexCoord(numTC,readDouble(MSGCURRPOS),readDouble(MSGCURRPOS));
}
// Polygons
while (numP-- > 0){
int type,materialId,numVI,numNI,numTCI;
// Read polygon head
materialId = readDWord(MSGCURRPOS);
type = readWord(MSGCURRPOS);
numVI = readWord(MSGCURRPOS);
numNI = readWord(MSGCURRPOS);
numTCI = readWord(MSGCURRPOS);
CPolygon * poly = new CPolygon(type,materialId,numVI,numNI,numTCI);
// Read polygon body
// Read vertex index list
while (numVI-- > 0){
poly->setVertexIndex(numVI,readWord(MSGCURRPOS));
}
// Read normal index list
while (numNI-- > 0){
poly->setNormalIndex(numNI,readWord(MSGCURRPOS));
}
// Read texCoord index list
while (numTCI-- > 0){
poly->setTexCoordIndex(numTCI,readWord(MSGCURRPOS));
}
geo->setPolygon(numP,poly);
}
}
return geo;
}
CGeometry * CMsgGeometry::newGeometry(int geometryId, int numVertices,
int numNormals, int numTexCoords, int numPolygons){
return new CGeometry(geometryId,numVertices,numNormals,
numTexCoords,numPolygons);
}
///////////////////////////////////////////////////////////////////////////////
// MsgMaterial
CMsgMaterial::CMsgMaterial():CMessage(MSG_MATERIAL,sizeof(WORD)*2+4*4+1){
setName("MsgMaterial");
}
CMsgMaterial::CMsgMaterial(CMaterial & material):CMessage(MSG_MATERIAL,sizeof(WORD)*2+4*4+1){
cdebug << "CMegsMaterial\n";
setName("MsgMaterial");
writeWord(1,material.getId());
writeWord(3,material.getTextureId());
for (int ii = 0; ii < 4 ; ii++){
writeByte(5+ii,material.getAmbientByte(ii));
writeByte(9+ii,material.getDiffuseByte(ii));
writeByte(13+ii,material.getSpecularByte(ii));
writeByte(17+ii,material.getEmissionByte(ii));
}
writeByte(21,material.getShininessByte());
}
int CMsgMaterial::getMaterialId(){
return (short int)readWord(1);
}
int CMsgMaterial::getTextureId(){
return (short int)readWord(3);
}
BYTE CMsgMaterial::getAmbientByte(int num){
return readByte(5+num);
}
BYTE CMsgMaterial::getDiffuseByte(int num){
return readByte(9+num);
}
BYTE CMsgMaterial::getSpecularByte(int num){
return readByte(13+num);
}
BYTE CMsgMaterial::getEmissionByte(int num){
return readByte(17+num);
}
BYTE CMsgMaterial::getShininessByte(){
return readByte(21);
}
CMaterial* CMsgMaterial::getMaterial(){
CMaterial * material = newMaterial(getMaterialId());
material->setTextureId(getTextureId());
for (int ii = 0; ii < 4; ii++){
material->setAmbient(ii,getAmbientByte(ii));
material->setDiffuse(ii,getDiffuseByte(ii));
material->setSpecular(ii,getSpecularByte(ii));
material->setEmission(ii,getEmissionByte(ii));
}
material->setShininess(getShininessByte());
return material;
}
CMaterial * CMsgMaterial::newMaterial(int materialId){
return new CMaterial(materialId);
}
///////////////////////////////////////////////////////////////////////////////
// MsgTexture
CMsgTexture::CMsgTexture():CMsgVarLength(MSG_TEXTURE){
setName("MsgTexture");
}
CMsgTexture::CMsgTexture(CTexture & texture):CMsgVarLength(MSG_TEXTURE){
setName("MsgTexture");
CTextureMap * map = texture.getTextureMap();
setBodyLength(sizeof(WORD)*3 + map->getWidth()*map->getHeight()*sizeof(DWORD));
writeWord(getLength(),texture.getId());
writeWord(getLength()+2,map->getWidth());
writeWord(getLength()+4,map->getHeight());
writeBuf(getLength()+6,map->getData(),map->getWidth()*map->getHeight()*sizeof(DWORD));
}
WORD CMsgTexture::getTextureId(){
return readWord(getLength());
}
WORD CMsgTexture::getMapWidth(){
return readWord(getLength()+2);
}
WORD CMsgTexture::getMapHeight(){
return readWord(getLength()+4);
}
CTexture * CMsgTexture::getTexture(){
CTexture * texture = newTexture(getTextureId());
WORD width = getMapWidth();
WORD height = getMapHeight();
BYTE * data = (BYTE*)malloc(width*height*sizeof(DWORD));
readBuf(getLength()+6,data,width*height*sizeof(DWORD));
CTextureMap * map = new CTextureMap(width,height,data);
texture->setTextureMap(map);
return texture;
}
CTexture * CMsgTexture::newTexture(int textureId){
return new CTexture(textureId);
}